def make_urban_embed(d: UrbanDefinition) -> discord.Embed: """ Makes a ``discord.Embed`` from an ``UrbanDefinition``. """ embed = discord.Embed(title=d.word, description=utils.truncate(d.definition, 2048)) if d.example: embed.add_field(name='Example', value=utils.truncate(d.example, 1024), inline=False) embed.add_field(name='\N{THUMBS UP SIGN}', value=utils.commas(d.thumbs_up)) embed.add_field(name='\N{THUMBS DOWN SIGN}', value=utils.commas(d.thumbs_down)) return embed
def create_post_embed(post) -> discord.Embed: endings = ('.gif', '.jpeg', '.png', '.jpg', '.webp') is_image = not post.is_self and any( post.url.endswith(ending) for ending in endings) embed = discord.Embed(title=utils.truncate(post.title, 256), url=post.url, description=utils.truncate(post.selftext, 2048)) embed.set_author(name='/r/%s \N{EM DASH} /u/%s' % (post.subreddit, post.author)) if is_image: embed.set_image(url=post.url) return embed
def embed(self) -> Embed: """Makes a :class:``discord.Embed`` from an ``UrbanDefinition``.""" embed = Embed(title=self.word, description=utils.truncate(self.definition, 2048)) if self.example: embed.add_field(name='Example', value=utils.truncate(self.example, 1024), inline=False) embed.add_field(name='\N{THUMBS UP SIGN}', value=utils.commas(self.thumbs_up)) embed.add_field(name='\N{THUMBS DOWN SIGN}', value=utils.commas(self.thumbs_down)) return embed
async def on_message_delete(self, msg: discord.Message): # don't handle message deletion elsewhere if not isinstance(msg.channel, discord.TextChannel): return # do not process bulk message deletes, or message censors (the censor cog does that already) # TODO: do this but cleanly, maybe paste website? if await self.bulk_deletes.check_batch( msg.id) or await self.censored_messages.check(message_id=msg.id ): return # if this channel isn't publicly visible or deletes shouldn't be tracked, bail if (not await is_publicly_visible(self.bot, msg.channel) or await self.bot.config_is_set(msg.guild, 'modlog_notrack_deletes')): return # if the author was a bot and we aren't configured to allow bots, return if msg.author.bot and not await self.bot.config_is_set( msg.guild, 'modlog_filter_allow_bot'): return # format attachment list attachments = 'no attachments' if not msg.attachments else f'{len(msg.attachments)} attachment(s): ' + \ ', '.join(f'{a.filename}, {filesize(a.size)}' for a in msg.attachments) content = utils.prevent_codeblock_breakout( utils.truncate(msg.content, 1500)) fmt = ( f'\U0001f6ae Message by {describe(msg.author)} deleted in {msg.channel.mention}: ```\n{content}\n``` ' f'({attachments}, {len(msg.embeds)} embed(s)') await self.log(msg.guild, fmt)
async def on_message_delete(self, msg: discord.Message): # no, i can't use and if msg.author.bot: if not await self.bot.config_is_set(msg.guild, 'modlog_filter_allow_bot'): return # no it's not a typo delet_emote = '<:DeletThis:213623030197256203>' embed = self._make_modlog_embed(title=f'{delet_emote} Message deleted') # fields embed.add_field(name='Author', value=self._member_repr(msg.author)) embed.add_field(name='Channel', value=f'{msg.channel.mention} {msg.channel.name}') embed.add_field(name='ID', value=msg.id) if msg.attachments: def description(a): if "width" in a: # is a picture after = f'({a["width"]}×{a["height"]})' else: # is a file after = f'({a["size"]} bytes)' return f'`{a["filename"]} {after}`' atts = [description(a) for a in msg.attachments] embed.add_field(name='Attachments', value=', '.join(atts)) # set message content content = utils.truncate(msg.content, 1500) embed.description = content await self.bot.send_modlog(msg.guild, embed=embed)
async def on_message_edit(self, before: discord.Message, after: discord.Message): # if message author was a bot, or the embeds were added by discord, bail if before.author.bot or before.content == after.content: return # if this channel isn't publicly visible or we aren't tracking edits, bail if (not await is_publicly_visible(self.bot, before.channel) or await self.bot.config_is_set(before.guild, 'modlog_notrack_edits')): return # truncate :blobsweats: m_before = utils.prevent_codeblock_breakout( utils.truncate(before.content, 900)) m_after = utils.prevent_codeblock_breakout( utils.truncate(after.content, 900)) # format fmt = ( f'\N{MEMO} Message by {describe(before.author)} in {describe(before.channel, mention=True)} edited: ' f'```\n{m_before}\n``` to ```\n{m_after}\n```') await self.log(before.guild, fmt)
def _make_anime_embed(self, anime: Anime) -> discord.Embed: embed = discord.Embed(title=anime.title) not_airing = anime.end_date == '0000-00-00' or anime.status != 'Finished Airing' embed.add_field(name='Score', value=anime.score) embed.add_field(name='Episodes', value=anime.episodes) embed.add_field(name='Status', value=anime.status) if not_airing: embed.add_field(name='Start date', value=anime.start_date) else: aired_value = f'{anime.start_date} - {anime.end_date}' if anime.start_date == anime.end_date: aired_value = anime.start_date + ' (one day)' embed.add_field(name='Aired', value=aired_value) synopsis = html.unescape(anime.synopsis).replace('<br />', '\n')[:2500] embed.add_field(name='Synopsis', value=utils.truncate(synopsis, 1000), inline=False) embed.set_thumbnail(url=anime.image) return embed
def format_record(r, cmd_flags): """ Formats a messages row. """ flags = {'E': r['edited'], 'D': r['deleted']} # render the flags flags_rendered = ''.join(fl for fl, value in flags.items() if value) # empty out of we are hiding flags, else pad it out flags_rendered = '' if 'hide-flags' in cmd_flags else f'{flags_rendered: <{len(flags)}} ' # decide which content to show content = r['new_content'] or r['original_content'] # override on show-original if 'show-original' in cmd_flags: content = r['original_content'] # truncate content = utils.truncate(content, 1500) created_at = '' if 'hide-dates' in cmd_flags else f'{r["created_at"].strftime("%y-%m-%d %H:%M")} ' message_id = f"{r['message_id']} " if 'show-ids' in cmd_flags else '' attachments = f" {r['attachments']}" if 'show-attachments' in cmd_flags else '' return f'{flags_rendered}{message_id}{created_at}{content}{attachments}'
async def define(self, ctx, *, word: str): """ Defines a word. """ api_base = 'https://od-api.oxforddictionaries.com/api/v1' # request headers oxford = ctx.bot.cfg['credentials'].get('oxford', {}) if not oxford: return await ctx.send('My bot owner hasn\'t set that up.') headers = { 'app_id': oxford['application_id'], 'app_key': oxford['application_key'] } search_params = {'q': word, 'limit': 3} # search word async with ctx.bot.session.get(api_base + '/search/en', params=search_params, headers=headers) as resp: results = (await resp.json())['results'] if not results: # empty return await ctx.send('Word not found.') word_id = results[0]['id'] # get word definition async with ctx.bot.session.get( api_base + f'/entries/en/{utils.urlescape(word_id)}', headers=headers) as resp: # grab results try: results = (await resp.json())['results'] except aiohttp.ClientError: return await ctx.send( 'Hmm, I couldn\'t decode the results from Oxford.') lexical = results[0]['lexicalEntries'][0] if 'pronunciations' in lexical: pronun = ','.join(p['phoneticSpelling'] for p in lexical['pronunciations'] if 'phoneticSpelling' in p) else: pronun = '' # combine senses definitions = [] examples = [] def add_sense(sense): nonlocal definitions, examples if 'definitions' not in sense: return # don't bother if 'definitions' in sense: definitions += sense['definitions'] if 'examples' in sense: examples += sense['examples'] for entry in lexical['entries']: if 'senses' not in entry: continue for sense in entry['senses']: add_sense(sense) if 'subsenses' in sense: for subsense in sense['subsenses']: add_sense(subsense) def_text = '\n'.join(f'\N{BULLET} {defn}' for defn in definitions) embed = discord.Embed(title=utils.truncate(lexical['text'], 256), description=utils.truncate(def_text, 2048)) if examples: examples_text = '\n'.join(f'\N{BULLET} {example["text"]}' for example in examples) embed.add_field(name='Examples', value=utils.truncate(examples_text, 1024)) embed.set_footer(text=pronun) await ctx.send(embed=embed)