def __init__(self, name: str, data: dict): self.sound_name = name self.sound_data = data files = data["files"] arrays, weights = [], [] for fd in files: filenames = [] if "glob" in fd.keys(): filenames.extend(glob.glob(fd["glob"])) if "filenames" in fd.keys(): filenames.extend(fd["filenames"]) if "filename" in fd.keys(): filenames.append(fd["filename"]) if len(filenames) >= 1: arrays.append(filenames) weights.append(fd.get("weight", 1)) self.sound_arrays = arrays self.sound_weights = weights commands.Command.__init__(self, soundplayer_callback, name=name, aliases=data.get("aliases", []), **data.get("commandkwargs", {})) commands.guild_only()( self) # make the command guild-only by adding the check
async def cog_check(self, ctx): return all([ await check.predicate(ctx) for check in { commands.guild_only(), commands.bot_has_guild_permissions(manage_roles=True) } ])
def __init__(self, debug=False, *args, **kwargs): super().__init__(*args, **kwargs) self.debug = debug self.logger = Logger(name, log_level, log_type) self.logger.info(f"Starting {name}") self.cfg = ConfigUtil() self.add_check(commands.guild_only())
def main(): bot = commands.Bot(command_prefix=commands.when_mentioned_or('!'),) async def on_ready(): logger.info(f'{bot.user} has connected to Discord!') bot.add_listener(on_ready) bot.add_check(commands.guild_only()) # bot.add_cog(BGGCog(bot)) bot.add_cog(Music(bot)) bot.run(token)
class Roleplay(Cog): """Commands related to roleplay.""" def __init__(self, bot): super().__init__(bot) @commands.command(name='rmember', aliases=['rmem', 'draw']) @commands.check(commands.guild_only()) async def rand_member(self, ctx): """Choose a random member from the message's guild.""" satisfied = False m_list = list(ctx.guild.members) while not satisfied: rmem = random.choice(m_list) satisfied = str(rmem.status) == 'online' await ctx.send(rmem.mention) return rmem @commands.command(aliases=['boop', 'poke', 'hit']) async def slap(self, ctx, *, target: str): """Slap someone, for the win. Usage: slap [person]""" keystr = '* ' + ctx.message.content.split()[0][len(ctx.prefix):] + 's *' await ctx.send('*' + ctx.author.display_name + keystr + target + '* **' + random.choice(adjs) + '**.') @commands.command(aliases=['stab', 'kill', 'punch', 'shoot', 'hurt', 'fight']) async def attack(self, ctx, *, target: str): """Hurt someone with determination in the shot. Usage: attack [person]""" await ctx.send('*' + ctx.author.display_name + '* ' + random.choice(fights).format('*' + target + '*') + '. ' + random.choice(death).format('*' + target + '*')) @commands.command() async def charlie(self, ctx, *, question: str): """Ask a question... Charlie Charlie are you there? Usage: charlie [question to ask, without punctuation]""" aq = '' if question.endswith('?') else '?' await ctx.send('*Charlie Charlie* ' + question + aq + "\n**" + random.choice(['Yes', 'No']) + '**') @commands.command(aliases=['soontm']) async def soon(self, ctx): """Feel the loading of 10000 years, aka Soon™. Usage: soon""" e = discord.Embed(color=random.randint(1, 255**3-1)) e.set_image(url='https://images.discordapp.net/.eJwFwdENhCAMANBdGIBiK2dxG4KIJGoN7X1dbnff-7nvON3qDrNHV4Cta5GxeTUZuVXfRNpZ89PVF7kgm-VyXPU2BYwYF6Y0cwgTcsAJMOFMxJESBqblQwgqcvvWd_d_AZ09IXY.TT-FWSP4uhuVeunhP1U44KnCPac') await ctx.send(embed=e)
def is_moderator(): """A check that determins if a user is a moderator This is similar to `is_guild_moderator` except it uses `has_permissions` instead of `has_guild_permissions` """ guild_only = commands.guild_only().predicate perms = commands.has_permissions(manage_messages=True, kick_members=True, ban_members=True).predicate async def predicate(ctx: Context) -> bool: return await guild_only(ctx) and await perms(ctx) return commands.check(predicate)
def sensitive(): check_guild = commands.guild_only().predicate has_bypass = commands.has_guild_permissions(manage_messages=True).predicate async def extended_check(ctx): await check_guild(ctx) sensitive = await ctx.bot.get_cog("Config").get_value( ctx.guild, get(config.configurables, name="private") ) if sensitive: return await has_bypass(ctx) return True return commands.check(extended_check)
def is_guild_moderator(): """A check that determines if a user is a guild moderator This is done by checking if the user has the following guild permissions: - `Manage Messages` - `Kick Members` - `Ban Members` """ guild_only = commands.guild_only().predicate perms = commands.has_guild_permissions(manage_messages=True, kick_members=True, ban_members=True).predicate async def predicate(ctx: Context) -> bool: return await guild_only(ctx) and await perms(ctx) return commands.check(predicate)
class Ranks(Cog): """Ranks and levels.""" async def on_not_command(self, msg): """Do level-up logic.""" if self.bot.selfbot: return if isinstance(msg.channel, discord.abc.PrivateChannel): return if msg.author.bot: return prof_name = 'profile_' + str(msg.guild.id) prof = self.bot.store.get_prop(msg, prof_name) prof['exp'] += math.ceil(((len(msg.content) / 6) * 1.5) + random.randint(0, 14)) new_level = rank.xp_level(prof['exp'])[0] if new_level > prof['level']: bclu = self.bot.store.get_prop(msg, 'broadcast_level_up') if isinstance(bclu, str): bclu = bclu.lower() if bclu in bool_true: await msg.channel.send( '**Hooray!** {0.mention} has just *advanced* to **level {1}**.' .format(msg.author, str(new_level))) prof['level'] = new_level self.bot.store.set_prop(msg, 'by_user', prof_name, prof) @commands.command(aliases=['xp', 'level', 'lvl', 'exp', 'levels']) @commands.check(commands.guild_only()) async def rank(self, ctx, *, user: discord.Member): """Check experience, level, and rank! Usage: xp {user}""" stat_fmt = '''{0.author.mention} Here are {5} **stats**: **LEVEL: {1} EXPERIENCE: __{2}/{3}__ for next level TOTAL EXPERIENCE: {4}** *Try getting some more! :smiley:* ''' target = FakeMessageMember(user) prof = self.bot.store.get_prop(target, 'profile_' + str(target.guild.id)) rlevel = rank.xp_level(prof['exp']) await ctx.send( stat_fmt.format(target, str(rlevel[0]), str(int(rlevel[1])), str(int((rlevel[0] + 1) * lvl_base)), str(prof['exp']), ('your' if target.author.id == ctx.author.id else str(target.author) + "'s")))
async def on_ready(): print("{0.name} is ready!\nID: {0.id}\ndiscord.py Version: {1}".format( client.user, str(discord.__version__))) await client.change_presence(activity=UpdatedPresence(client)) # Cogs and Checks (only on first start) global starting if starting: global to_cog global stats_cog global debug_cog starting = False to_cog = TOrganizer(client) stats_cog = Stats(client) debug_cog = Debug(client) misc_cog = Misc(client) client.add_check(commands.guild_only()) client.add_cog(to_cog) client.add_cog(stats_cog) client.add_cog(debug_cog) client.add_cog(misc_cog)
def register_commands(self, bot: commands.Bot): @bot.group( name='duel', description='Command for managing duels', ) @commands.check(commands.guild_only()) async def duel(ctx: commands.Context): if not ctx.invoked_subcommand: ctx.channel.send('Invalid Subcommand!') @duel.command( name='challenge', description='Challenges another user', ) async def challenge(ctx: commands.Context): raise NotImplementedError # TODO @duel.command() async def list_duels(ctx: commands.Context): raise NotImplementedError # TODO @duel.command() async def duel_params(ctx: commands.context): raise NotImplementedError # TODO
'separate': False, } logger = logging.getLogger('logs_uploader') logger.setLevel(logging.INFO) handler = logging.StreamHandler(sys.stdout) handler.setLevel(logging.INFO) logger.addHandler(handler) # Don't post to team channels and force the guild used so testing can you DMs DISCORD_TESTING = bool(os.getenv('DISCORD_TESTING')) # Just post all messages to calling channel, allow DMs DISCORD_DEBUG = bool(os.getenv('DISCORD_DEBUG')) if DISCORD_TESTING or DISCORD_DEBUG: # Allow DMs in testing guild_only = commands.check_any(commands.guild_only(), commands.dm_only()) # type: ignore # print all debug messages logger.setLevel(logging.DEBUG) handler.setLevel(logging.DEBUG) else: guild_only = commands.guild_only() bot = commands.Bot(command_prefix='!') async def log_and_reply(ctx: commands.Context, error_str: str) -> None: logger.error(error_str) await ctx.reply(error_str)
def cog_check(self, ctx): return commands.guild_only().predicate(ctx)
async def __local_check(self, ctx): return commands.guild_only()
def __init__(self, bot): super().__init__(bot) for cmd in self.get_commands(): cmd.add_check(commands.guild_only())
import emoji from discord.ext import commands from dog import Cog from dog.core import checks, converters from dog.core.checks import create_stack from dog.core.context import DogbotContext from dog.core.converters import DeleteDays from dog.core.utils.formatting import describe logger = logging.getLogger(__name__) CUSTOM_EMOJI_REGEX = re.compile(r'<:([a-zA-Z_0-9-]+):(\d+)>') purge_command = create_stack( checks.is_moderator(), checks.bot_perms(manage_messages=True, read_message_history=True), commands.guild_only()) def _create_purge_command(name, base_purge_handler, *, parent, aliases=None, help_text=''): """A function used to dynamically construct purge command subcommands.""" @parent.command(name=name, aliases=aliases or []) @purge_command async def _purge_generated(self, ctx, amount: int = 5): """...""" await self.base_purge(ctx, amount, base_purge_handler)
def __init__(nested_self, bot): super().__init__(bot) if guild_only: nested_self.settings.add_check(commands.guild_only().predicate)
def wrapper(func): # wooo, currying return commands.guild_only()(commands.command(*args, **kwargs)(func))
def __init__(self, bot): super().__init__(bot) for cmd in self.get_commands(): cmd.add_check(commands.guild_only()) if cmd.name in ['서버정보', '권한']: cmd.add_check(partial(self.check.subcmd_valid, True))
class Admin: """ Administrative tasks. """ def __init__(self): # Might be nicer to also have "@botuser get invite" as a command if # "@botuser add me" is not intuitive enough for me to remember. self.add_group.command(name='me', brief='Gets an invite URL.')(self.add_guild) self.get_group.command(name='invite', brief='Gets an invite URL.')(self.add_guild) self.remove_group.command(name='guild', aliases=['guilds', 'server', 'servers'], brief='Makes me leave a given server.')( self.remove_guild) commands.command(name='leave', brief='Makes me leave a given server.')( self.remove_guild) @staticmethod async def __local_check(ctx): return (await ctx.bot.is_owner(ctx.author) or ctx.author.id in ctx.bot.commanders) @util.group(name='get', aliases=['list'], brief='Lists various elements.') async def get_group(self, ctx): pass @get_group.command(name='commanders', aliases=['commander'], brief='Lists the current commanders for my bot.') async def get_commanders(self, ctx): """Lists any commanders authorized to use me.""" embed = discord.Embed( title=f'Authorized commanders for {ctx.bot.user} are', color=0x00FFFF, ) embed.set_thumbnail(url=ctx.bot.user.avatar_url) user_strings = [] for id in ctx.bot.commanders: # Use the cached version or we will be dead before the # command finishes execution. user = ctx.bot.get_user(id) if ctx.guild is not None and user in ctx.guild.members: user_strings.append(f'- {user.mention} `{user.id}`') else: user_strings.append(f'- {user} `{user.id}`') embed.description = '\n'.join(user_strings) msg = await ctx.send(embed=embed) util.confirm_operation(ctx) util.make_closeable(ctx, msg) @get_group.command(name='guilds', aliases=['guild', 'server', 'servers'], brief='Lists the guilds I am part of.') async def get_guilds(self, ctx): """Lists all guilds I am currently connected to.""" embed = discord.Embed(title=f'{ctx.bot.user} is currently a member in', color=0xFFFF00) for guild in ctx.bot.guilds: d = [ f'**ID**: `{guild.id}`', f'**Text Channels**: {len(guild.text_channels)}', f'**Voice Channels**: {len(guild.voice_channels)}', f'**Categories**: {len(guild.categories)}', f'**Members**: {len(guild.members)}', f'**MFA**: {"2FA" if guild.mfa_level else "None"}', f'**Verif\'n Level**: {guild.verification_level}', f'**Content Filter**: {guild.explicit_content_filter}', f'**Owner**: {guild.owner} `{guild.owner.id}`' ] if len(embed.fields) == 0: embed.set_thumbnail(url=guild.icon_url) embed.add_field(name=guild.name, value='\n'.join(d), inline=False) msg = await ctx.send(embed=embed) util.confirm_operation(ctx) util.make_closeable(ctx, msg) @commands.check(commands.guild_only()) @get_group.command( name='perms', aliases=['perm', 'permission', 'permissions'], brief='Lists the permissions for this guild that I am granted.', ) async def get_permissions(self, ctx): """Lists the current permissions the bot has in the current guild.""" perms = ctx.guild.me.guild_permissions truthy_perms = [p[0] for p in perms if p[1]] falsey_perms = [p[0] for p in perms if not p[1]] truthy_perms = '\n'.join(map(str, truthy_perms)) falsey_perms = '\n'.join(map(str, falsey_perms)) embed = discord.Embed(title=f'My permissions in {ctx.guild}', color=0xFF00FF) embed.set_thumbnail(url=ctx.guild.icon_url) embed.add_field(name='Permissions granted', value=truthy_perms if truthy_perms else 'None') embed.add_field(name='Permissions denied', value=falsey_perms if falsey_perms else 'None') msg = await ctx.send(embed=embed) util.confirm_operation(ctx) util.make_closeable(ctx, msg) @get_group.command( name='emojis', aliases=[ 'emoji', 'emote', 'emotes', 'emoticon', 'reaction' 'emoticons', 'react', 'reacts', 'reactions' ], brief='Lists the emojis that I will currently react with.') async def get_emojis(self, ctx): embed = discord.Embed( title=f'My super dank list of emojis to shitpost with', color=0xFFAACC) embed.set_thumbnail(url=ctx.bot.user.avatar_url) emojis = ctx.bot.loaded_emojis embed.description = '\n'.join( map(lambda e: f'{str(e)} {e.name} {e.id}', emojis)) msg = await ctx.send(embed=embed) util.confirm_operation(ctx) util.make_closeable(ctx, msg) @get_group.command(name='blacklist', brief='Gets the blacklisted channels to not react in.') async def get_blacklist(self, ctx): """ This blacklist exists to ensure that the bot does not react in inappropriate situations. """ blacklist = ctx.bot.dont_react_in.get() embed = discord.Embed( title='Channels I am not allowed to react in', description='These are the channels I am not allowed to react to ' 'messages in...', color=0xB000B5) # Guild is a string. JSON standard says we can't use ints as keys. # Bloody stupid. for guild, channels in blacklist.items(): guild_obj = discord.utils.find(lambda g: str(g.id) == guild, ctx.bot.guilds) if guild_obj is None: continue channel_objs = [] for channel in channels: chan_obj = discord.utils.find(lambda c: c.id == channel, guild_obj.text_channels) if chan_obj is None: continue channel_objs.append(chan_obj) embed.add_field(name=guild_obj.name, value='\n'.join( map(lambda c: f'#{c.name}', channel_objs)), inline=False) if len(embed.fields) == 0: embed.add_field(name='I am a free bot.', value='Nothing is blacklisted!') msg = await ctx.send(embed=embed) util.confirm_operation(ctx) util.make_closeable(ctx, msg) @get_group.command( name='trigger', aliases=[ 'triggers', 'word', 'words', 'regex', 'regexes', 'regexs', 'pattern', 'patterns', 'phrase', 'phrases' ], brief='Lists all phrases/regular expressions I understand.') async def get_phrases(self, ctx): # noinspection PyProtectedMember patterns = [] for pattern in ctx.bot.patterns: # Determines if the regex was probably added as a word. match = re.match(r'\\b\(([^)]+)\)\\b', pattern.pattern) if match: patterns.append(match.group(1)) else: patterns.append(f'`{pattern.pattern}` (regex)') embed = discord.Embed(title=f'Things I react to', description='\n'.join(patterns), color=0xFEC) embed.set_thumbnail(url=ctx.bot.user.avatar_url) msg = await ctx.send(embed=embed) util.confirm_operation(ctx) util.make_closeable(ctx, msg) """ 'Add' commands """ @util.group(name='add', brief='Adds various elements.') async def add_group(self, ctx): pass # Apparently making a staticmethod shits across the resolution of coro-s # ... thanks Guido. # noinspection PyMethodMayBeStatic async def add_guild(self, ctx, *, user: commands.MemberConverter = None): """ DM's you the invite to the server. If you mention someone, then they get sent a URL instead of you. """ if user is None: user = ctx.author await user.send(f'Add me to your server, please.\n\n{ctx.bot.invite}') util.confirm_operation(ctx) # noinspection PyUnresolvedReferences @commands.check(commands.guild_only()) @add_group.command(name='commander', brief='Authorizes a user to talk on my behalf.') async def add_commander(self, ctx, *, commander: commands.MemberConverter): commanders = ctx.bot.commanders.get() if commander == ctx.bot.user: raise NameError('I am not going to command _myself_...') elif commander.bot: raise NameError( 'I am not going to be controlled by a lowlife bot!') elif commander.id in commanders: raise NameError('That name is already in my list. Tough luck.') else: commanders.append(commander.id) # Commit to disk await ctx.bot.commanders.set(commanders) util.confirm_operation(ctx) @commands.check(commands.guild_only()) @add_group.command(name='emoji', aliases=['emote', 'emoticon', 'reaction', 'react'], brief='Adds a new emoji to my reaction list.') async def add_emoji(self, ctx, *, emote: commands.EmojiConverter): emotes = ctx.bot.loaded_emojis if emote not in emotes: emotes.append(emote) await ctx.bot.set_emoji_list(emotes) util.confirm_operation(ctx) else: raise ValueError(f'Emote already exists in my list. {emote}') @add_group.command(name='regex', aliases=['pattern'], brief='Adds a regular expression to Kat. Ask Espy.') async def add_pattern(self, ctx, *, phrase: str): """Compiles the given regular expression.""" regex = re.compile(phrase, flags=re.I) # Will assert that this compiled? Maybe? regex.match('') patterns = ctx.bot.patterns patterns.append(regex) await ctx.bot.set_pattern_list(patterns) util.confirm_operation(ctx) @add_group.command( name='word', aliases=['phrase'], brief='Adds a word or phrase to the list of things I can react to.', ) async def add_word(self, ctx, *, phrase: str): """Compiles the given phrase into a regular expression.""" # Hacky, but if I put brackets around said phrase... it should make # sure I detect that this is a command added word, then in the list # we don't have to show it in backticks. Hacky work around. Sue me, etc. regex = re.compile('\\b(%s)\\b' % phrase, flags=re.I | re.U | re.M) # Will assert that this compiled? Maybe? patterns = ctx.bot.patterns patterns.append(regex) await ctx.bot.set_pattern_list(patterns) util.confirm_operation(ctx) @commands.check(commands.guild_only()) @add_group.command( name='blacklist', brief='Blacklists a given channel, or if unspecified, __this__ channel.' ) async def add_blacklist(self, ctx, *, channel: commands.TextChannelConverter = None): if channel is None: channel = ctx.channel guild_id = str(ctx.guild.id) chan_id = channel.id blacklist = ctx.bot.dont_react_in.get() if guild_id in blacklist: if chan_id in blacklist[guild_id]: raise ValueError(f'{channel.name} is already blacklisted on ' 'this server.') else: blacklist[guild_id].append(chan_id) else: blacklist[guild_id] = [chan_id] await ctx.bot.dont_react_in.set(blacklist) util.confirm_operation(ctx) """ 'Remove' methods. """ @util.group(name='remove', brief='Removes various elements.') async def remove_group(self, ctx): pass # noinspection PyMethodMayBeStatic async def remove_guild(self, ctx, *, guild): """ Removes my user from a given server. """ # Try to find the guild. guild_obj = discord.utils.find( lambda g: g.name.lower() == guild.lower() or g.id == guild, ctx.bot.guilds) if guild_obj is None: raise ValueError('Could not find a guild with that name or ID.') else: if ctx.guild == guild_obj: # We can't react after we have left. await ctx.message.add_reaction('\N{OK HAND SIGN}') await guild_obj.leave() else: await guild_obj.leave() util.confirm_operation(ctx) @remove_group.command( name='commander', aliases=['commanders'], brief='De-authenticates a given commander from using me.') async def remove_commander(self, ctx, *, member: commands.MemberConverter): """Removes a commander from my authenticated list.""" # Don't allow removal of the bot owner. if await ctx.bot.is_owner(member): raise PermissionError('You cannot remove the bot owner.') else: commanders = ctx.bot.commanders.get() commanders.remove(member.id) await ctx.bot.commanders.set(commanders) util.confirm_operation(ctx) @remove_group.command(name='regex', aliases=['pattern', 'word', 'phrase'], brief='Removes a given regex or phrase.') async def remove_pattern(self, ctx, *, pattern): """ Removes the given pattern from the list of patterns I react to. """ regex = discord.utils.find(lambda r: r.pattern == pattern, ctx.bot.patterns) if regex is None: regex = discord.utils.find( lambda r: r.pattern.lower() == f'\\b({pattern.lower()})\\b', ctx.bot.patterns) if regex is None: raise ValueError('Could not find that pattern.') else: patterns = ctx.bot.patterns patterns.remove(regex) await ctx.bot.set_pattern_list(patterns) util.confirm_operation(ctx) @remove_group.command(name='emoji', aliases=['emote'], brief='Removes an emote from my list of reactions.') async def remove_emoji(self, ctx, *, emoji: commands.EmojiConverter): """Removes the emoji from my reaction list, if it is there.""" emojis = ctx.bot.loaded_emojis if emoji not in emojis: raise ValueError('That emoji is not registered.') else: emojis.remove(emoji) await ctx.bot.set_emoji_list(emojis) util.confirm_operation(ctx) @commands.check(commands.guild_only()) @remove_group.command( name='blacklist', brief='Un-blacklists a given channel, or if unspecified, ' '__this__ channel.') async def remove_blacklist(self, ctx, *, channel: commands.TextChannelConverter = None): if channel is None: channel = ctx.channel guild_id = str(ctx.guild.id) chan_id = channel.id blacklist = ctx.bot.dont_react_in.get() if guild_id not in blacklist: if chan_id not in blacklist[guild_id]: raise ValueError(f'{channel.name} is not blacklisted on ' 'this server anyway.') else: blacklist[guild_id].remove(chan_id) else: blacklist.pop(guild_id) await ctx.bot.dont_react_in.set(blacklist) util.confirm_operation(ctx) @util.command( name='stop', aliases=['kill', 'reboot', 'restart', 'logout', 'exit', 'quit'], brief='Kills the bot process (Generally causes bot to restart).') async def stop(self, ctx): await ctx.send( random.choice([ 'Yessir!', 'Sure.', 'Do I really have to?', 'Goodbye ;-;', '*cries*...\n\n*sniffle* ...o..okay...', '*deletes the other bots', '*hisses*', '*nods*', 'kk', 'k', 'Sure thing sauce boss.', 'Gimme a sec then!', 'Okydokes', 'Ja.', 'PlEaSe ShUtDoWn FoR Me BoT!', 'Meh', 'You are no fun...', 'Soon. Soon you will regret the day you messed with --' '*powers down*' ])) await ctx.bot.logout()
import discord from ddtrace import tracer from discord import app_commands from discord.app_commands import Choice from discord.ext import commands from .. import SpellBot from ..actions import ConfigAction from ..metrics import add_span_context from ..utils import for_all_callbacks logger = logging.getLogger(__name__) @for_all_callbacks(commands.guild_only()) class ConfigCog(commands.Cog): def __init__(self, bot: SpellBot): self.bot = bot @app_commands.command( name="power", description="Set your power level.", ) @app_commands.describe(level="What is your current power level?") @app_commands.choices( level=[ Choice(name="1", value=1), Choice(name="2", value=2), Choice(name="3", value=3), Choice(name="4", value=4),
from settings import BOT_TOKEN, BOT_APPLICATION_ID, BOT_ROLES_DB, BOT_GUILD_IDS import discord from discord.ext import commands from discord_slash import SlashCommand, SlashContext from discord_slash.utils.manage_commands import create_option import api from itertools import dropwhile intent = discord.Intents.default() intent.members = True bot = commands.Bot(command_prefix='prefix', intents=intent) bot.add_check(commands.guild_only()) slash = SlashCommand(bot, sync_commands=True, application_id=BOT_APPLICATION_ID) con, cur = api.makeApi(BOT_ROLES_DB) LIMITS = { 'content': 2000, 'embeds': 10, 'title': 256, 'description': 2048, 'author': 256, 'fields': 25, 'field_name': 256, 'field_value': 1024, 'footer': 2048, 'embed': 6000 }
def cog_check(self, ctx: commands.Context): return commands.guild_only() and \ Utils.is_loaded(self.qualified_name.lower(), ctx.guild.id) and \ Utils.is_authorized(ctx.author, ctx.guild.id) and \ not Utils.is_banned(ctx.command, ctx.author, ctx.guild.id)
class Admin(Cog): """Commands useful for admins and/or moderators. Can be extremely powerful, use with caution! """ @commands.command(aliases=['clear', 'nuke', 'prune', 'clean']) # no_pm @commands.check(commands.guild_only()) async def purge(self, ctx, *count): """Purge a channel of messages. Usage: purge""" if self.bot.selfbot: await ctx.send( '**This command doesn\'t work in selfbot mode, due to a Discord restriction.**' ) return or_check_perms(ctx, ['manage_guild', 'manage_channels', 'manage_messages']) mode = 'count' detected = False if not count: limit = 1500 detected = True elif len(count) == 1: if count[0] == 'infinite': limit = 1600 detected = True else: try: limit = abs(int(count[0])) + 1 if limit > 1600: await ctx.send( ctx.mention + ' **You can only clean messages by user or 1-1600!**' ) return detected = True except ValueError: pass if not detected: mode = 'target' targets = set() members = {} s = ctx.guild for i in getattr(s, 'members', []): members[i.mention] = i members[i.id] = i members[i.display_name] = i members[i.name] = i for i in count: try: member = s.get_member(i) except AttributeError: try: member = await self.bot.get_user_info(i) except discord.HTTPException: member = None if member: targets.add(member) else: try: member = await self.bot.get_user_info(i) except discord.HTTPException: member = None if member: targets.add(member) names = [] _i = 0 while _i < len(count): names.append(count[_i]) with suppress(KeyError): if ' '.join(names) in members: targets.add(members[' '.join(names)]) names = [] elif _i + 1 == len(count): targets.add(members[count[0]]) _i = -1 users = count[1:] names = [] _i += 1 if not targets: await ctx.send( '**No matching users, try again! Name, nickname, name#0000 (discriminator), or ID work. Spaces do, too!**' ) return purge_ids = [m.id for m in targets] try: if mode == 'count': deleted = await ctx.channel.purge(limit=limit) else: deleted = await ctx.channel.purge( limit=1500, check=lambda m: m.author.id in purge_ids) except discord.Forbidden: await ctx.send( ctx.mention + ' **I don\'t have enough permissions to do that here 😢**') return except discord.HTTPException as e: if '14 days old' in str(e): await ctx.send( 'I can only purge messages under 14 days old :sob:') return else: raise e dn = len(deleted) del_msg = await ctx.send( '👏 I\'ve finished, deleting {0} message{1}!'.format( (dn if dn else 'no'), ('' if dn == 1 else 's'))) await asyncio.sleep(2.8) await del_msg.delete(reason='Deleting "finished purging" message') @commands.command(aliases=['amiadmin', 'isadmin', 'admin']) async def admintest(self, ctx): """Check to see if you're registered as a bot admin. Usage: admintest'""" tmp = check_perms(ctx, ('bot_admin', )) if tmp: await ctx.send(ctx.mention + ' You are a bot admin! :smiley:') else: await ctx.send(ctx.mention + ' You are not a bot admin! :slight_frown:') @commands.command(aliases=['adminadd']) async def addadmin(self, ctx, *rrtarget: str): """Add a user to the bot admin list. Usage: addadmin [user]""" tmp = check_perms(ctx, ('bot_admin', )) if not rrtarget: await ctx.send( '**You need to specify a name, nickname, name#0000, mention, or ID!**' ) return rtarget = ' '.join(rrtarget) try: _target = ctx.guild.get_member_named(rtarget) except AttributeError: _target = None if _target: target = _target.id elif len(rtarget) == 18: target = rrtarget[0] elif ctx.message.mentions: target = ctx.message.mentions[0].id else: await ctx.send( '**Invalid name! Name, nickname, name#0000, mention, or ID work.**' ) return if tmp: aentry = target if aentry not in self.bot.store['bot_admins']: self.bot.store['bot_admins'].append(aentry) await ctx.send( 'The user specified has successfully been added to the bot admin list!' ) else: await ctx.send('The user specified is already a bot admin!') else: await ctx.send( ctx.mention + ' You are not a bot admin, so you may not add others as admins!' ) @commands.command(aliases=['deladmin', 'admindel', 'adminrm']) async def rmadmin(self, ctx, *rrtarget: str): """Remove a user from the bot admin list. Usage: rmadmin [user]""" tmp = check_perms(ctx, ('bot_admin', )) if not rrtarget: await ctx.send( '**You need to specify a name, nickname, name#discriminator, or ID!**' ) return rtarget = ' '.join(rrtarget) try: _target = ctx.guild.get_member_named(rtarget) except AttributeError: _target = None if _target: target = _target.id elif len(rtarget) in range(15, 21): target = rrtarget[0] else: await ctx.send( '**Invalid name! Name, nickname, name#discriminator, or ID work.**' ) return if tmp: aentry = target try: self.bot.store['bot_admins'].remove(aentry) except ValueError: await ctx.send('The user specified is not a bot admin!') else: await ctx.send( 'The user specified has successfully been demoted!') else: await ctx.send( ctx.mention + ' You are not a bot admin, so you may not demote other admins!' ) @commands.command(aliases=['admins']) async def adminlist(self, ctx): """List all bot admins defined. Usage: adminlist""" alist = '' for i in self.bot.store['bot_admins']: nid = '' try: _name = ctx.guild.get_member(i) except AttributeError: _name = None if not _name: try: _name = await self.bot.get_user_info(i) except discord.NotFound: _name = 'UNKNOWN' nid = i if not nid: nid = _name.id alist += '**' + str(_name) + f'** (ID `{nid}`)\n' await ctx.send('The following people are bot admins:\n' + alist) @commands.command() @commands.check(commands.guild_only()) async def getprop(self, ctx, pname: str): """Fetch a property from the datastore. Usage: getprop [property name]""" try: pout = self.bot.store.get_prop(ctx.message, pname) except Exception: await ctx.send('⚠ An error occured.') return await ctx.send(pout) @commands.command() @commands.check(commands.guild_only()) async def setprop(self, ctx, pname: str, *, value: str): """Set the value of a property on guild level. Usage: setprop [property name] [value]""" echeck_perms(ctx, ('manage_guild', )) self.bot.store.set_prop(ctx.message, 'by_guild', pname, value) await ctx.send(':white_check_mark:') @commands.command(aliases=['getprefix', 'setprefix']) async def prefix(self, ctx, *prefix: str): """Get or set the command prefix. Usage: prefix {new prefix}""" sk = ' guild' prop = ('by_guild', 'command_prefix') if self.bot.selfbot: sk = '' prop = ('global', 'selfbot_prefix') if prefix: or_check_perms( ctx, ['manage_guild', 'manage_channels', 'manage_messages']) jprefix = ' '.join(prefix) self.bot.store.set_prop(ctx.message, *prop, jprefix) await ctx.send(':white_check_mark:') else: oprefix = self.bot.store.get_cmdfix(ctx.message) await ctx.send('**Current%s command prefix is: **`%s`' % (sk, oprefix)) async def progress(self, msg: discord.Message, begin_txt: str): """Play loading animation with dots and moon.""" fmt = '{0}{1} {2}' anim = '🌑🌒🌓🌔🌕🌝🌖🌗🌘🌚' anim_len = len(anim) - 1 anim_i = 0 dot_i = 1 while True: await msg.edit(content=fmt.format(begin_txt, ('.' * dot_i) + ' ' * (3 - dot_i), anim[anim_i])) dot_i += 1 if dot_i > 3: dot_i = 1 anim_i += 1 if anim_i > anim_len: anim_i = 0 await asyncio.sleep(1.1) @commands.command() @commands.check(commands.guild_only()) async def mute(self, ctx, *, member: discord.Member): """Mute someone on voice and text chat. Usage: mute [person's name]""" or_check_perms(ctx, [ 'mute_members', 'manage_roles', 'manage_channels', 'manage_messages' ]) status = await ctx.send('Muting... 🌚') pg_task = self.loop.create_task( asyncio.wait_for(self.progress(status, 'Muting'), timeout=30, loop=self.loop)) try: ch_perms = discord.PermissionOverwrite( **{p: False for p in muted_perms}) for channel in ctx.guild.channels: await channel.set_permissions(member, ch_perms) await member.__redit(mute=True, deafen=None, reason='Mute command was used on user') pg_task.cancel() await status.delete(reason='Deleting progress/status message') await ctx.send('Successfully muted **%s**!' % str(member)) except (discord.Forbidden, discord.HTTPException): pg_task.cancel() await status.delete(reason='Deleting progress/status message') await ctx.send('**I don\'t have enough permissions to do that!**') @commands.command() @commands.check(commands.guild_only()) async def unmute(self, ctx, *, member: discord.Member): """Unmute someone on voice and text chat. Usage: unmute [person's name]""" or_check_perms(ctx, ('mute_members', 'manage_roles', 'manage_channels', 'manage_messages')) status = await ctx.send('Unmuting... 🌚') pg_task = self.loop.create_task( asyncio.wait_for(self.progress(status, 'Unmuting'), timeout=30, loop=self.loop)) role_map = {r.name: r for r in member.roles} try: if 'Muted' in role_map: await member.remove_roles( role_map['Muted'], reason='Unmute command was used on user') ch_perms = discord.PermissionOverwrite( **{p: None for p in muted_perms}) for channel in ctx.guild.channels: await channel.set_permissions(member, ch_perms) await member.__redit(mute=False, deafen=None, reason='Unmute command was used on user') pg_task.cancel() await status.delete(reason='Deleting progress/status message') await ctx.send('Successfully unmuted **%s**!' % str(member)) except (discord.Forbidden, discord.HTTPException): pg_task.cancel() await status.delete(reason='Deleting progress/status message') await ctx.send('**I don\'t have enough permissions to do that!**') @commands.command() @commands.check(commands.guild_only()) async def ban(self, ctx, *, member: discord.Member): """Ban someone from the guild. Usage: ban [member]""" echeck_perms(ctx, ('ban_members', )) await ctx.send(':hammer: **Are you sure you want to ban ' + member.mention + '?**') if not (await self.bot.wait_for( 'message', timeout=6.0, check=lambda m: m.content.lower().startswith('y') and m.channel == ctx.channel and m.author == ctx.author)): await ctx.send('Not banning.') return await member.ban( reason= 'Ban was requested by command (from someone with the Ban Members permission)' ) await ctx.send(':hammer: Banned. It was just about time.')
class Channel(commands.Cog): """Channel related commands.""" def __init__(self, bot): self.bot = bot global confirm confirm = "confirm" @commands.check_any(commands.is_owner(), commands.has_permissions(manage_messages=True), commands.guild_only()) @commands.group( name="channel", aliases=["ch"], brief="Useful channel management commands", help= "Channel management commands, use the help command for a list of commands", invoke_without_command=True, case_insensitive=True) async def _channel(self, ctx): await ctx.send_help(ctx.command) @_channel.command( name="rename", aliases=["re"], brief="Renames channel.", help= "Renames the current channel or mentioned channel if argument passed.") async def _rename(self, ctx, channel, newname): pass #togglelock @commands.check_any(commands.is_owner(), commands.has_permissions(manage_channels=True), commands.guild_only()) @_channel.command( name="togglelock", aliases=['tl'], brief="Locks/Unlocks a channel, and optionally renames channel", case_insensitive=True, help= "Toggles send_messages perms for everyone. And renames channel if an argument is passed.)" ) async def _togglelock(self, ctx, *, channel_name=None): overwrite = ctx.channel.overwrites_for(ctx.guild.default_role) ch_name = channel_name try: if ch_name != None: channel = ctx.channel await channel.edit(name=ch_name) await ctx.send(f"Changed channel name to {ch_name}") if overwrite.send_messages != False: await ctx.channel.set_permissions(ctx.guild.default_role, send_messages=False) await ctx.send("Locked.") if overwrite.send_messages == False: await ctx.channel.set_permissions(ctx.guild.default_role, send_messages=True) await ctx.send("Unlocked.") except Exception as e: raise e #lock @commands.check_any(commands.is_owner(), commands.has_permissions(manage_channels=True), commands.guild_only()) @_channel.command(name="lock", brief="Locks channel(s).", help="Lock current/all channel(s)") async def _lock(self, ctx, channel=None): overwrite = ctx.channel.overwrites_for(ctx.guild.default_role) if channel == None and overwrite.send_messages == True: await ctx.channel.set_permissions(ctx.guild.default_role, send_messages=False) await ctx.send("Locked.") if channel == None and overwrite.send_messages != True: await ctx.send("This channel is already locked.") if channel == "all": await ctx.send( f"This will **lock** *all* channels. Type `{confirm}` to confirm." ) def check(m): return m.channel.id == ctx.channel.id and m.author.id == ctx.author.id try: msg = await self.bot.wait_for("message", timeout=30, check=check) except asyncio.TimeoutError: return await ctx.send("Time's up. Aborted.") if msg.content.lower() != "confirm": return await ctx.send("Aborted.") msg = await ctx.send("Locking all channels...") for c in ctx.guild.channels: if overwrite.send_messages != False: await c.set_permissions(ctx.guild.default_role, send_messages=False) await ctx.send("Locked all channels ✅.") #unlock @commands.check_any(commands.is_owner(), commands.has_permissions(manage_channels=True), commands.guild_only()) @_channel.command(name="unlock", brief="Unlocks channel(s).", help="Unlock current/all channel(s)") async def _unlock(self, ctx, channel=None): overwrite = ctx.channel.overwrites_for(ctx.guild.default_role) if channel == None and overwrite.send_messages == False: await ctx.channel.set_permissions(ctx.guild.default_role, send_messages=True) await ctx.send("Unlocked.") if channel == None and overwrite.send_messages != False: await ctx.send("This channel is already unlocked.") if channel == "all": await ctx.send( f"This will **unlock** *all* channels. Type `{confirm}` to confirm." ) def check(m): return m.channel.id == ctx.channel.id and m.author.id == ctx.author.id try: msg = await self.bot.wait_for("message", timeout=30, check=check) except asyncio.TimeoutError: return await ctx.send("Time's up. Aborted.") if msg.content.lower() != "confirm": return await ctx.send("Aborted.") msg = await ctx.send("Unlocking all channels...") for c in ctx.guild.channels: if overwrite.send_messages != True: await c.set_permissions(ctx.guild.default_role, send_messages=True) await ctx.send("Unlocked all channels ✅.") @commands.check_any(commands.is_owner(), commands.has_permissions(manage_channels=True), commands.guild_only()) @_channel.group( name="strip", aliases=["split"], brief="Strips and renames channels.", help= f"Strips off the second part of every channels' name after the separator, and only keeps the first half before the separator\n\nsingle channel\n\n{prefix}channel strip <channel> <separator>.", invoke_without_command=True, case_insensitive=True) async def _strip(self, ctx, channel: discord.TextChannel = None, *, separator): channel = channel or ctx.channel stripped = channel.name.split(separator)[0] channel_name = channel.name if channel != "all" and channel != "current": await ctx.send( f"This will **rename** {channel.mention} to **{stripped}**. This action cannot be undone. Type `{confirm}` to confirm." ) def check(m): return m.channel.id == ctx.channel.id and m.author.id == ctx.author.id try: msg = await self.bot.wait_for("message", timeout=30, check=check) except asyncio.TimeoutError: return await ctx.send("Time's up. Aborted.") if msg.content.lower() != "confirm": return await ctx.send("Aborted.") if channel != "all" and channel != "current": await ctx.send( f"Stripping {channel.mention}'s name with separator `{separator}` ..." ) if separator in channel_name: new_name = stripped await channel.edit(name=new_name) await ctx.send(f"Done stripping the name of {channel.mention} ✅.") @_strip.command(name="current", brief="Strips current channel.", help="Strips the channel the command was used in.") async def _current(self, ctx, separator): channel = ctx.channel channel_name = channel.name stripped = channel.name.split(separator)[0] await ctx.send( f"This will **rename** {channel.mention} to **{stripped}**. This action cannot be undone. Type `{confirm}` to confirm." ) def check(m): return m.channel.id == ctx.channel.id and m.author.id == ctx.author.id try: msg = await self.bot.wait_for("message", timeout=30, check=check) except asyncio.TimeoutError: return await ctx.send("Time's up. Aborted.") if msg.content.lower() != "confirm": return await ctx.send("Aborted.") await ctx.send( f"Stripping {channel.mention}'s name with separator `{separator}` ..." ) if separator in channel_name: new_name = stripped await channel.edit(name=new_name) await ctx.send(f"Done stripping the name of {channel.mention} ✅.") @_strip.command(name="all", brief="Strips all channels.", help="Strips all channels in a server.") async def _all(self, ctx, separator): await ctx.send( f"This will **strip with `{separator}` and rename** *all* channels. This action cannot be undone. Type `{confirm}` to confirm." ) def check(m): return m.channel.id == ctx.channel.id and m.author.id == ctx.author.id try: msg = await self.bot.wait_for("message", timeout=30, check=check) except asyncio.TimeoutError: return await ctx.send("Time's up. Aborted.") if msg.content.lower() != "confirm": return await ctx.send("Aborted.") await ctx.send( f"Stripping all channels' names with separator ` {separator} ` ..." ) for channel in ctx.guild.channels: stripped = channel.name.split(separator)[0] channel_name = channel.name if separator in channel_name: new_name = stripped await channel.edit(name=new_name) await ctx.send("Done stripping all channels' names ✅.")
def __init__(self, bot): super().__init__(bot) for cmd in self.get_commands(): cmd.add_check(commands.guild_only()) if cmd.name == '환영메시지': cmd.add_check(self.check.subcmd_valid)
class Utility(Cog): """Random commands that can be useful here and there. Settings, properties, and other stuff can be found here. """ def __init__(self, bot): super().__init__(bot) self.logger = self.logger.getChild('utility') @commands.command() @commands.check(commands.guild_only()) async def icon(self, ctx): """Retrive the current guild's icon. Usage: icon""" sname = '**' + ctx.guild.name + '**' iurl = ctx.guild.icon_url if iurl: await ctx.send('Here is the link to the icon for ' + sname + ': <' + iurl + '>') else: await ctx.send('The current guild, ' + sname + ', does not have an icon set! :slight_frown:') @commands.command(aliases=['echo']) async def say(self, ctx, *, message: str): """Repeat your message. Usage: say [message]""" await ctx.send(message) @commands.command(aliases=['whois', 'who', 'userinfo', 'uinfo', 'u']) async def user(self, ctx, *users: str): """Get tons of info on an user or some users. Spaces, multiuser, and cross-guild IDs work. Usage: user {user(s)}""" targets = [] s = ctx.guild if users: # huge complicated mess for spaces, # multiuser, nicknames, mentions, IDs, # names, and more in one go. members = {} for i in getattr(s, 'members', []): members[i.mention] = i members[i.id] = i members[i.display_name] = i members[i.name] = i members[str(i)] = i for i in users: try: member = s.get_member(i) except AttributeError: try: member = await self.bot.get_user_info(i) except discord.HTTPException: member = None if member: targets.append(member) else: try: member = await self.bot.get_user_info(i) except discord.HTTPException: member = None if member: targets.append(member) names = [] _i = 0 while _i < len(users): names.append(users[_i]) with suppress(KeyError): if ' '.join(names) in members: targets.append(members[' '.join(names)]) names = [] elif _i + 1 == len(users): targets.append(members[users[0]]) _i = -1 users = users[1:] names = [] _i += 1 if not targets: await ctx.send( '**No matching users, try again! Name, nickname, name#0000 (discriminator), or ID work. Spaces do, too!**' ) return else: targets.append(ctx.author) targets = list(OrderedDict.fromkeys(targets)) for target in targets: d_name = target.display_name avatar_url = target.avatar_url try: t_roles = target.roles except AttributeError: t_roles = [] try: t_game = target.game except AttributeError: t_game = None is_guild = ctx.guild is not None with suppress(ValueError, AttributeError): t_roles.remove(target.guild.default_role) r_embed = discord.Embed(color=random.randint(0, 255**3 - 1)) r_embed.set_author(name=str(target), icon_url=avatar_url, url=avatar_url) r_embed.set_thumbnail(url=avatar_url) #top right r_embed.set_footer(text=str(target), icon_url=avatar_url) r_embed.add_field( name='Nickname', value=('None' if d_name == target.name else d_name)) r_embed.add_field(name='User ID', value=target.id) r_embed.add_field(name='Creation Time', value=target.created_at.strftime(absfmt)) r_embed.add_field(name='Guild Join Time', value=target.joined_at.strftime(absfmt) if is_guild else 'Couldn\'t fetch') r_embed.add_field( name='Roles', value=', '.join([str(i) for i in t_roles]) if t_roles else 'None') r_embed.add_field(name='Status', value=status_map[str(target.status)] if is_guild else 'Couldn\'t fetch') try: r_embed.add_field(name='Currently Playing', value=(str(t_game) if t_game else 'Nothing')) except TypeError: r_embed.add_field(name='Currently Playing', value='Nothing 😦') await ctx.send(embed=r_embed) @commands.command(aliases=['sinfo', 'serverinfo', 'guild', 'ginfo'], no_pm=True) async def guildinfo(self, ctx): """Get loads of info about this guild. Usage: guildinfo""" s = ctx.guild ach = s.channels chlist = [len(ach), 0, 0] for i in ach: if isinstance(i, discord.TextChannel): chlist[1] += 1 else: chlist[2] += 1 iurl = s.icon_url s_reg = str(s.region) r_embed = discord.Embed(color=random.randint(0, 255**3 - 1)) if iurl: thing = {'url': iurl} else: thing = {} r_embed.set_author(name=s.name, **thing, icon_url=(iurl if iurl else ctx.me.avatar_url)) r_embed.set_footer(text=ctx.me.display_name, icon_url=ctx.me.avatar_url) if iurl: r_embed.set_image(url=iurl) r_embed.add_field(name='ID', value=s.id) r_embed.add_field(name='Members', value=len(s.members)) r_embed.add_field(name='Channels', value=ch_fmt.format(*[str(i) for i in chlist])) r_embed.add_field(name='Roles', value=len(s.roles)) r_embed.add_field(name='Custom Emojis', value=len(s.emojis)) r_embed.add_field(name='Region (Location)', value=str(s.region).replace( '-', ' ').title().replace('Eu ', 'EU ').replace( 'Us ', 'US ').replace('Vip', 'VIP ')) r_embed.add_field(name='Owner', value=str(s.owner)) r_embed.add_field( name='Default Channel', value=f'<#{s.default_channel.id}>\n(#{s.default_channel.name})' if s.default_channel is not None else 'None (deleted)') r_embed.add_field(name='Admins Need 2FA', value=('Yes' if s.mfa_level else 'No')) r_embed.add_field(name='Verification Level', value=v_level_map[str(s.verification_level)]) await ctx.send(embed=r_embed) @commands.command(aliases=['goldmine', 'about']) async def info(self, ctx): """Get bot info. Usage: info""" ach = self.bot.get_all_channels() chlist = [0, 0, 0] for i in ach: chlist[0] += 1 if isinstance(i, discord.TextChannel): chlist[1] += 1 else: chlist[2] += 1 up = self.bot.format_uptime() ram = self.bot.get_ram() got_conversion = ram[0] emb = discord.Embed(color=random.randint(0, 255**3 - 1)) emb.set_author(name=ctx.me.display_name, url='https://khronodragon.com/', icon_url=ctx.me.avatar_url) emb.set_footer( text='Made in Python 3.6+ with Discord.py %s' % self.bot.lib_version, icon_url= 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c3/Python-logo-notext.svg/400px-Python-logo-notext.svg.png' ) emb.add_field(name='Guilds', value=len(self.bot.guilds)) emb.add_field(name='Author', value='Dragon5232#1841') emb.add_field(name='Uptime', value=up) emb.add_field(name='Local Time', value=time.strftime(absfmt, time.localtime())) emb.add_field(name='Cogs Loaded', value=len(self.bot.cogs)) emb.add_field(name='Command Calls', value=sum(self.bot.command_calls.values())) emb.add_field(name='Memory Used', value=(str(round(ram[1], 1)) + ' MB (%s MiB)' % str(round(ram[2], 1))) if got_conversion else 'Couldn\'t fetch') emb.add_field(name='Members Seen', value=sum(g.member_count for g in self.bot.guilds)) emb.add_field(name='Channels', value=ch_fmt.format(*[str(i) for i in chlist])) emb.add_field(name='Custom Emojis', value=len(self.bot.emojis)) emb.add_field(name='Commands', value=str(len(self.bot.all_commands))) emb.add_field(name='ID', value=ctx.me.id) if self.bot.user.id == 239775420470394897: emb.add_field(name='Invite Link', value='https://tiny.cc/goldbot') await ctx.send(home_broadcast, embed=emb) @commands.cooldown(1, 2.95, type=commands.BucketType.guild) @commands.command(aliases=['pong', 'latency']) async def ping(self, ctx): """Ping, pong! Usage: ping""" begin_time = datetime.now() msg = await ctx.send('**Pong!** | I wonder how long this takes...') await msg.edit(content='**Pong!** | I really do wonder...') time_diff = datetime.now() - begin_time await msg.edit(content='**Pong!** Responded in {}ms.'.format( round((time_diff.total_seconds() / 2) * 1000, 2))) @commands.command(aliases=['ram', 'memory', 'mem']) async def uptime(self, ctx): """Report the current uptime of the bot. Usage: uptime""" up = self.bot.format_uptime() ram = self.bot.get_ram() got_conversion = ram[0] ram_final = (' RAM usage is **' + str(round(ram[1], 1)) + ' MB (%s MiB)**.' % str(round(ram[2], 1))) if got_conversion else '' await ctx.send(ctx.mention + ' I\'ve been up for **' + up + '**.' + ram_final) @commands.command(aliases=['addbot']) async def invite(self, ctx, *rids: str): """Generate an invite link for myself or another bot. Usage: invite {optional: bot ids}""" ids = list(rids) msg = [] if not ids: ids.append(self.bot.user.id) for iid in ids: try: int(iid) if len(iid) in range(16, 20): if iid == self.bot.user.id: msg.append( '<https://discordapp.com/api/oauth2/authorize?client_id={}&scope=bot&permissions={}>' .format(iid, self.bot.perm_mask)) else: msg.append( '<https://discordapp.com/api/oauth2/authorize?client_id=%s&scope=bot&permissions=3072>' % iid) else: msg.append('**Invalid ID!**') except ValueError: msg.append('**Invalid ID!**') if msg: await ctx.send('\n'.join(msg)) @commands.command(aliases=['website']) async def home(self, ctx): """Get my "contact" info. Usage: home""" await ctx.send(home_broadcast) async def poll_task(self, emojis, msg, poll_table): while True: user, r = await self.bot.wait_for( 'reaction_add', check=lambda r, u: r.message == msg and u != msg.guild.me and r .emoji in emojis) if user not in poll_table[str(r.emoji)]: poll_table[str(r.emoji)].append(user) @commands.cooldown(1, 10, type=commands.BucketType.user) @commands.command() async def poll(self, ctx, *rquestion: str): """Start a public poll with reactions. Usage: poll [emojis] [question] [time in seconds]""" async def cem_help(emojis, raw_c_emojis, cem_map, c_emojis): """Custom emoji helper.""" if raw_c_emojis: try: for i in ctx.guild.emojis: cem_map[str(i)] = i except AttributeError: return for i in raw_c_emojis: try: c_emojis.append(cem_map[i]) except KeyError: await ctx.send( '**Custom emoji `%s` doesn\'t exist!**' % i) return emojis += c_emojis question = '' if rquestion: question = ' '.join(rquestion) else: await ctx.send('**You must specify a question!**') return stime = 0.0 cem_map = {} highpoints = None try: stime = float(rquestion[-1:][0]) except ValueError: await ctx.send('**You must provide a valid poll time!**') return _question = question.split() del _question[-1:] question = ' '.join(_question) try: # UCS-4 highpoints = re.compile(u'[\U00010000-\U0010ffff\u2615]') except re.error: # UCS-2 highpoints = re.compile(u'[\uD800-\uDBFF][\uDC00-\uDFFF]') u_emojis = re.findall(highpoints, question) raw_c_emojis = re.findall( re.compile(r'<:[a-z]+:[0-9]{18}>', flags=re.IGNORECASE), question) c_emojis = [] emojis = u_emojis await cem_help(emojis, raw_c_emojis, cem_map, c_emojis) emojis = list(OrderedDict.fromkeys(emojis)) for ri in emojis: i = str(ri) question = question.replace(' ' + i, '') question = question.replace(i + ' ', '') question = question.replace(i, '') question = question.strip() if not emojis: await ctx.send('**You must specify some emojis!**') return elif len(emojis) < 2: await ctx.send('**You need at least 2 emojis to poll!**') return msg_key = ctx.mention + ' is now polling:\n \u2022 ' + question + '\n' msg = await ctx.send(msg_key + '**Adding reactions, please wait...**') for emoji in emojis: await msg.add_reaction(emoji) await asyncio.sleep(0.14) await msg.edit(content=msg_key + '**Poll is active, vote!**') emojis = list(emojis) poll_table = OrderedDict((str(i), []) for i in emojis) task = self.loop.create_task(self.poll_task(emojis, msg, poll_table)) await asyncio.sleep(stime) task.cancel() _vote_table = {i: len(poll_table[i]) for i in poll_table} vote_table = OrderedDict( reversed(sorted(_vote_table.items(), key=lambda t: t[1]))) _totals = '\n'.join([ str(i) + ': {0} votes'.format(str(vote_table[i])) for i in vote_table ]) winner = max(vote_table, key=vote_table.get) await ctx.send('**Poll time is over, stopped! Winner is...** ' + str(winner) + '\nResults were:\n' + _totals) await msg.edit(content=msg_key + '**Poll ended.**') @commands.command(aliases=['memegen'], hidden=True) async def meme(self, ctx, *, pre_text: str): """Generate a meme! Usage: meme [top text] [bottom text]""" char_table = { '-': '--', '_': '__', '?': '~q', '%': '~p', '#': '~h', # TODO: make '/': '~s', '"': "''", '\n': ' ' } for key in char_table: pre_text = pre_text.replace(key, char_table[key]) pre_text = pre_text.replace(' ', '__bottom__') pre_text = pre_text.replace(' ', '-') if '__bottom__' in pre_text: segments = pre_text.split('__bottom__') else: segments = textwrap.wrap(pre_text, width=int(len(pre_text) / 2)) with async_timeout.timeout(10): async with self.bot.cog_http.get( 'https://memegen.link/api/templates/') as r: rtext = await r.text() templates = list(json.loads(rtext).values()) rtemp = random.choice(templates) meme_url = rtemp + '/' + segments[0] + '/' + segments[1] + '.jpg' async with self.bot.cog_http.get(meme_url) as r: raw_image = await r.read() await ctx.send(file=discord.File(BytesIO(raw_image), 'meme.jpg')) @commands.command(aliases=['statistics', 'guilds', 'channels', 'users']) async def stats(self, ctx): """Show some basic stats. Usage: stats""" fmt = '''Stats: (get more with `{1}info`) **Guilds**: {2} **Channels**: {3} **Members**: {4} **Uptime**: {5}''' up = self.bot.format_uptime() await ctx.send( fmt.format(ctx.message, ctx.prefix, len(self.bot.guilds), sum(len(s.channels) for s in self.bot.guilds), sum(len(s.members) for s in self.bot.guilds), up)) @commands.command(aliases=['randcolor', 'rc', 'randcolour', 'rcolour']) async def rcolor(self, ctx): """Generate a random color. Usage: rcolor""" col_rgb = [random.randint(1, 255) for i in range(0, 3)] col_str = '0x%02X%02X%02X' % (col_rgb[0], col_rgb[1], col_rgb[2]) await ctx.send( embed=discord.Embed(color=int(col_str, 16), title='Hex: ' + col_str.replace('0x', '#') + ' | RGB: ' + ', '.join([str(c) for c in col_rgb]) + ' | Integer: ' + str(int(col_str, 16)))) @commands.command(aliases=['character', 'char', 'cinfo', 'unicode']) async def charinfo(self, ctx, *, uchars: str): """Get the Unicode info for a character or characters. Usage: charinfo [character(s)]""" no_preview = ['\u0020', '\uFEFF'] cinfo = commands.Paginator( prefix='', suffix='', max_size=(1999 if self.bot.selfbot else 2000)) for char in list(uchars.replace('\n', '')): hexp = str(hex(ord(char))).replace('0x', '').upper() while len(hexp) < 4: hexp = '0' + hexp preview = f' (`{char}`)' cinfo.add_line(f'U+{hexp} {unicodedata.name(char)} {char}' + (preview if char not in no_preview else '')) if len(cinfo.pages) > 5: await ctx.send('Too long, trimming to 5 pages.') for page in cinfo.pages[0:5]: await ctx.send(page) @commands.command() async def encode(self, ctx, *, content: str): """Encode your text into Goldcode! Usage: encode [text]""" await ctx.send('```' + (b_encode(content)) + '```') @commands.command() async def decode(self, ctx, *, content: str): """Decode your text from Goldcode! Usage: decode [encoded text]""" await ctx.send('```' + (b_decode(content)) + '```') @commands.cooldown(1, 6.75, type=commands.BucketType.user) @commands.command(aliases=['mc']) async def minecraft(self, ctx, *, server_ip: str): """Get information about a Minecraft server. Usage: minecraft [server address]""" port = 25565 port_split = server_ip.split(':') server = port_split[0].replace('/', '') if len(port_split) > 1: try: port = int(port_split[1]) except ValueError: pass if ('.' not in server) or (' ' in server_ip): await ctx.send(':warning: Invalid address.') return try: self.logger.info('Connecting to Minecraft server ' + server + ':' + str(port) + '...') with async_timeout.timeout(5): data = await self.loop.run_in_executor(None, mclib.get_info, server, port) except Exception as e: await ctx.send( f':warning: Couldn\'t get server info for `{server}:{port}`.') return desc = '' server_type = 'Vanilla' def decode_extra_desc(): final = [] format_keys = { 'bold': '**', 'italic': '*', 'underlined': '__', 'strikethrough': '~~' } for e in data['description']['extra']: item = e['text'] for fkey in format_keys: if e.get(fkey, False): int_key = '%{f:' + fkey + '}$' item = int_key + item + int_key final.append(item) final = ''.join(final) for fkey in format_keys: int_key = '%{f:' + fkey + '}$' final = final.replace(int_key * 3, '').replace(int_key * 2, '') final = final.replace(int_key, format_keys[fkey]) return final if isinstance(data['description'], dict): if 'text' in data['description']: if data['description']['text']: desc = data['description']['text'] else: desc = decode_extra_desc() else: desc = decode_extra_desc() elif isinstance(data['description'], str): desc = data['description'] else: desc = str(data['description']) def decode_section_code(): formats = { 'l': '**', 'n': '__', 'o': '*', 'k': '', 'm': '~~', 'k': '**', 'r': '' } # k = obf, r = reset state = '' desc = re.sub(r'\u00a7[4c6e2ab319d5f780lnokmr]', '', desc) emb = discord.Embed(title=server + ':' + str(port), description=desc, color=random.randint(0, 255**3 - 1)) emb.set_footer(text=ctx.me.display_name, icon_url=ctx.me.avatar_url) emb.add_field(name='Players', value=str(data['players']['online']) + '/' + str(data['players']['max'])) if data['players'].get('sample', False): content = re.sub( r'\u00a7[4c6e2ab319d5f78lnokmr]', '', smartjoin([p['name'] for p in data['players']['sample']])) if len(content) <= 1024: emb.add_field(name='Players Online', value=content) else: pages = textwrap.wrap(content, width=1024) for page in pages: emb.add_field(name='Players Online', value=page) emb.add_field(name='Version', value=re.sub(r'\u00a7[4c6e2ab319d5f78lnokmr]', '', data['version']['name'])) emb.add_field(name='Protocol Version', value=data['version']['protocol']) if 'modinfo' in data: if 'modList' in data['modinfo']: if data['modinfo']['modList']: content = smartjoin([ m['modid'].title() + ' ' + m['version'] for m in data['modinfo']['modList'] ]) if len(content) <= 1024: emb.add_field(name='Mods', value=content) else: pages = textwrap.wrap(content, width=1024) for page in pages: emb.add_field(name='Mods', value=page) if data['modinfo'].get('type', False): t = data['modinfo']['type'] if t.lower() == 'fml': server_type = 'Forge / FML' else: server_type = t.title() emb.add_field(name='Server Type', value=server_type) emb.add_field(name='Ping', value=str(round(data['latency_ms'], 2)) + 'ms') await ctx.send(embed=emb) @commands.cooldown(1, 20, type=commands.BucketType.user) @commands.command() async def contact(self, ctx, *, message: str): """Contact the bot owner with a message. Usage: contact [message]""" for m in ctx.message.mentions: message = message.replace(m.mention, '@' + str(m)) msg_object = { 'message': message, 'user': str(ctx.author), 'nick': ctx.author.display_name, 'message_id': ctx.message.id, 'user_id': ctx.author.id, 'channel_id': ctx.channel.id, 'pm': isinstance(msg.channel, discord.abc.PrivateChannel), 'time': str(ctx.message.timestamp), 'timestamp': ctx.message.timestamp.timestamp(), 'contains_mention': bool(ctx.message.mentions), } if ctx.guild: msg_object.update({ 'guild': ctx.guild.name, 'guild_id': ctx.guild.id, 'guild_members': len(ctx.guild.members), 'channel': ctx.channel.name }) self.bot.store['owner_messages'].append(msg_object) await ctx.send(':thumbsup: Message recorded.') @commands.command(aliases=['rprof', 'rp']) async def rprofile(self, ctx): """Generate a random profile. Usage: rprofile""" name_overrides = {'cvv': 'CVV', 'cid': 'CID'} excluded = [ 'password', 'sexual_orientation', 'avatar', 'identifier', 'title', 'language', 'paypal', 'worldview', 'views_on', 'political_views', 'surname' ] if not ctx.author.avatar_url: ctx.author.avatar_url = ctx.author.default_avatar_url emb = discord.Embed(color=random.randint(1, 255**3 - 1)) emb.set_author(name=ctx.author.display_name, icon_url=ctx.author.avatar_url) p = elizabeth.Personal() traits = {} calls = { d: getattr(p, d) for d in dir(p) if (not d.startswith('_')) and hasattr(getattr(p, d), '__call__') } for call in calls: if call not in excluded: if call in name_overrides: f_name = name_overrides[call] else: f_name = call.replace('_', ' ').title() traits[f_name] = calls[call]() emb.set_thumbnail(url=p.avatar()) emb.title = traits['Full Name'].split()[0] for trait in traits: emb.add_field(name=trait, value=str(traits[trait])) await ctx.send(embed=emb) @commands.cooldown(1, 5.75, type=commands.BucketType.user) @commands.command(aliases=['qr']) async def qrcode(self, ctx, *, text: str): """Create a QR code. Usage: qrcode [text to use]""" img_bytes = BytesIO() image = await self.loop.run_in_executor(None, qrcode.make, text) image.save(img_bytes, format='PNG') img_bytes.seek(0) await ctx.send(file=discord.File(img_bytes, 'qrcode.png')) @commands.command() async def avatar(self, ctx, *, target: discord.User): """Get someone's avatar. Usage: avatar [member]""" await ctx.send(target.avatar_url) @commands.command() async def ocr(self, ctx): """OCR an image. Usage: ocr [attach an image]""" or_check_perms(ctx, ('bot_owner', )) warnings.simplefilter('error', Image.DecompressionBombWarning) if ctx.message.attachments: with async_timeout.timeout(5): async with self.bot.cog_http.get( ctx.message.attachments[0].proxy_url) as r: raw_image = await r.read() else: await ctx.send(':warning: No attachment found.') return img_bytes = BytesIO(raw_image) image = Image.open(img_bytes) text = tesserocr.image_to_text(image) if text: await ctx.send(text) else: await ctx.send('No results.') @commands.command(aliases=['cm_discrim']) async def discrim(self, ctx, *, discriminator: str): """Look up users by discriminator. Usage: discrim [discriminator]""" d = discriminator targets = list( set( str(m) for m in self.bot.get_all_members() if m.discriminator == d)) if targets: await ctx.send('**I found: **\n' + '\n'.join(targets)) else: await ctx.send( 'I found no matches. Maybe I\'m not in a guild with them?') @commands.command(aliases=['perms']) async def permissions(self, ctx): """Get your permissions here. Usage: permissions""" perms = [ '**' + k[0].replace('_', ' ').title() + '**' for k in list(ctx.author.permissions_in(ctx.channel)) if k[1] ] if '**Administrator**' in perms: perms.remove('**Administrator**') perms.append('be an **administrator**') if '**Send Tts Messages**' in perms: perms[perms.index( '**Send Tts Messages**')] = '**Send TTS Messages**' await ctx.send('You can ' + smartjoin(perms) + '!') @commands.group(name='xkcd') async def cmd_xkcd(self, ctx): """Get a xkcd comic. Usage: xkcd {stuff}""" if ctx.invoked_subcommand is None: await self.bot.send_cmd_help(ctx) @commands.cooldown(1, 4, type=commands.BucketType.user) @cmd_xkcd.command(name='random') async def xkcd_random(self, ctx): """Get a random comic from xkcd. Usage: xkcd random""" comic = await xkcd.random_comic() emb = discord.Embed(color=random.randint(1, 255**3 - 1), title=comic.title) emb.set_image(url=comic.image_link) emb.set_footer(text=comic.alt_text) await ctx.send(embed=emb) @commands.cooldown(1, 4, type=commands.BucketType.user) @cmd_xkcd.command(name='latest') async def xkcd_latest(self, ctx): """Get the latest comic from xkcd. Usage: xkcd latest""" comic = await xkcd.latest_comic() emb = discord.Embed(color=random.randint(1, 255**3 - 1), title=comic.title) emb.set_image(url=comic.image_link) emb.set_footer(text=comic.alt_text) await ctx.send(embed=emb) @commands.cooldown(1, 4, type=commands.BucketType.user) @cmd_xkcd.command(name='number') async def xkcd_number(self, ctx, number: int): """Get the Nth comic from xkcd. Usage: xkcd number [number]""" try: comic = await xkcd.get_comic(number) except xkcd.InvalidComic: await ctx.send(':warning: That comic doesn\'t exist.') return emb = discord.Embed(color=random.randint(1, 255**3 - 1), title=comic.title) emb.set_image(url=comic.image_link) emb.set_footer(text=comic.alt_text) await ctx.send(embed=emb) @commands.command(aliases=['zws', 'u200b', '200b']) async def zwsp(self, ctx, number: int = 1): """Output a number of ZWSPs. Usage: zwsp {number = 1}""" if number > 2000: await ctx.send('I can\'t give you more than 2000 ZWSPs.') elif number > 0: await ctx.send('\u200b' * number) else: await ctx.send('I can\'t give you zero ZWSPs.') @commands.command() async def b64decode(self, ctx, *, b64: str): """Decode some base64 data. Usage: b64decode [base64]""" br = base64.b64decode(b64) try: m = br.decode('utf-8') except ValueError: m = '```' + str(br)[2:][:-1] + '```' await ctx.send(m) @commands.command() async def b64encode(self, ctx, *, b64: str): """Encode some base64 data. Usage: b64encode [base64]""" br = base64.b64encode(b64.encode('utf-8')) try: m = br.decode('utf-8') except ValueError: m = '```' + str(br)[2:][:-1] + '```' await ctx.send(m) @commands.command(aliases=['ttsspam', 'tts_spam']) async def ttspam(self, ctx, *, text: str): """Spam a message with TTS. **This may get you banned from guilds.** Usage: ttspam [message]""" or_check_perms(ctx, ('manage_messages', )) m = await ctx.send(textwrap.wrap((text + ' ') * 2000, width=2000)[0], tts=True) await asyncio.sleep(0.1) await m.delete( reason= 'Deleting message used for a ttspam command (only usable by people with Manage Messages)' ) @commands.command(aliases=['ip', 'rdns', 'reverse_dns', 'reversedns']) async def ipinfo(self, ctx, *, ip: str): """Get the GeoIP and rDNS data for an IP. Usage: ipinfo [ip/domain]""" emb = discord.Embed(color=random.randint(1, 255**3 - 1)) emb.set_author(icon_url=ctx.me.avatar_url, name='IP Data') with async_timeout.timeout(5): async with self.bot.cog_http.get('https://freegeoip.net/json/' + ip) as r: data_res = await r.json() rdns = 'Failed to fetch' try: with async_timeout.timeout(6): rdns = (await self.loop.run_in_executor(None, socket.gethostbyaddr, data_res['ip']))[0] except Exception: pass emb.add_field(name='IP', value=data_res['ip']) emb.add_field(name='Reverse DNS', value=rdns) emb.add_field(name='Country', value=data_res['country_name'] + ' (%s)' % data_res['country_code']) region_val = data_res['region_name'] + ' (%s)' % data_res['region_code'] emb.add_field( name='Region', value=(region_val if region_val != ' ()' else 'Not specified')) emb.add_field( name='City', value=(data_res['city'] if data_res['city'] else 'Not specified')) emb.add_field(name='ZIP Code', value=(data_res['zip_code'] if data_res['zip_code'] else 'Not specified')) emb.add_field(name='Timezone', value=(data_res['time_zone'] if data_res['time_zone'] else 'Not specified')) emb.add_field(name='Longitude', value=data_res['longitude']) emb.add_field(name='Latitude', value=data_res['latitude']) emb.add_field(name='Metro Code', value=(data_res['metro_code'] if data_res['metro_code'] != 0 else 'Not specified')) await ctx.send(embed=emb) @commands.command() async def dial(self, ctx, *, number: str): """Dial someone on the phone! Usage: dial [phone number]""" self.logger.info('Dialing ' + number + '...') await ctx.send(':telephone: **Dialing {}...**'.format(number)) await asyncio.sleep((random.randint(1, 3) + random.uniform(0, 1)) * random.uniform(0.4, 1.6) + random.uniform(0, 1)) await ctx.send('**No answer.**') @commands.command(aliases=['define']) async def urban(self, ctx, *, term: str): """Define something, according to Urban Dictionary. Usage: urban [term]""" with async_timeout.timeout(5): async with self.bot.cog_http.get( 'http://api.urbandictionary.com/v0/define', params={'term': term}) as r: data_res = await r.json() try: word = data_res['list'][0] except IndexError: await ctx.send('No results.') return emb = discord.Embed(color=random.randint(0, 255**3 - 1), title=word['word']) emb.set_author( name='Urban Dictionary', url=word['permalink'], icon_url= 'https://images.discordapp.net/.eJwFwdsNwyAMAMBdGICHhUPIMpULiCAlGIHzUVXdvXdf9cxLHeoUGeswJreVeGa9hCfVoitzvQqNtnTi25AIpfMuXZaBDSM4G9wWAdA5vxuIAQNCQB9369F7a575pv7KLUnjTvOjR6_q9wdVRCZ_.BorCGmKDHUzN6L0CodSwX7Yv3kg' ) emb.set_footer(text=datetime.now().strftime(absfmt)) definition = word['definition'] if definition: def_pages = textwrap.wrap(definition, width=1024) for pg in def_pages[:3]: emb.add_field(name='Definition', value=pg, inline=False) else: emb.add_field(name='Definition', value='None?!?!', inline=False) example = word['example'] if example: ex_pages = textwrap.wrap(example, width=1024) for pg in ex_pages[:3]: emb.add_field(name='Example', value=pg, inline=False) else: emb.add_field(name='Example', value='None?!?!', inline=False) emb.add_field(name='👍', value=word['thumbs_up']) emb.add_field(name='👎', value=word['thumbs_down']) await ctx.send(embed=emb) @commands.command(aliases=['nickname', 'setnick']) @commands.check(commands.guild_only()) async def nick(self, ctx, *, nick: str): """Set your nickname. Usage: nick [new nickname]""" if ctx.author.guild_permissions.change_nickname: await ctx.author.edit(nick=nick, reason='User requested using command') await ctx.send(':thumbsup: Done.') else: await ctx.send( ':x: You don\'t have permission to change your nickname.') @commands.command() async def bleach(self, ctx): """Get some bleach. NOW. Usage: bleach""" emb = discord.Embed(color=random.randint(0, 255**3 - 1), title='Bleach') emb.set_image( url= 'https://upload.wikimedia.org/wikipedia/commons/d/d3/Clorox_Bleach_products.jpg' ) await ctx.send(embed=emb) @commands.command() async def mcskin(self, ctx, *, username: str): """Get a Minecraft player's skin. Usage: mcskin [username]""" un = username.replace('\u200b', '').replace('/', '').replace('\u200e', '') if not re.match(r'^[a-zA-Z0-9_]+$', un): await ctx.send(':warning: Invalid username.') return emb = discord.Embed(color=random.randint(0, 255**3 - 1), title=un + "'s skin") emb.set_image(url='https://mcapi.ca/skin/' + un + '/150/true') await ctx.send(embed=emb) @commands.command() async def mchead(self, ctx, *, username: str): """Get a Minecraft player's head. Usage: mchead [username]""" un = username.replace('\u200b', '').replace('/', '').replace('\u200e', '') if not re.match(r'^[a-zA-Z0-9_]+$', un): await ctx.send(':warning: Invalid username.') return emb = discord.Embed(color=random.randint(0, 255**3 - 1), title=un + "'s head") emb.set_image(url='https://mcapi.ca/avatar/' + un + '/150/true') await ctx.send(embed=emb)
class Useful(commands.Cog): """Useful commands""" def __init__(self, bot): self.bot = bot #wiki @commands.command( name="wiki", aliases=["wikipedia"], brief="Searches wikipedia for info.", help= "Use this command to look up anything on wikipedia. Sends the first 10 sentences from wikipedia." ) async def wiki(self, ctx, *, arg=None): try: if arg == None: await ctx.send("Please, specify what do you want me to search." ) elif arg: msg = await ctx.send("Fetching...") start = arg.replace(" ", "") end = wikipedia.summary(start) await msg.edit(content=f"```py\n{end}\n```") except: try: start = arg.replace(" ", "") end = wikipedia.summary(start, sentences=10) await msg.edit(content=f"```py\n{end}\n```") except: await msg.edit(content="Not found.") # spam @commands.check_any(commands.is_owner(), commands.has_permissions(manage_messages=True), commands.guild_only()) @commands.group(name="spam", aliases=['sp'], brief="Spams desired message", invoke_without_command=True, case_insensitive=True, help="Spams desired message, with desired intervals.") async def spam(self, ctx): await ctx.send_help(ctx.command) # spam start @commands.check_any(commands.is_owner(), commands.has_permissions(manage_messages=True)) @spam.command( name="start", aliases=["s"], brief="Starts spam.", help= "Spams <message> every <delay> seconds. For multi-word messages put them within quotes" ) @commands.max_concurrency(1, per=commands.BucketType.guild, wait=False) async def _spam_start(self, ctx, delay: float, *, msg): global on global sp_start_channel sp_start_channel = ctx.channel on = True while on: await ctx.send(msg) await asyncio.sleep(delay) # spam start error @_spam_start.error async def spamstart_error(self, ctx, error): if isinstance(error, commands.BadArgument): await ctx.send("The delay must be a number.") # spam stop @commands.check_any(commands.is_owner(), commands.has_permissions(manage_messages=True)) @spam.command(name="stop", aliases=['end'], brief="Stops running spam", help="Stops a running `spam` command.") async def _spam_stop(self, ctx): global on global sp_start_channel sp_stop_channel = ctx.channel if on == True and sp_stop_channel == sp_start_channel: on = False await ctx.send("Stopped spam.") else: await ctx.send( "There isn't a `spam` command running in this channel.") # timer max_time = 600 time = "" mins = "" tr_start_user = "" msg = "" secondint = "" @commands.group( name="timer", aliases=["tr", "countdown", "cd"], brief="Sets a timer", help= "Sets a timer, which the bot will count down from and ping at the end.", invoke_without_command=True, case_insensitive=True) async def timer(self, ctx): await ctx.send_help(ctx.command) #timer start @timer.command( name="start", aliases=["s"], brief="Starts timer.", help= f"Sets a timer for <seconds> and counts down from it(max {round(max_time/60, 2)}mins or {max_time}seconds). One timer per user at a time. Stop a running timer by using the {prefix}timer stop command." ) @commands.max_concurrency(1, per=commands.BucketType.user, wait=False) async def _timer_start(self, ctx, seconds: int): global time time = round(seconds, 2) global mins mins = round(seconds / 60, 2) global tr_start_user tr_start_user = ctx.author global msg msg = f"{ctx.author.mention} time's up! ({mins}mins or {seconds}seconds)" global secondint secondint = seconds if seconds > max_time: await ctx.send( f"Timer can be set for max **{max_time/60}** minutes or **{max_time}** seconds" ) elif seconds <= 0: await ctx.send("Please input a positive whole number.") else: message = await ctx.send(f"Timer: {secondint} seconds") while True: secondint -= 1 if secondint == 0: await message.edit(content=msg) break await message.edit(content=f"Timer: {secondint} seconds.") await asyncio.sleep(1) @_timer_start.error async def timerstart_error(self, ctx, error): if isinstance(error, commands.BadArgument): await ctx.send("The time must be a positive whole number.") # timer stop @timer.command(name="stop", aliases=["end"], brief="Stops running timer", help="Stops a running `timer` command.") async def _timer_stop(self, ctx): try: global msg global mins global time global tr_start_user global secondint if secondint > 0 and ctx.author == tr_start_user: msg = f"{ctx.author.mention} timer stopped! Stopped at {round(secondint/60, 2)}mins/{secondint}seconds **out of** {mins}mins/{time}seconds" secondint = 1 await ctx.message.add_reaction('👍') else: await ctx.send( f"There isn't a `timer` running that belongs to you.") except Exception as e: raise e
class Cosmetic(Cog): """Commands for some neat-o fun! Includes color changing and more. """ def __init__(self, bot): self.playing_anim = set() self.stop_anim = set() self.al_aliases = charsets.keys() super().__init__(bot) @commands.command() @commands.check(commands.guild_only()) async def emotes(self, ctx): """Lists all the custom emoji im this guild. Usage: emotes""" cemotes = ctx.guild.emojis em_string = (' '.join([str(i) for i in cemotes]) if len(cemotes) >= 1 else 'This guild has no custom emojis!') await ctx.send(em_string) @commands.command(aliases=['rev', 'mirror']) async def reverse(self, ctx, *, rmsg: str): """Reverse some text you give. Usage: reverse [text here]""" await ctx.send(':repeat: ' + rmsg[::-1]) @commands.command(aliases=[ 'math_sans_italic', 'circled', 'math_double', 'math_bold_italic', 'math_sans_bold_italic', 'parenthesized', 'math_bold_fraktur', 'math_sans_bold', 'squared', 'math_mono', 'fullwidth', 'squared_negative', 'normal', 'circled_negative', 'regional', 'math_sans', 'math_bold_script', 'math_bold', 'upside_down' ]) async def style(self, ctx, *rmsg): """Stylize text in cool alphabets! Invoke with alphabet name. Usage: style [style name] [text here]""" if rmsg: imsg = ' '.join(rmsg) final_result = self.stylize(ctx.invoked_with.lower(), imsg) await ctx.send(final_result) else: await ctx.send( '**You must invoke this command as: `[p][name of set] [message here]`.** For example: `!math_bold hello world`! Here are the character sets available:' ) await self.fontlist.invoke(ctx) def stylize(self, alphabet, intxt): return intxt.translate( str.maketrans(charsets['normal'], charsets[alphabet])) @commands.command(aliases=[ 'fonts', 'alphabet', 'alphabets', 'alphalist', 'styles', 'stylelist', 'chars', 'charlist', 'charsets', 'charsetlist' ]) async def fontlist(self, ctx): """List the available fancy character sets / alphabets / fonts. Usage: fonts""" pager = commands.Paginator(prefix='', suffix='') pager.add_line('**Listing all character sets defined with samples.**') for i in self.al_aliases: tmp = self.stylize(i, 'abcdefghijklmnopqrstuvwxyz') pager.add_line('**{0}**: `{1}`'.format(i, tmp)) pager.add_line( '**Invoke with `[p][name of set] [message here]`.** For example: `!math_bold hello world`.' ) for page in pager.pages: await ctx.send(page) @commands.cooldown(1, 6, type=commands.BucketType.guild) @commands.command( aliases=['af', 'sca', 'anim', 'a', 'playanim', 'aplay', 'animplay']) async def animation(self, ctx, anim_seq, runs: int): """Do a 0.9 fps animation x times from the given sequence. Usage: animation [packed animation] [number of runs]""" try: cmid = ctx.guild.id except AttributeError: cmid = ctx.author.id if cmid not in self.playing_anim: self.playing_anim.add(cmid) msg = await ctx.send('Starting animation...') for _xi in range(runs): for frame in anim_seq: if cmid not in self.stop_anim: await msg.edit(content=frame) await asyncio.sleep(0.93) else: await msg.edit(content='**Animation stopped!**') await ctx.send('**Animation stopped!**') self.playing_anim.remove(cmid) return await msg.edit(content='**Animation stopped!**') await ctx.send('**Animation stopped!**') self.playing_anim.remove(cmid) else: await ctx.send('**Already playing an animation in this guild!**') @commands.command( aliases=['sa', 'ssca', 'sanim', 'stopanimation', 'animstop', 'saf']) async def stopanim(self, ctx): """Stop the animation playing in this guild, if any. Usage: stopanim""" try: cmid = ctx.guild.id except AttributeError: cmid = ctx.author.id if cmid in self.playing_anim: await ctx.send('**Stopping animation...**') self.stop_anim.add(cmid) await asyncio.sleep(1.9) try: self.stop_anim.remove(cmid) except KeyError: pass else: await ctx.send('**Not playing any animation here!**') @commands.command(aliases=[ 'lanim', 'listanims', 'listanim', 'animationlist', 'animl', 'anims', 'animations', 'al', 'packs', 'packed', 'pal', 'pa', 'alist' ]) async def animlist(self, ctx): """List the packed animations I have saved. Usage: animlist""" await ctx.send('**Listing stored packed animations.**\n```\n' + '\n'.join(spinners) + '```') @commands.command(aliases=[ 'random.cat', 'randomcat', 'rcat', 'cats', 'catrandom', 'random_cat' ]) async def cat(self, ctx): """Get a random cat! Because why not. Usage: cat""" with async_timeout.timeout(8): async with self.bot.cog_http.get( 'http://random.cat/meow') as response: ret = await response.json() e = discord.Embed(color=random.randint(1, 255**3 - 1)) e.set_image(url=ret['file']) await ctx.send(embed=e) @commands.command( aliases=['temote', 'bemote', 'dcemote', 'getemote', 'fetchemote']) async def emote(self, ctx, emote: str): """Get a Twitch, FrankerFaceZ, BetterTTV, or Discord emote. Usage: emote [name of emote]""" emote = emote.replace(':', '') with async_timeout.timeout(13): try: async with self.bot.cog_http.get( 'https://static-cdn.jtvnw.net/emoticons/v1/' + str(self.bot.emotes['twitch'][emote]['image_id']) + '/1.0') as resp: emote_img = await resp.read() except KeyError: # let's try frankerfacez try: async with self.bot.cog_http.get( 'https://cdn.frankerfacez.com/emoticon/' + str(self.bot.emotes['ffz'][emote]) + '/1') as resp: emote_img = await resp.read() except KeyError: # let's try BetterTTV try: async with self.bot.cog_http.get( self.bot.emotes['bttv'][emote]) as resp: emote_img = await resp.read() except KeyError: # let's try Discord await ctx.send( '**No such emote!** I can fetch from Twitch, FrankerFaceZ, BetterTTV, or Discord (soon).' ) return False img_bytes = io.BytesIO(emote_img) ext = imghdr.what(img_bytes) await ctx.send(file=discord.File(img_bytes, f'emote.{ext}'))
def interaction_command_factory(name, *, normal: list, reject: list, condition_rejected: list = author + "could not do this to" + author.reflexive, condition_predicate=lambda _, __: True): async def command(self, ctx, *users: RelativeMemberConverter): message = await make_response(self, ctx, *users) if message is not None: async def unload(): await message.delete() ctx.bot.get_cog("Uninvoke").create_unload(ctx.message, unload) command.__doc__ = f"executes a {name} action towards selected users, if allowed" async def make_response(self, ctx, *users: discord.Member): users: List[discord.Member] = list(users) if not user_accepts(ctx.author, name, "thing"): return await ctx.send(f"But you don't like that") if ctx.message.reference is not None: referenced: discord.Message referenced = (ctx.message.reference.cached_message or await ctx.message.channel.fetch_message( ctx.message.reference.message_id)) users.append(referenced.author) allowed = [] role_denied = [] condition_denied = [] for user in users: # noinspection PyTypeChecker if user_accepts(user, name, "thing"): if condition_predicate(ctx.author, user): allowed.append(user) else: condition_denied.append(user) else: role_denied.append(user) if not users: return await ctx.send( "No users", allowed_mentions=discord.AllowedMentions.none()) title_baking = [] if allowed: title_baking.extend(normal) description_baking = [] if allowed and (role_denied or condition_denied): description_baking.append("however") if role_denied: description_baking.extend(reject) if condition_denied: description_baking.extend(condition_rejected) with PhraseBuilder() as builder: title = await builder.build(title_baking, speaker=ctx.bot.user, deferred={ "action_author": ctx.author, "valid": allowed, "rejected": role_denied, "condition": condition_denied }) if title == "": title = discord.Embed.Empty elif len(title) > 256: return await ctx.message.reply( embed=discord.Embed(title="(ಠ_ಠ)"), allowed_mentions=discord.AllowedMentions.none()) description = await builder.build(description_baking, speaker=ctx.bot.user, deferred={ "action_author": ctx.author, "valid": allowed, "rejected": role_denied, "condition": condition_denied }) if description == "": description = discord.Embed.Empty embed = discord.Embed(title=title, description=description) return await ctx.send(embed=embed, allowed_mentions=discord.AllowedMentions.none()) command = commands.guild_only()(commands.Command(command, name=name)) # inject command into class by putting it into a variable in it's frame inspect.currentframe().f_back.f_locals[f"_command_{name}"] = command