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)
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}'
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}'
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)
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
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
def check_message_for_emoji(message): parsed = parse_emoji(message.content) if parsed is None: return False return parsed
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)
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)