async def _show_config(self, ctx): config = await self._get_case_config(ctx.guild.id, connection=ctx.db) if not config: return await ctx.send( 'Mod-logging hasn\'t been configured yet. ' f'To turn it on, use `{ctx.clean_prefix}{ctx.invoked_with} channel #channel`.' ) will, color = ('will', random_color()) if config.enabled else ('won\'t', random_color()) flags = ', '.join(flag.name for flag in ActionFlag if config.events & flag) count = await _get_number_of_cases(ctx.db, ctx.guild.id) embed = (discord.Embed( description=f'I have made {count} cases so far.', color=color).set_author( name=f'In {ctx.guild}, I {will} be logging mod actions.'). add_field(name='Logging Channel:', value=f'<#{config.channel_id}>').add_field( name='Actions that will be logged:', value=flags, inline=False)) await ctx.send(embed=embed)
async def _new_users(self, ctx, *, count: int = 5): """Tells you the recently joined members on this server. The minimum is 3 members. If no number is given, I will show the last 5 members that joined. """ human_delta = time.human_timedelta count = max(count, 3) members = heapq.nlargest(count, ctx.guild.members, key=attrgetter('joined_at')) names = map(str, members) values = (( f'**Joined:** {human_delta(member.joined_at)}\n' f'**Created:** {human_delta(member.created_at)}\n{"-" * 40}') for member in members) entries = zip(names, values) title = f'The {formats.pluralize(**{"newest members": len(members)})}' pages = FieldPaginator(ctx, entries, per_page=5, title=title, color=random_color()) await pages.interact()
async def _shell(self, ctx, *, script): """Runs a shell script.""" script = self.cleanup_code(script) embed = (discord.Embed(description=f'```\n{script}```', color=random_color()).set_author(name='Output')) links = [] async def maybe_put_content(content, *, name): if len(content) >= 1017: url = await ctx.hastebin(content.encode("utf-8")) links.append(f'<{url}>') content = 'Too big...' elif not content: content = 'Nothing...' else: content = f'```\n{content}```' embed.add_field(name=name, value=content, inline=False) stdout, stderr = await run_subprocess(script) await maybe_put_content(stdout, name='stdout') await maybe_put_content(stderr, name='stderr') links = links or '' await ctx.send('\n'.join(links), embed=embed)
async def _delete(self, ctx, name: str): """Delete a tag!""" query = """DELETE FROM tags WHERE tag = $1""" _query = """SELECT * FROM tags WHERE tag = $1""" row = await self.bot.db.fetchrow(_query, name) if row["id"] == ctx.author.id: await self.bot.db.execute(query, name) embed = discord.Embed(title="Tag successful deleted!", color=colors.random_color()) await ctx.send(embed=embed) else: embed = discord.Embed( title="You cant delete this tag!", color=colors.random_color(), description="You are not the author of this tag!") await ctx.send(embed=embed)
async def on_error(self, ctx, error): if isinstance(error, commands.CommandInvokeError): embed = discord.Embed(title="Cant find this word!", description="Try another one\n" "Maybe try to to write them together.", color=int(colors.random_color())) await ctx.send(embed=embed)
async def search_docs(self, ctx, branch, search): if not search: return await ctx.send(BASE_URL + branch) if not self._docs_cache: await ctx.trigger_typing() await self.build_docs_cache(ctx) search = search.replace(' ', '_') if branch == 'rewrite': lower = search.lower() if hasattr(discord.abc.Messageable, lower): search = f'abc.Messageable.{lower}' def replace(o): return HELPERS.get(o.group(0), '') pattern = re.compile('|'.join(rf'\b{key}\b' for key in HELPERS)) search = pattern.sub(replace, search) cache = self._docs_cache[branch] matches = finder(search, cache, count=10) if not matches: return await ctx.send( 'I\'m sorry but I couldn\'t find anything that matches what you are looking for.' ) description = '━━━━━━━━━━━━━━━━━━━\n' + '\n'.join( f'[{key}]({url})' for key, url in matches) embed = discord.Embed(title='discord.py documentation search', description=description, color=random_color()) await ctx.send(embed=embed)
async def _tag_info(self, ctx, *, name: TagName): """Shows some information about an existing tag.""" # Ouch, big performance loss. Querying takes about 10ms. # I will ignore this for now until the bot becomes bigger and querying the tags becomes expensive. tag = await self._get_tag(ctx.db, name, ctx.guild.id) rank = await self._get_tag_rank(ctx.db, tag) user = self.bot.get_user(tag['created_by']) creator = user.mention if user else f'Mysterious person (ID: {tag["created_by"]})' icon_url = user.avatar_url if user else discord.Embed.Empty embed = (discord.Embed( color=random_color(), timestamp=tag['created_at']).set_author( name=tag['name'], icon_url=icon_url).add_field( name='Created by:', value=creator).add_field( name='Used:', value=f'{formats.pluralize(time=tag["uses"])}', inline=False).add_field(name='Rank:', value=f'#{rank}', inline=False)) if tag['is_alias']: embed.description = f'Original tag: **{tag["content"]}**' await ctx.send(embed=embed)
def to_embed(self): embed = (discord.Embed(description=self.reason, color=random_color()).set_author( name=self.message, icon_url=_blocked_icon)) if self.reason: embed.description = self.reason return embed
def default(self): # Paginate? return (discord.Embed( description=HELP_TEXT, color=random_color()).set_author(name='Sudoku Help').add_field( name='How to play:', value=INPUT_FIELD).add_field(name='Controls:', value=self.help(), inline=False))
async def _neko(self, ctx, *, tag=None): """Gives you a random neko picture. You can provide a tag on what you are looking for, or leave it empty for something random. Tags available: feet, yuri, trap, hololewd, lewdkemo, solog, feetg, cum, erokemo, les, wallpaper, lewdk, ngif, meow, tickle, lewd, feed, gecg, eroyuri, eron, cum_jpg, bj, nsfw_neko_gif, solo, kemonomimi, nsfw_avatar, gasm, poke, anal, slap, hentai, avatar, erofeet, holo, keta, b*****b, pussy, t**s, holoero, lizard, pussy_jpg, pwankg, classic, kuni, waifu, pat, 8ball, kiss, femdom, neko, spank, cuddle, erok, fox_girl, boobs, Random_hentai_gif, smallboobs, hug, ero """ await ctx.trigger_typing() if not tag: tag = random.choice(self.tags) if tag == 'random_hentai_gif': tag = tag.capitalize() async with ctx.session.get( f'https://nekos.life/api/v2/img/{tag}') as resp: data = await resp.json() try: embed = (discord.Embed( title=f'Neko - {tag}', color=random_color(), timestamp=ctx.message.created_at).set_image( url=f'{data.get("url")}').set_footer( text=f'Requested by {ctx.author.display_name}', icon_url=ctx.author.avatar_url)) except Exception: # muh pycodestyle embed = (discord.Embed( color=random_color(), timestamp=ctx.message.created_at).set_thumbnail( url=self.thumbnail).set_author( name=f'{ctx.author.display_name}, an error occurred.', icon_url=ctx.author.avatar_url)) await ctx.send(embed=embed)
async def _id(self, ctx): guild_id = ctx.guild.id channel_id = ctx.channel.id user_id = ctx.author.id embed = discord.Embed(title="Get ID", color=colors.random_color(), description=f"Server ID: `{guild_id}`\n" f"Channel ID: `{channel_id}`\n" f"Your ID: `{user_id}`") await ctx.send(embed=embed)
def default(self): author = self.ctx.author if self.using_reactions(): help_text = 'Stuck? Click \N{INFORMATION SOURCE} for help.' else: help_text = 'Stuck? Type `help` for help.' return (discord.Embed(description=str(self._board), color=random_color()) .set_author(name=f'Sudoku: {author.display_name}', icon_url=author.avatar_url) .add_field(name='\u200b', value=help_text, inline=False))
async def _duden(self, ctx, word): """Search a word in the duden (German only!)""" get = duden.get(word) if get != None: embed = discord.Embed(title=f"DudenSearch ~ {word}", description=f"```{get}```", color=int(colors.random_color())) await ctx.send(embed=embed) else: await self.error(ctx.channel, word)
def on_mouse_press(self, x, y, button, modifiers): if button == 1: entity = Entity(x, y, random_color(), speed_x=(random.random() - 0.5) * 1000, speed_y=(random.random() - 0.5) * 1000, radius=random.randint(10, 15), filled=random.choice([True, False])) self.entities.append(entity)
def default(self): prompt = discord.Embed(color=random_color()) prompt.set_author(name=f'Let\'s play Sudoku, {self.ctx.author.display_name}!', icon_url=SUDOKU_ICON) prompt.description = '**Please choose a difficulty.**\n-----------------------\n' prompt.description += '\n'.join( f'{trig} = {callback.func.__name__.title().replace("_", " ")}' for trig, callback in self._reaction_map.items() ) return prompt
async def _clean(self, ctx, limit=100): """Cleans up my messages from the channel. Give me Manage Messages and Read Message History permissions, and I'll also delete messages that invoked my commands. """ prefixes = tuple(self.bot.get_guild_prefixes(ctx.guild)) bot_id = self.bot.user.id bot_perms = ctx.channel.permissions_for(ctx.me) purge = functools.partial(ctx.channel.purge, limit=limit, before=ctx.message) can_bulk_delete = bot_perms.manage_messages and bot_perms.read_message_history if can_bulk_delete: def is_possible_command_invoke(m): if m.author.id == bot_id: return True return m.content.startswith( prefixes) and not m.content[1:2].isspace() deleted = await purge(check=is_possible_command_invoke) else: deleted = await purge(check=lambda m: m.author.id == bot_id, bulk=False) spammers = Counter(str(m.author) for m in deleted) total_deleted = sum(spammers.values()) second_part = ' was' if total_deleted == 1 else 's were' title = f'{total_deleted} message{second_part} removed.' joined = '\n'.join( itertools.starmap('**{0}**: {1}'.format, spammers.most_common())) if ctx.bot_has_embed_links(): spammer_stats = joined or discord.Embed.Empty embed = (discord.Embed( description=spammer_stats, color=random_color()).set_author(name=title)) embed.timestamp = ctx.message.created_at await ctx.send(embed=embed, delete_after=10) else: message = f'{title}\n{joined}' await ctx.send(message, delete_after=10) await asyncio.sleep(20) with contextlib.suppress(discord.HTTPException): await ctx.message.delete()
async def _create(self, ctx, name: str, *, content: str): """Create a new tag""" query = """INSERT INTO tags VALUES ($1, $2, $3) """ await self.bot.db.execute(query, name, ctx.author.id, content) embed = discord.Embed( title="Tag created successfully!", description=f"See the tag, by using b.loadtag {name}", color=colors.random_color()) await ctx.send(embed=embed)
async def _default_flip(ctx): """Flip called with no arguments.""" side = random.choices(SIDES, WEIGHTS)[0] file = discord.File(f'data/images/coins/{side}.png', 'coin.png') embed = (discord.Embed(title=f'...Flipped {side}!', color=random_color()) .set_author(name=ctx.author.display_name, icon_url=ctx.author.avatar_url) .set_image(url='attachment://coin.png')) await ctx.send(file=file, embed=embed)
async def _todo(self, ctx, *, text: str = None): """Add something as ToDo""" if text: file = open("./cogs/owner/Todo.txt", "a", encoding="utf-8") file.write(f"\n {text}") file.close() embed = Embed(title="Add a new ToDo:", description="```css\n" f"{text}\n" "```", color=random_color()) await ctx.send(embed=embed) else: file = open("./cogs/owner/Todo.txt", "r", encoding="utf-8").read() embed = Embed(title="ToDo's", description="```css\n" f"{file}\n" "```", color=random_color()) await ctx.send(embed=embed)
async def _macts_enable(self, ctx, actions: commands.Greedy[ActionFlag]): """Enables case creation for all given mod actions.""" query = """ INSERT INTO modlog_config (guild_id, events) VALUES ($1, $3) ON CONFLICT (guild_id) DO UPDATE SET events = modlog_config.events | $2 RETURNING channel_id, events; """ await self._set_actions(ctx, query, actions, color=random_color(), default_op=partial(operator.or_, _default_flags))
async def _macts_disable(self, ctx, actions: commands.Greedy[ActionFlag]): """Disables case creation for all given mod actions.""" query = """ INSERT INTO modlog_config (guild_id, events) VALUES ($1, $3) ON CONFLICT (guild_id) DO UPDATE SET events = modlog_config.events & ~cast($2 AS INTEGER) RETURNING channel_id, events; """ await self._set_actions(ctx, query, actions, color=random_color(), default_op=lambda f: _default_flags & ~f)
async def _blacklist_embed(self, ctx, action, icon, thing, reason, time): type_name = 'Server' if isinstance(thing, discord.Guild) else 'User' reason = truncate(reason, 1024, '...') if reason else 'None' embed = (discord.Embed( timestamp=time, color=random_color()).set_author( name=f'{type_name} {action}', icon_url=icon).add_field(name='Name:', value=thing).add_field( name='ID:', value=thing.id).add_field(name='Reason:', value=reason, inline=False)) await ctx.send(embed=embed)
async def _wiki(self, ctx, *, word: str): """Search something on Wikipedia""" if " " in word: word_split = word.split(" ") new_word = word_split[0] + word_split[1] text = wikipedia.summary(new_word, sentences=2) embed = discord.Embed(title=f"WikiSearch ~ `{new_word}`", description=f"```{text}```", url=f"https://wikipedia.org/wiki/{new_word}", color=int(colors.random_color())) embed.set_footer(text=f"Requested by {ctx.author}", icon_url=ctx.author.avatar_url) await ctx.send(embed=embed) else: text = wikipedia.summary(word, sentences=2) embed = discord.Embed(title=f"WikiSearch ~ `{word}`", description=f"```{text}```", url=f"https://wikipedia.org/wiki/{word}", color=int(colors.random_color())) embed.set_footer(text=f"Requested by {ctx.author}", icon_url=ctx.author.avatar_url) await ctx.send(embed=embed)
async def _jdoodle(self, ctx): """Checks some stats about the JDoodle API. *This command can only be used by the bot owner.* """ result = await self._request('credit-spent') embed = (discord.Embed( description= f'The bot made **{result.used}** requests, **{200 - result.used}** remaining.', color=random_color()).set_author(name='JDoodle API requests', icon_url=ctx.author.avatar_url)) await ctx.send(embed=embed)
async def _messages(self, ctx): """Shows all set welcome messages for this server.""" if ctx.invoked_subcommand: return messages = self.get_welcome_messages() description = '\n'.join( itertools.starmap('`{0}.` => {1}'.format, enumerate(messages, 1)) if messages else ('No welcome messages set for this server yet', )) embed = discord.Embed(title=f'Custom welcome messages for {ctx.guild}', description=description, color=random_color()) await ctx.send(embed=embed)
async def _prefix(self, ctx): """Shows the prefixes that you can use in this server.""" if ctx.invoked_subcommand: return prefixes = self.bot.get_guild_prefixes(ctx.guild) del prefixes[0] # To make the mention not show up twice. description = '\n'.join( starmap('`{0}.` **{1}**'.format, enumerate(prefixes, 1))) embed = discord.Embed(title=f'Prefixes you can use in {ctx.guild}', description=description, color=random_color()) await ctx.send(embed=embed)
async def _numbered_flip(self, ctx, number): if number == 1: await self._default_flip(ctx) elif number > 100: await ctx.send('I am not going to flip that many coins for you.') elif number <= 0: await ctx.send('Wtf, how is that supposed to work?') else: message, file = await self._flip_image(number) embed = (discord.Embed(title=f'...Flipped {message}', color=random_color()) .set_author(name=ctx.author.display_name, icon_url=ctx.author.avatar_url) .set_image(url='attachment://flipcoins.png')) await ctx.send(file=file, embed=embed)
async def send_embed(ctx, lang, emote, result): # The thing is that we need to format the title properly... title = f'Code evaluation: {lang.capitalize()} {emote}' # Potentially risky shit for not displaying the embed. Don't ask me why this isn't handled while parsing the response. if not result.memory: result.memory = 0 if not result.cpu_time: result.cpu_time = 0.00 embed = (discord.Embed(title=title, description='━━━━━━━━━━━━━━━━━━━', color=random_color()) .add_field(name='Memory usage:', value=f'{int(result.memory) / 1000}mb') .add_field(name='Evaluated in:', value=f'{result.cpu_time}ms') .add_field(name='Output:', value=f'```\n{truncate(result.output, 1013, "...")}```', inline=False) .set_footer(text='Evaluated using the JDoodle API.', icon_url='https://bit.ly/2CvWRiA')) await ctx.send(embed=embed)
async def _stats(self, ctx): """Shows some usage statistics about this bot.""" content = ( f'__**Usage statistics:**__\n', f'Commands invoked in total: **{self.bot.command_counter.get("total")}**', f'Commands invoked in this guild: **{self.bot.command_counter.get(str(ctx.guild.id))}**', f'Commands invoked in DMs: **{self.bot.command_counter.get("in DMs")}**\n', f'And here are the commands, which were invoked successfully in total: **{self.bot.command_counter.get("succeeded")}**\n', f'*Only applies to the period from since the bot was restarted for the last time until now.*', ) if ctx.bot_has_embed_links(): await ctx.send(embed=discord.Embed(description='\n'.join(content), color=random_color())) else: await ctx.send('\n'.join(content))
async def _mod_actions(self, ctx): """Shows all the actions that can be logged. For this command to work, it is necessary that you've set a channel for logging cases first. """ config = await self._get_case_config(ctx.guild.id, connection=ctx.db) if not config: return await ctx.send(f'Please set a channel with `{ctx.clean_prefix}modlog channel #channel` first.') flags = ', '.join(flag.name for flag in ActionFlag) enabled_flags = ', '.join(flag.name for flag in ActionFlag if config.events & flag) embed = (discord.Embed(color=random_color()) .add_field(name='List of valid Mod Actions:', value=flags) .add_field(name='Actions that will be logged:', value=enabled_flags)) await self._check_modlog_channel(ctx, config.channel_id, embed=embed)