Пример #1
0
async def add_emoji(client,
                    event,
                    emoji: ('str', 'The emoji to add.'),
                    name: ('str',
                           'Custom name to add the emoji with.') = None):
    """Adds an emoji to the guild."""
    if not client.is_owner(event.user):
        abort('Owner only!')

    emoji = parse_emoji(emoji)
    if emoji is None:
        abort('That\'s not an emoji.')

    if emoji.is_unicode_emoji():
        abort('Cannot add unicode emojis')

    if name is None:
        name = emoji.name
    else:
        if len(name) > 32:
            abort('Name length can be max 32.')

    embed = Embed('Are you sure to add this emoji?').add_field(
        'Name:', name).add_image(emoji.url)

    message = yield InteractionResponse(embed=embed,
                                        components=ADD_EMOJI_COMPONENTS)

    try:
        component_interaction = await wait_for_component_interaction(
            message,
            timeout=300.0,
            check=functools.partial(check_is_user_same, event.user))

    except TimeoutError:
        component_interaction = None
        cancelled = True
    else:
        if component_interaction.interaction == ADD_EMOJI_BUTTON_CANCEL:
            cancelled = True
        else:
            cancelled = False

    if cancelled:
        embed.title = 'Adding emoji has been cancelled.'
    else:
        embed.title = 'Emoji has been added!'

        async with client.http.get(emoji.url) as response:
            emoji_data = await response.read()

        await client.emoji_create(event.guild, name, emoji_data)

    yield InteractionResponse(embed=embed,
                              components=None,
                              message=message,
                              event=component_interaction)
Пример #2
0
async def configured_show_emoji(emoji):
    """Shows the given custom emoji."""
    emoji = parse_emoji(emoji)
    if emoji is None:
        return 'That\'s not an emoji.'
    
    if emoji.is_unicode_emoji():
        return 'That\' an unicode emoji, cannot link it.'
    
    return f'**Name:** {emoji:e} **Link:** {emoji.url}'
Пример #3
0
async def show_emoji(
        client,
        event,
        emoji: ('str', 'Yes?'),
):
    """Shows the given custom emoji."""
    emoji = parse_emoji(emoji)
    if emoji is None:
        return 'That\'s not an emoji.'

    if emoji.is_unicode_emoji():
        return 'That\' an unicode emoji, cannot link it.'

    return f'**Name:** {emoji:e} **Link:** {emoji.url}'
