Exemplo n.º 1
0
async def _delete(ctx, t: Ticket):
    """ This is to delete a ticket. """

    utc = time.time()

    conf = Confirmation(ctx)
    await conf.confirm(ctx.translate("you are attempting to delete ticket [ticket]").format(t.id))

    if conf.confirmed:
        author = User.from_discord_user(ctx.author)

        t.state_enum = enums.State.DELETED
        t.deleted_by.add(author, properties={'UTC': utc})
        t.push()

        for resp in t.get_responses():
            resp.deleted = True
            resp.deleted_by.add(author, properties={'UTC': utc})

            resp.push()

        await conf.display(ctx.translate("ticket deleted"))

        if t.scope_enum == enums.Scope.CHANNEL:
            channel = t.channel
            if channel is not None:
                await channel.delete(reason=ctx.translate("ticket has been deleted"))

        await t.guild.log(ctx.translate("[user] deleted ticket [ticket]").format(ctx.author, t.id))

    else:
        await conf.display((ctx.translate("canceled")))
Exemplo n.º 2
0
async def on_member_join(member):
    db_guild = Guild.from_discord_guild(member.guild)
    db_user = User.from_discord_user(member)

    db_guild.joined_users.add(db_user, properties={'UTC': time.time()})

    db_guild.push()
Exemplo n.º 3
0
async def _create(ctx, t: Ticket, content: str):
    """ This is to create new responses/to answer tickets. """

    if t.scope_enum == enums.Scope.CHANNEL and ctx.channel != t.channel and not ctx.may_fully_access(
            t):
        await ctx.send(ctx.translate("the related ticket is channel scope"))
        return None

    elif t.scope_enum == enums.Scope.PRIVATE and not ctx.may_fully_access(t):
        await ctx.send(ctx.translate("this is a private ticket"))
        return None

    elif t.state_enum == enums.State.CLOSED:
        await ctx.send(ctx.translate("this ticket is closed"))
        return None

    if t.scope_enum == enums.Scope.PRIVATE:
        try:
            await ctx.message.delete()
        except discord.Forbidden:
            pass

    utc = time.time()

    resp = Response()

    author = User.from_discord_user(ctx.author)
    resp.created_by.add(author, properties={'UTC': utc})

    resp.located_on.add(ctx.db_guild)

    resp.refers_to.add(t)

    resp.content = escaped(content)

    resp.deleted = False
    resp.updated = utc

    highest_id = graph.run(
        "MATCH (r:Response)-[:REFERS_TO]->(t:Ticket {uuid: '%s'}) RETURN max(r.id)"
        % t.uuid).evaluate()
    if highest_id is None:
        highest_id = 0

    resp.id = highest_id + 1
    resp.uuid = uuid.uuid4().hex

    graph.create(resp)

    await ctx.send(ctx.translate("response created").format(resp.full_id))

    resp_msg = ctx.translate(
        "[user] just responded to your ticket [ticket]").format(
            ctx.author.name, ctx.author.discriminator, t.id)

    await notify_author(ctx, resp_msg, t, embed=response_embed(ctx, resp))
    await resp.guild.log(
        ctx.translate("[user] created response [response]").format(
            ctx.author, f"{resp.ticket.id}-{resp.id}"))
Exemplo n.º 4
0
async def _reopen(ctx, t: Ticket):
    """ This is to reopen a specific support ticket. """

    if t.state_enum != enums.State.CLOSED:
        await ctx.send(ctx.translate("this ticket is not closed"))
        return None

    utc = time.time()

    t.state = enums.State.REOPENED.value

    user = User.from_discord_user(ctx.author)
    t.reopened_by.add(user, properties={'UTC': utc})

    t.updated = utc

    graph.push(t)

    if t.scope_enum == enums.Scope.CHANNEL:
        category = t.guild.discord.get_channel(t.guild.ticket_category)

        channel = await t.guild.discord.create_text_channel(
            str(t.id),
            overwrites={
                t.author.discord:
                discord.PermissionOverwrite(read_messages=True,
                                            send_messages=True)
            },
            category=category,
            reason=ctx.translate("channel-ticket has been reopened"))
        await channel.edit(topic=t.title, sync_permissions=True)

    await ctx.send(ctx.translate("ticket reopened"))

    if t.guild.channel != ctx.channel.id:
        await notify_ticket_authority(
            ctx,
            t,
            ctx.translate("[user] just reopened a ticket").format(
                ctx.author.mention),
            send_embed=True)

    await t.guild.log(
        ctx.translate("[user] reopened ticket [ticket]").format(
            ctx.author, t.id))
Exemplo n.º 5
0
async def on_member_update(before: Member, after: Member):
    if before.guild.id != CONFIG['home_guild']:
        return

    prime_roles = CONFIG['prime_roles']

    was_prime = any(r.id in prime_roles for r in before.roles)
    is_prime = any(r.id in prime_roles for r in after.roles)

    if was_prime == is_prime:
        return  # abort because nothing has changed

    db_user = User.from_discord_user(after)
    db_user.prime = is_prime  # update value
    db_user.push()

    logger.info(
        f"{'added' if is_prime else 'removed'} prime member: {db_user.id}")
Exemplo n.º 6
0
async def _close(ctx, t: Ticket, response=None):
    """ This is to close a specific support ticket. """

    if t.state_enum == enums.State.CLOSED:
        await ctx.send(ctx.translate('this ticket is already closed'))
        return None

    utc = time.time()

    t.state = enums.State.CLOSED.value

    user = User.from_discord_user(ctx.author)
    t.closed_by.add(user, properties={'UTC': utc})

    t.updated = utc

    graph.push(t)

    conf_msg = ctx.translate('ticket closed')
    close_msg = ctx.translate('[user] just closed ticket [ticket]').format(
        ctx.author.mention, t.id)

    if response is not None:
        close_msg += f"\n```{escaped(response)}```"

    send_success = await notify_author(ctx, close_msg, t)

    if send_success == 1:
        conf_msg += ctx.translate("ticket author doesn't allow dms")

    await ctx.send(conf_msg)

    if t.guild.channel != ctx.channel.id:
        await notify_ticket_authority(ctx, t, close_msg, send_embed=True)

    if t.scope_enum == enums.Scope.CHANNEL:
        channel = t.channel
        if channel is not None:
            await channel.delete(reason=ctx.translate("ticket has been closed")
                                 )

    await t.guild.log(
        ctx.translate("[user] closed ticket [ticket]").format(
            ctx.author, t.id))
Exemplo n.º 7
0
async def _delete(ctx, resp: Response):
    """ This is to delete a response. """

    utc = time.time()
    ticket = resp.ticket

    if not (ctx.author.id == resp.author.id or ctx.may_fully_access(ticket)):
        await ctx.send(
            ctx.translate("you are not allowed to perform this action"))
        return None

    resp.deleted = True
    resp.deleted_by.add(User.from_discord_user(ctx.author),
                        properties={'UTC': utc})

    resp.push()

    await ctx.send(ctx.translate("response deleted"))
    await resp.guild.log(
        ctx.translate("[user] deleted response [response]").format(
            ctx.author, f"{resp.ticket.id}-{resp.id}"))
Exemplo n.º 8
0
async def _create(ctx, title: str, description: str="", scope: Scope=None):
    """ This is to create a support ticket. """

    guild = ctx.db_guild

    t = Ticket(ctx=ctx)

    if len(title) > enums.TitleLength.MAX:
        await ctx.send(ctx.translate("title too long").format(enums.TitleLength.MAX.value, len(title)))

    elif len(title) < enums.TitleLength.MIN:
        await ctx.send(ctx.translate("title too short").format(enums.TitleLength.MIN.value, len(title)))

    else:
        utc = time.time()

        t.title = escaped(title)

        t.description = escaped(description)

        t.state = enums.State.OPEN.value
        t.updated = utc

        author = User.from_discord_user(ctx.author)
        t.created_by.add(author, properties={'UTC': utc})

        t.located_on.add(guild)

        if scope is None:
            scope = t.guild.default_scope

        t.scope = scope

        highest_id = graph.run(
            "MATCH (t:Ticket)-[:TICKET_LOCATED_ON]->(g:Guild {id: %i}) RETURN max(t.id)" % guild.id
        ).evaluate()

        if highest_id is None:
            highest_id = 0

        t.id = highest_id + 1
        t.uuid = uuid.uuid4().hex

        responsible_user = None

        if t.guild.auto_assigning:
            support_role: discord.Role = t.guild.discord.get_role(t.guild.support_role)

            if support_role is not None:
                responsible_user = random.choice(support_role.members)
                responsible_user = User.from_discord_user(responsible_user, ctx=ctx)

                t.assigned_to.add(responsible_user)

        graph.create(t)

        send_invokation_channel = False

        # create text channel (and category if not exist yet) for channel ticket
        if t.scope_enum == enums.Scope.CHANNEL:
            supporter = discord.utils.get(guild.discord.roles, id=guild.support_role)
            if supporter is None:
                supporter = guild.discord.owner

            overwrites = {
                guild.discord.default_role:
                    discord.PermissionOverwrite(read_messages=False),
                guild.discord.me:
                    discord.PermissionOverwrite(read_messages=True,
                                                send_messages=True,
                                                manage_messages=True,
                                                add_reactions=True,
                                                manage_channels=True),
                supporter:
                    discord.PermissionOverwrite(read_messages=True,
                                                send_messages=True)
            }

            if guild.ticket_category is None:
                category = await guild.discord.create_category(
                    ctx.translate("support tickets"),
                    overwrites=overwrites,
                    reason=ctx.translate("first channel-ticket has been created")
                )
                guild.ticket_category = category.id
                guild.push()
            else:
                category = guild.discord.get_channel(guild.ticket_category)

            overwrites[author.discord] = discord.PermissionOverwrite(read_messages=True, send_messages=True)

            channel = await guild.discord.create_text_channel(
                str(t.id),
                overwrites=overwrites,
                category=category,
                reason=ctx.translate("new channel-ticket has been created")
            )
            await channel.edit(
                topic=t.title
            )
            await channel.send(embed=ticket_embed(ctx, t))
            format_id = channel.mention

        elif t.scope_enum == enums.Scope.PRIVATE:
            try:
                await ctx.message.delete()
            except discord.Forbidden:
                pass

            format_id = t.id

        else:
            send_invokation_channel = True
            format_id = t.id

        msg = ctx.translate("ticket created").format(format_id)

        try:
            await ctx.author.send(ctx.translate("your ticket has been created").format(t.id, guild.discord.name))
            dm_allowed = True
        except commands.BotMissingPermissions:
            dm_allowed = False

        if not dm_allowed:
            msg += '\n' + ctx.translate("please allow receiving dms")

        if responsible_user is not None:
            msg += '\n\n' + ctx.translate("ticket auto-assigned to [user]").format(responsible_user.discord)

        await ctx.send(msg)

        if t.guild.channel != ctx.channel.id:
            new_ticket_msg = ctx.translate("new ticket")
            if send_invokation_channel:
                new_ticket_msg += ctx.translate("created in [channel]").format(ctx.channel.mention)

            await notify_ticket_authority(ctx, t, new_ticket_msg, send_embed=True)

        await t.guild.log(ctx.translate("[user] created ticket [ticket]").format(ctx.author, t.id))