Пример #4
0
async def edit_(
    client,
    event,
    sticker_name: ('str', 'The sticker\'s name to delete', 'sticker'),
    new_name: (
        'str',
        'New name for the sticker',
    ) = None,
    new_emoji_value: (str, 'Emoji representation of the sticker.',
                      'new_emoji') = None,
    new_description: (str, 'Description for the sticker.') = None,
):
    """Edits the given sticker. (You must have emoji-council role)"""
    if not event.user.has_role(ROLE__NEKO_DUNGEON__EMOJI_MANAGER):
        abort(
            f'You must have {ROLE__NEKO_DUNGEON__EMOJI_MANAGER:m} role to invoke this command.'
        )

    sticker = event.guild.get_sticker_like(sticker_name)
    if (sticker is None):
        abort(f'No sticker matched the given name: {sticker_name!r}.')

    anything_to_edit = False

    if (new_name is not None):
        if (sticker.name != new_name):
            name_length = len(new_name)
            if (name_length < 2) or (name_length > 32):
                abort(
                    f'Sticker name\'s length can be in range [2:32], got {name_length!r}, {new_name!r}.'
                )

            anything_to_edit = True
        else:
            new_name = None

    if (new_emoji_value is not None):
        new_emoji = parse_emoji(new_emoji_value)

        if new_emoji is None:
            abort(f'{new_emoji_value} cannot be interpreted as an emoji.')

        if new_emoji.is_custom_emoji():
            abort(f'Only unicode can be used, got {new_emoji:e}')

        tags = sticker.tags
        if (tags is None) or (len(tags) != 1) or (next(iter(tags)) !=
                                                  new_emoji.name):
            anything_to_edit = True
        else:
            new_emoji = None
    else:
        new_emoji = None

    if (new_description is not None):
        description_length = len(new_description)
        if (description_length > 100):
            abort(
                f'Sticker description\'s length can be in range [0:100], got {description_length!r}, '
                f'{new_description!r}.')

        if (sticker.description != new_description):
            anything_to_edit = True
        else:
            new_description = None

    if not anything_to_edit:
        abort('No differences were provided.')

    embed = Embed('Confirmation',
                  f'Are you sure to edit {sticker.name!r} sticker?')

    if (new_name is not None):
        embed.add_field('Name', f'{sticker.name} -> {new_name}')

    if (new_emoji is not None):
        embed.add_field('Tags',
                        f'{", ".join(sticker.tags)} -> {new_emoji.name}')

    if (new_description is not None):
        embed.add_field('Description',
                        f'{sticker.description} -> {new_description}')

    message = yield InteractionResponse(embed=embed,
                                        components=STICKER_EDIT_COMPONENTS,
                                        allowed_mentions=None)

    try:
        component_interaction = await wait_for_component_interaction(
            message,
            timeout=300.0,
            check=partial_func(check_sticker_editor, event.user))

    except TimeoutError:
        embed.title = 'Timeout'
        embed.description = f'Sticker {sticker.name!r} was not edited.'

        # Edit the source message with the source interaction
        yield InteractionResponse(embed=embed,
                                  components=None,
                                  allowed_mentions=None,
                                  message=message)
        return

    if component_interaction.interaction == STICKER_EDIT_BUTTON_CANCEL:
        embed.title = 'Cancelled'
        embed.description = f'Sticker {sticker.name!r} was not edited.'

        # Edit the source message with the component interaction
        yield InteractionResponse(embed=embed,
                                  components=None,
                                  allowed_mentions=None,
                                  event=component_interaction)
        return

    # Acknowledge the event
    await client.interaction_component_acknowledge(component_interaction)

    kwargs = {}

    if (new_name is not None):
        kwargs['name'] = new_name

    if (new_emoji is not None):
        kwargs['emoji_representation'] = new_emoji

    if (new_description is not None):
        kwargs['description'] = new_description

    try:
        await client.sticker_guild_edit(sticker, **kwargs)
    except ConnectionError:
        # No internet, let it be
        return

    except DiscordException as err:
        if err.code == ERROR_CODES.unknown_sticker:
            failure = False
        else:
            failure = True
            embed.title = 'Failure'
            embed.description = repr(err)
    else:
        failure = False

    if not failure:
        embed.title = 'Success'
        embed.description = f'Sticker {sticker.name!r} has been successfully edited.'

    # Edit the source message
    yield InteractionResponse(embed=embed, message=message, components=None)
Пример #5
0
async def add_(
    client,
    event,
    link: (str, 'Link to the sticker to add'),
    name: (str, 'The sticker\'s name.'),
    emoji_value: (str, 'Emoji representation of the sticker.', 'emoji'),
    description: (str, 'Description for the sticker.') = None,
):
    """Adds a sticker to the guild. (You must have emoji-council role)"""
    if not event.user.has_role(ROLE__NEKO_DUNGEON__EMOJI_MANAGER):
        abort(
            f'You must have {ROLE__NEKO_DUNGEON__EMOJI_MANAGER:m} role to invoke this command.'
        )

    name_length = len(name)
    if (name_length < 2) or (name_length > 32):
        abort(
            f'Sticker name\'s length can be in range [2:32], got {name_length!r}, {name!r}.'
        )

    emoji = parse_emoji(emoji_value)

    if emoji is None:
        abort(f'{emoji_value} cannot be interpreted as an emoji.')

    if emoji.is_custom_emoji():
        abort(f'Only unicode can be used, got {emoji:e}')

    if (description is not None):
        description_length = len(description)
        if (description_length > 100):
            abort(
                f'Sticker description\'s length can be in range [0:100], got {description_length!r}, '
                f'{description!r}.')

    if not is_url(link):
        abort(f'The given link is invalid, got {link!r}.')

    yield

    while True:
        try:
            async with client.http.get(link) as response:
                response_status = response.status
                if response_status != 200:
                    response_reason = response.reason
                    if response_reason is None:
                        error_message = f'Request failed: {response_status}'
                    else:
                        error_message = f'Request failed: {response_status} {response_reason}'

                    break

                future = Task(response.read(), KOKORO)
                future_or_timeout(future, 15.0)
                image = await future

        except ConnectionError as err:
            error_message = f'Getting image failed: {err.args[0]}'
            break

        except TimeoutError as err:
            error_message = 'Timeout (15s) occurred meanwhile trying to read the response.'
            break

        except OSError as err:
            error_message = f'Getting image failed: {err.strerror}'
            break

        try:
            sticker = await client.sticker_guild_create(
                event.guild, name, image, emoji, description)
        except ConnectionError as err:
            return

        except DiscordException as err:
            error_message = repr(err)
            break

        except ValueError as err:
            error_message = err.args[0]
            break

        yield 'The sticker has been successfully created'
        await client.message_create(event.channel, sticker=sticker)
        return

    yield error_message
Пример #6
0
async def raffle(client, event,
        message : ('str', 'The message to raffle from'),
        emoji : ('str', 'The reactor users to raffle from.'),
            ):
    """Raffles an user out who reacted on a message."""
    guild = event.guild
    if (guild is None) or (guild not in client.guild_profiles):
        abort('The command unavailable in guilds, where the application\'s bot is not in.')
    
    emoji = parse_emoji(emoji)
    if emoji is None:
        abort('That\'s not an emoji.')
    
    message_reference = parse_message_reference(message)
    if message_reference is None:
        abort('Could not identify the message.')
    
    guild_id, channel_id, message_id = message_reference
    try:
        message = MESSAGES[message_id]
    except KeyError:
        if channel_id:
            try:
                channel = CHANNELS[channel_id]
            except KeyError:
                abort('I have no access to the channel.')
                return
        else:
            channel = event.channel
        
        if not channel.cached_permissions_for(client).can_read_message_history:
            abort('I have no permission to get that message.')
        
        yield
        
        try:
            message = client.message_get(channel, message_id)
        except ConnectionError:
            # No internet
            return
        except DiscordException as err:
            if err.code in (
                    ERROR_CODES.unknown_channel, # message deleted
                    ERROR_CODES.unknown_message, # channel deleted
                        ):
                # The message is already deleted.
                abort('The referenced message is already yeeted.')
                return
            
            if err.code == ERROR_CODES.missing_access: # client removed
                # This is not nice.
                return
            
            if err.code == ERROR_CODES.missing_permissions: # permissions changed meanwhile
                abort('I have no permission to get that message.')
                return
            
            raise
    
    yield
    
    users = await client.reaction_user_get_all(message)
    
    if users:
        user = choice(users)
        content = user.mention
    else:
        content = 'Could not find any user.'
    
    yield content
    return
Пример #7
0
def check_message_for_emoji(message):
    parsed = parse_emoji(message.content)
    if parsed is None:
        return False

    return parsed
Пример #8
0
async def emoji_role(
    client,
    event,
    emoji: ('str', 'Select the emoji to bind to roles.'),
    role_1: ('role', 'Select a role.') = None,
    role_2: ('role', 'Double role!') = None,
    role_3: ('role', 'Triple role!') = None,
    role_4: ('role', 'Quadra role!') = None,
    role_5: ('role', 'Penta role!') = None,
    role_6: ('role', 'Epic!') = None,
    role_7: ('role', 'Legendary!') = None,
    role_8: ('role', 'Mythical!') = None,
    role_9: ('role', 'Lunatic!') = None,
):
    """Binds the given emoji to the selected roles. You must have administrator permission."""
    guild = event.guild
    if guild is None:
        abort('Guild only command.')

    if guild not in client.guild_profiles:
        abort('I must be in the guild to do this.')

    if not event.user_permissions.can_ban_users:
        abort('You must have ban users permission to use this command.')

    permissions = event.channel.cached_permissions_for(client)
    if (not permissions.can_manage_emojis_and_stickers) or (
            not permissions.can_add_reactions):
        abort(
            f'{client.name_at(guild)} requires manage emojis and add reactions permissions for this command.'
        )

    emoji = parse_emoji(emoji)
    if emoji is None:
        abort('That\'s not an emoji.')

    if emoji.is_unicode_emoji():
        abort('Cannot edit unicode emojis.')

    emoji_guild = emoji.guild
    if (emoji_guild is None) or (emoji_guild is not guild):
        abort('Wont edit emojis from an other guild.')

    roles = set()
    for role in role_1, role_2, role_3, role_4, role_5, role_6, role_7, role_8, role_9:
        if role is None:
            continue

        if role.guild is guild:
            roles.add(role)
            continue

        abort(f'Role {role.name}, [{role.id}] is bound to an other guild.')

    roles = sorted(roles)
    roles_ = emoji.roles

    embed = Embed(f'Edit {emoji.name}\'s roles').add_thumbnail(emoji.url)

    if (roles_ is None) or (not roles_):
        role_text = '*none*'
    else:
        role_text = ', '.join([role.mention for role in roles_])

    embed.add_field('Before:', role_text)

    if (not roles):
        role_text = '*none*'
    else:
        role_text = ', '.join([role.mention for role in roles])

    embed.add_field('After:', role_text)

    message = yield InteractionResponse(embed=embed,
                                        components=EMOJI_ROLE_COMPONENTS)

    try:
        component_interaction = await wait_for_component_interaction(
            message, timeout=300.0, check=role_emoji_checker)

    except TimeoutError:
        component_interaction = None
        cancelled = True
    else:
        if component_interaction.interaction == EMOJI_ROLE_BUTTON_CANCEL:
            cancelled = True
        else:
            cancelled = False

    if cancelled:
        description = 'Emoji edit cancelled.'
    else:
        try:
            await client.emoji_edit(emoji, roles=roles)
        except DiscordException as err:
            description = repr(err)
        else:
            description = 'Emoji edited successfully.'

    embed = Embed(f'Edit {emoji.name}\'s roles',
                  description).add_thumbnail(emoji.url)
    yield InteractionResponse(embed=embed,
                              components=None,
                              message=message,
                              event=component_interaction)
Пример #9
0
async def emoji_top(
        raw_emoji: ('str', 'Pick an emoji', 'emoji'),
        months: (range(1, 13), 'The months to get') = 1,
        action_type: (EMOJI_COMMAND_ACTION_TYPES, ('Choose emoji action type')) = EMOJI_COMMAND_ACTION_TYPE_ALL,
            ):
    """List the users using the given emoji the most."""
    emoji = parse_emoji(raw_emoji)
    if emoji is None:
        emoji = GUILD__NEKO_DUNGEON.get_emoji_like(raw_emoji)
        if emoji is None:
            abort(f'`{raw_emoji}` is not an emoji.')
    else:
        if emoji.is_unicode_emoji():
            abort(f'{emoji:e} is an unicode emoji. Please give custom.')
        
        if emoji.guild is not GUILD__NEKO_DUNGEON:
            abort(f'{emoji:e} is bound to an other guild.')
    
    async with DB_ENGINE.connect() as connector:
        statement = (
            select([
            emoji_counter_model.user_id,
            alchemy_function.count(emoji_counter_model.user_id).label('total'),
            ]). \
            where(and_(
                emoji_counter_model.emoji_id == emoji.id,
                emoji_counter_model.timestamp > datetime.utcnow()-RELATIVE_MONTH*months,
            )). \
            limit(30). \
            group_by(emoji_counter_model.user_id). \
            order_by(desc('total'))
        )
        
        if (action_type != EMOJI_COMMAND_ACTION_TYPE_ALL):
            statement = statement.where(emoji_counter_model.action_type==action_type)
        
        response = await connector.execute(statement)
        results = await response.fetchall()
    
    
    if results:
        index = 0
        limit = len(results)
        description_parts = []
        
        while True:
            user_id, count = results[index]
            
            index += 1
            
            try:
                user = USERS[user_id]
            except KeyError:
                continue
            
            try:
                guild_profile = user.guild_profiles[GUILD__NEKO_DUNGEON]
            except KeyError:
                nick = None
            else:
                nick = guild_profile.nick
            
            description_parts.append(str(index))
            description_parts.append('.: **')
            description_parts.append(str(count))
            description_parts.append('** x ')
            description_parts.append(user.full_name)
            if (nick is not None):
                description_parts.append(' *[')
                description_parts.append(nick)
                description_parts.append(']*')
            
            if index == limit:
                break
            
            description_parts.append('\n')
            continue
        
        description = ''.join(description_parts)
    else:
        description = '*No usages recorded*'
    
    
    return Embed(
        f'Top emoji users of {emoji.name}',
        description,
    ).add_thumbnail(emoji.url)