async def on_message(self, message: discord.Message): if not message.guild: return try: if message.guild.id != self.system.config.getint("general", "server_id", fallback=None): return except:pass prefixes = await self.bot.get_prefix(message) view = StringView(message.content) if isinstance(prefixes, list): for prefix in prefixes: if view.skip_string(prefix): cmd = view.get_word() command = await self.system.get_command(cmd) if command is not None: user = await self.system.get_user_discord_id(message.author.id) if command.can_run_discord(message, user): return await self.process_commands(message, command, view) else: if view.skip_string(prefixes): cmd = view.get_word() command = await self.system.get_command(cmd) if command is not None: user = await self.system.get_user_discord_id(message.author.id) if command.can_run_discord(message, user): return await self.process_commands(message, command, view)
async def on_message(self, message): if message.author.bot or not self.bot.is_running(): return if message.content.startswith(self.bot.command_prefix): name = message.content.lower().lstrip(self.bot.command_prefix).split(" ")[0] if command := config.Commands.fetch(name): attachment = None if command["attachment"]: async with aiohttp.ClientSession() as session: async with session.get(command["attachment"]) as resp: buff = io.BytesIO(await resp.read()) attachment = discord.File(filename=command["attachment"].split("/")[-1], fp=buff) args = [] view = StringView(message.content.lstrip(self.bot.command_prefix)) view.get_word() # command name while not view.eof: view.skip_ws() args.append(view.get_quoted_word()) text = re.sub( r'{(\d+)}', lambda match: args[int(match.group(1))] if int(match.group(1)) < len(args) else '(missing argument)', command["content"] ).replace('{...}', ' '.join(args)) await self.bot.reply_to_msg(message, text, file=attachment) return
async def event_message(self, message: twitchio.Message): if not message.channel: return if message.channel.name != self.bot._ws.nick: return prefixes = await self.bot._get_prefixes(message) view = StringView(message.content) if isinstance(prefixes, list): for prefix in prefixes: if view.skip_string(prefix): cmd = view.get_word() command = await self.system.get_command(cmd) if command is not None: user = await self.system.get_user_twitch_name( message.author.name, id=message.author.id) if command.can_run_twitch(message, user): return await self.process_commands( message, command, view) else: if view.skip_string(prefixes): cmd = view.get_word() command = await self.system.get_command(cmd) if command is not None: user = await self.system.get_user_twitch_name( message.author.name, id=message.author.id) if command.can_run_twitch(message, user): return await self.process_commands( message, command, view)
async def get_context(self, message, *, cls=Context): view = StringView(message.content) ctx = cls(prefix=None, view=view, bot=self, message=message) if self._skip_check(message.author.id, self.user.id): return ctx prefix = await self.get_prefix(message) invoked_prefix = prefix if isinstance(prefix, str): if not view.skip_string(prefix): return ctx elif isinstance(prefix, list) \ and any([isinstance(p, list) for p in prefix]): # Regex time for p in prefix: if isinstance(p, list): if p[1]: # regex prefix parsing reg = re.match(p[0], message.content) if reg: if message.content == reg.groups()[0]: # ignore * prefixes continue # Matches, this is the prefix invoked_prefix = p # redo the string view with the capture group view = StringView(reg.groups()[0]) invoker = view.get_word() ctx.invoked_with = invoker ctx.prefix = invoked_prefix ctx.command = self.all_commands.get(invoker) ctx.view = view return ctx else: # regex has highest priority or something idk # what I'm doing help continue # No prefix found, use the branch below prefix = [p[0] for p in prefix if not p[1]] invoked_prefix = discord.utils.find(view.skip_string, prefix) if invoked_prefix is None: return ctx else: invoked_prefix = discord.utils.find(view.skip_string, prefix) if invoked_prefix is None: return ctx invoker = view.get_word() ctx.invoked_with = invoker ctx.prefix = invoked_prefix ctx.command = self.all_commands.get(invoker) return ctx
async def get_contexts(self, message, *, cls=commands.Context): """ Returns all invocation contexts from the message. Supports getting the prefix from database as well as command aliases. """ view = StringView(message.content) ctx = cls(prefix=self.prefix, view=view, bot=self, message=message) ctx.thread = await self.threads.find(channel=ctx.channel) if self._skip_check(message.author.id, self.user.id): return [ctx] prefixes = await self.get_prefix() invoked_prefix = discord.utils.find(view.skip_string, prefixes) if invoked_prefix is None: return [ctx] invoker = view.get_word().lower() # Check if there is any aliases being called. alias = self.aliases.get(invoker) if alias is not None: aliases = parse_alias(alias) if not aliases: logger.warning("Alias %s is invalid, removing.", invoker) self.aliases.pop(invoker) else: len_ = len(f"{invoked_prefix}{invoker}") contents = parse_alias(message.content[len_:]) if not contents: contents = [message.content[len_:]] ctxs = [] for alias, content in zip_longest(aliases, contents): if alias is None: break ctx = cls(prefix=self.prefix, view=view, bot=self, message=message) ctx.thread = await self.threads.find(channel=ctx.channel) if content is not None: view = StringView(f"{alias} {content.strip()}") else: view = StringView(alias) ctx.view = view ctx.invoked_with = view.get_word() ctx.command = self.all_commands.get(ctx.invoked_with) ctxs += [ctx] return ctxs ctx.invoked_with = invoker ctx.command = self.all_commands.get(invoker) return [ctx]
async def get_contexts(self, message, *, cls=commands.Context): """ Returns all invocation contexts from the message. Supports getting the prefix from database as well as command aliases. """ view = StringView(message.content) ctx = cls(prefix=self.prefix, view=view, bot=self, message=message) thread = await self.threads.find(channel=ctx.channel) if self._skip_check(message.author.id, self.user.id): return [ctx] prefixes = await self.get_prefix() invoked_prefix = discord.utils.find(view.skip_string, prefixes) if invoked_prefix is None: return [ctx] invoker = view.get_word().lower() # Check if there is any aliases being called. alias = self.aliases.get(invoker) if alias is not None: ctxs = [] aliases = normalize_alias( alias, message.content[len(f"{invoked_prefix}{invoker}"):]) if not aliases: logger.warning("Alias %s is invalid, removing.", invoker) self.aliases.pop(invoker) for alias in aliases: view = StringView(invoked_prefix + alias) ctx_ = cls(prefix=self.prefix, view=view, bot=self, message=message) ctx_.thread = thread discord.utils.find(view.skip_string, prefixes) ctx_.invoked_with = view.get_word().lower() ctx_.command = self.all_commands.get(ctx_.invoked_with) ctxs += [ctx_] return ctxs ctx.thread = thread ctx.invoked_with = invoker ctx.command = self.all_commands.get(invoker) return [ctx]
async def get_context(self, message, *, cls=commands.Context): """ Returns the invocation context from the message. Supports getting the prefix from database. """ view = StringView(message.content) ctx = cls(prefix=self.prefix, view=view, bot=self, message=message) if self._skip_check(message.author.id, self.user.id): return ctx ctx.thread = await self.threads.find(channel=ctx.channel) prefixes = await self.get_prefix() invoked_prefix = discord.utils.find(view.skip_string, prefixes) if invoked_prefix is None: return ctx invoker = view.get_word().lower() ctx.invoked_with = invoker ctx.command = self.all_commands.get(invoker) return ctx
async def on_message(self, message): # If no prefix is found discard the message if not message.content.startswith(settings.PREFIX): return # If the message has a prefix but no known command we # convert the message to an !i command before passing it view = StringView(message.content) view.skip_string(settings.PREFIX) invoker = view.get_word() for command in self.commands: if invoker == command.name: break else: message.content = message.content[:1] + "i " + message.content[1:] # if invoker not in self.commands.name: # message.content = message.content[:1] + "i " + message.content[1:] # Allow for the command to be processed by discord.py await self.process_commands(message) # Put the message in the database queue to be stored self.db.add_message_to_queue(message)
async def get_context(self, message, *, cls=cmd.Context): # This function is called internally by discord.py. # We have to fiddle with it because we are using a dynamic prefix (our mention string), # as well as no prefix inside of DMs. # The included prefix matching functions could not deal with this case. # If it ever becomes possible, we should probably switch to that. # Frankly, I don't really remember what I did here, but it might be good # to periodically check the get_context method on the base class and # port over any changes that happened there. ~hmry (2019-08-14, 02:25) if self.command_regex is None: return cls(prefix=None, view=None, bot=self, message=message) cmd_regex = self.command_dms_regex if message.guild is None else self.command_regex match = cmd_regex.match(message.content) if not match: return cls(prefix=None, view=None, bot=self, message=message) view = StringView(match.group(1).strip()) ctx = cls(prefix=None, view=view, bot=self, message=message) if self._skip_check(message.author.id, self.user.id): return ctx invoker = view.get_word() ctx.invoked_with = invoker ctx.command = self.all_commands.get(invoker) return ctx
async def parse_line(line): ''' Parses a macro line ''' if line.split()[0].lower() == "wait": if print_queue: # We have run into a wait, send ze messages await message.channel.send("\n".join(print_queue)) print_queue.clear() await asyncio.sleep(float(line.split()[1])) else: # Trick discord.py into parsing this command as a bot view = StringView(line) ctx = commands.Context(prefix=bot_prefix, view=view, bot=bot, message=message) invoker = view.get_word() ctx.invoked_with = invoker if (command := bot.all_commands.get(invoker) ) and not command.qualified_name == "macro": if print_queue: # We have run into a command, send ze messages await ctx.send("\n".join(print_queue)) print_queue.clear() # invoke a command ctx.command = command await bot.invoke(ctx) else:
async def on_thread_ready(self, thread, creator, category, initial_message): """Sends out menu to user""" menu_config = await self.db.find_one({'_id': 'config'}) if menu_config: message = DummyMessage(copy.copy(initial_message)) message.author = self.bot.modmail_guild.me message.content = menu_config['content'] #genesis = thread.recipient_genesis_message #await genesis.delete() msg, _ = await thread.reply(message, anonymous=True) for r in menu_config['options']: await msg.add_reaction(r) await asyncio.sleep(0.3) try: reaction, _ = await self.bot.wait_for( 'reaction_add', check=lambda r, u: r.message == msg and u == thread. recipient and str(r.emoji) in menu_config['options'], timeout=120) except asyncio.TimeoutError: message.content = 'No reaction recieved in menu... timing out' await thread.reply(message) else: alias = menu_config['options'][str(reaction.emoji)] ctxs = [] if alias is not None: ctxs = [] aliases = normalize_alias(alias) for alias in aliases: view = StringView(self.bot.prefix + alias) ctx_ = commands.Context(prefix=self.bot.prefix, view=view, bot=self.bot, message=message) ctx_.thread = thread discord.utils.find(view.skip_string, await self.bot.get_prefix()) ctx_.invoked_with = view.get_word().lower() ctx_.command = self.bot.all_commands.get( ctx_.invoked_with) ctxs += [ctx_] for ctx in ctxs: if ctx.command: old_checks = copy.copy(ctx.command.checks) ctx.command.checks = [ checks.has_permissions(PermissionLevel.INVALID) ] await self.bot.invoke(ctx) ctx.command.checks = old_checks continue
async def get_context(self, message, *, cls=commands.Context): """ Returns the invocation context from the message. Supports getting the prefix from database as well as command aliases. """ view = StringView(message.content) ctx = cls(prefix=None, view=view, bot=self, message=message) if self._skip_check(message.author.id, self.user.id): return ctx ctx.thread = await self.threads.find(channel=ctx.channel) prefixes = await self.get_prefix() invoked_prefix = discord.utils.find(view.skip_string, prefixes) if invoked_prefix is None: return ctx invoker = view.get_word().lower() # Check if there is any aliases being called. alias = self.config.get('aliases', {}).get(invoker) if alias is not None: ctx._alias_invoked = True len_ = len(f'{invoked_prefix}{invoker}') view = StringView(f'{alias}{ctx.message.content[len_:]}') ctx.view = view invoker = view.get_word() ctx.invoked_with = invoker ctx.prefix = self.prefix # Sane prefix (No mentions) ctx.command = self.all_commands.get(invoker) has_ai = hasattr(ctx, '_alias_invoked') if ctx.command is self.get_command('eval') and has_ai: # ctx.command.checks = None # Let anyone use the command. pass return ctx
async def invoke(self, ctx: SlashContext, command): view = StringView(command) m = await ctx.send(f"Invoking command `{command}`...") ctx = commands.Context( prefix=bot_prefix, view=view, bot=self.bot, message=m) invoker = view.get_word() ctx.invoked_with = invoker if command := self.bot.all_commands.get(invoker): # invoke a command ctx.command = command await self.bot.invoke(ctx)
async def get_context(self, message, prefixes=None): prefixes = prefixes or await get_prefix(self.bot, message) for prefix in prefixes: message_regex = re.compile( rf"^({re.escape(prefix)})[\s]*(\w+)(.*)", re.I | re.X | re.S) match = message_regex.findall(message.content) if match: break if not match: return match = match[0] invoked_prefix = match[0].lower() message.content = f"{invoked_prefix}{match[1].lower()}{match[2]}" #piping operator pop = self.pop piped = pop in message.content if self.piping_enabled: if piped: #edge case for prefix being piping operator if invoked_prefix == pop: split = message.content.rsplit( pop, message.content.count(pop) - 1) else: split = message.content.split(pop) #modify message content to first command invoked if not split[-1].strip(): piped = False else: piped = await self.process_piping(split, message.author, invoked_prefix) if piped: message.content = split[0] view = StringView(message.content) ctx = NotSoContext(prefix=None, view=view, bot=self.bot, message=message) view.skip_string(invoked_prefix) invoker = view.get_word() ctx.invoked_with = invoker ctx.prefix = invoked_prefix command = self.bot.all_commands.get(invoker) if command is None: return ctx.command = command if piped: ctx.piped = piped ctx.cached = [] return ctx, piped
def process_commands(self, message): _internal_channel = message.channel _internal_author = message.author view = StringView(message.content) if message.author == self.user: return prefix = self._get_prefix(message) invoked_prefix = prefix if not isinstance(prefix, (tuple, list)): if not view.skip_string(prefix): ## procesar emoticons yield from self.process_emotes(message, view) return else: invoked_prefix = discord.utils.find(view.skip_string, prefix) if invoked_prefix is None: return invoker = view.get_word() tmp = { 'bot': self, 'invoked_with': invoker, 'message': message, 'view': view, 'prefix': invoked_prefix } ctx = Context(**tmp) del tmp if invoker in self.commands: command = self.commands[invoker] self.dispatch('command', command, ctx) ctx.command = command yield from command.invoke(ctx) self.dispatch('command_completion', command, ctx) else: exc = CommandNotFound('Command "{}" is not found'.format(invoker)) self.dispatch('command_error', exc, ctx) ## Invocar Kaomojis si existen key = invoker if(key not in kaomoji.keys()): key = random.sample(kaomoji.keys(), 1)[0] kao = random.sample(kaomoji[key],1)[0] yield from self.say(kao)
async def get_context(self, message, *, cls=commands.Context): """ Returns the invocation context from the message. Supports getting the prefix from database as well as command aliases. """ view = StringView(message.content) ctx = cls(prefix=None, view=view, bot=self, message=message) if self._skip_check(message.author.id, self.user.id): return ctx prefixes = [self.prefix, f'<@{bot.user.id}> ', f'<@!{bot.user.id}>'] invoked_prefix = discord.utils.find(view.skip_string, prefixes) if invoked_prefix is None: return ctx invoker = view.get_word().lower() # Check if there is any aliases being called. alias = self.config.get('aliases', {}).get(invoker) if alias is not None: ctx._alias_invoked = True _len = len(f'{invoked_prefix}{invoker}') ctx.view = view = StringView( f'{alias}{ctx.message.content[_len:]}') invoker = view.get_word() ctx.invoked_with = invoker ctx.prefix = self.prefix # Sane prefix (No mentions) ctx.command = self.all_commands.get(invoker) # if hasattr(ctx, '_alias_invoked'): # ctx.command.checks = None # Let anyone use the command. return ctx
async def special_get_context(bot, message, cmdtext, *, cls=Context): # similar to bot's get_context method but use cmdtext rather than message.content to build the context # notice that if any command uses context.message.content be behavior may not be as expected # the documentation can be viewed in discord.ext.commands -> bot.get_context view = StringView(cmdtext) ctx = cls(prefix=None, view=view, bot=bot, message=message) if bot._skip_check(message.author.id, bot.user.id): return ctx prefix = await bot.get_prefix(message) invoked_prefix = prefix if isinstance(prefix, str): if not view.skip_string(prefix): return ctx else: try: # if the context class' __init__ consumes something from the view this # will be wrong. That seems unreasonable though. if cmdtext.startswith(tuple(prefix)): invoked_prefix = discord.utils.find(view.skip_string, prefix) else: return ctx except TypeError: if not isinstance(prefix, list): raise TypeError( "get_prefix must return either a string or a list of string, " "not {}".format(prefix.__class__.__name__)) # It's possible a bad command_prefix got us here. for value in prefix: if not isinstance(value, str): raise TypeError( "Iterable command_prefix or list returned from get_prefix must " "contain only strings, not {}".format( value.__class__.__name__)) # Getting here shouldn't happen raise invoker = view.get_word() ctx.invoked_with = invoker ctx.prefix = invoked_prefix ctx.command = bot.all_commands.get(invoker) return ctx
async def get_context(self, message, *, cls=TwitchContext) -> TwitchContext: view = StringView(message.content) ctx = cls(prefix=None, view=view, bot=self, message=message) prefix = await self._get_prefixes(message) invoked_prefix = prefix if isinstance(prefix, str): if not view.skip_string(prefix): return ctx else: try: # if the context class' __init__ consumes something from the view this # will be wrong. That seems unreasonable though. if message.content.startswith(tuple(prefix)): invoked_prefix = discord.utils.find( view.skip_string, prefix) else: return ctx except TypeError: if not isinstance(prefix, list): raise TypeError( "get_prefix must return either a string or a list of string, " "not {}".format(prefix.__class__.__name__)) # It's possible a bad command_prefix got us here. for value in prefix: if not isinstance(value, str): raise TypeError( "Iterable command_prefix or list returned from get_prefix must " "contain only strings, not {}".format( value.__class__.__name__)) # Getting here shouldn't happen raise invoker = view.get_word() ctx.invoked_with = invoker ctx.prefix = invoked_prefix ctx.command = self.all_commands.get(invoker) return ctx
def add_message(self, message): view = StringView(message.content) command = view.get_word() request_data = { "message_id": str(message.id), "user_id": str(message.author.id), "server_id": str(message.guild.id), "command": command, "content": view.read_rest(), "timestamp": message.created_at } try: self.firestore.collection('requests').add( document_data=request_data, document_id=str(message.id)) except Conflict as e: logger.error(e)
async def get_context(self, message, *, cls=Context): view = StringView(message.content) ctx = cls(prefix=None, view=view, bot=self, message=message) if self._skip_check((await message.author()).id, (await self.user()).id): return ctx prefix = await self.get_prefix(message) invoked_prefix = prefix if isinstance(prefix, str): if not view.skip_string(prefix): return ctx else: try: if message.content.startswith(tuple(prefix)): invoked_prefix = utils.find(view.skip_string, prefix) else: return ctx except TypeError: if not isinstance(prefix, list): raise TypeError( "get_prefix must return either a string or a list of string, " "not {}".format(prefix.__class__.__name__)) for value in prefix: if not isinstance(value, str): raise TypeError( "Iterable command_prefix or list returned from get_prefix must " "contain only strings, not {}".format( value.__class__.__name__)) raise invoker = view.get_word() ctx.invoked_with = invoker ctx.prefix = invoked_prefix ctx.command = self.all_commands.get(invoker) return ctx
async def process_commands(self, message): """ Override of process_commands to use our own context. """ _internal_channel = message.channel _internal_author = message.author view = StringView(message.content) if self._skip_check(message.author, self.user): return prefix = await self._get_prefix(message) invoked_prefix = prefix if not isinstance(prefix, (tuple, list)): if not view.skip_string(prefix): return else: invoked_prefix = discord.utils.find(view.skip_string, prefix) if invoked_prefix is None: return invoker = view.get_word() tmp = { 'bot': self, 'invoked_with': invoker, 'message': message, 'view': view, 'prefix': invoked_prefix } ctx = Context(**tmp) del tmp if invoker in self.commands: command = self.commands[invoker] self.dispatch('command', command, ctx) await command.invoke(ctx) self.dispatch('command_completion', command, ctx) elif invoker: exc = CommandNotFound('Command "{}" is not found'.format(invoker)) self.dispatch('command_error', exc, ctx)
async def get_context(client: Client, msg: Message) -> Context: view = StringView(msg.content) ctx = Context(prefix=None, view=view, bot=client, message=msg) if client._skip_check(msg.author.id, client.user.id): return ctx prefix = await client._get_prefix(msg) invoked_prefix = prefix if isinstance(prefix, str): if not view.skip_string(prefix): return ctx else: invoked_prefix = discord.utils.find(view.skip_string, prefix) if invoked_prefix is None: return ctx invoker = view.get_word() ctx.invoked_with = invoker ctx.prefix = invoked_prefix ctx.command = client.all_commands.get(invoker) return ctx
async def process_commands(self, message): _internal_channel = message.channel _internal_author = message.author view = StringView(message.content) if self._skip_check(message.author, self.user): return prefix = await self._get_prefix(message) invoked_prefix = prefix if not isinstance(prefix, (tuple, list)): if not view.skip_string(prefix): return else: invoked_prefix = discord.utils.find(view.skip_string, prefix) if invoked_prefix is None: return invoker = view.get_word().lower() # case-insensitive commands tmp = { 'bot': self, 'invoked_with': invoker, 'message': message, 'view': view, 'prefix': invoked_prefix } ctx = Context(**tmp) del tmp if invoker in self.commands: command = self.commands[invoker] self.dispatch('command', command, ctx) try: await command.invoke(ctx) except CommandError as e: ctx.command.dispatch_error(e, ctx) else: self.dispatch('command_completion', command, ctx) elif invoker: exc = CommandNotFound('Command "{}" is not found'.format(invoker)) self.dispatch('command_error', exc, ctx)
async def on_message(message): """ discord.py on_message Processes messages, and if the message is a command, will execute it. We do check if the command is in the whitelist - these commands do not require bot terms acceptance to run, as they are typically general use commands (e.g. accept). If the command is not in the whitelist, we check that the user has accepted the terms of service. If they have, we process the command and move on. If they have not, we inform them that they must accept the terms before they can use commands. """ view = StringView(message.content) # invoked_prefix = COMMAND_PREFIX # Can we remove this? It's reset immediately after invoked_prefix = discord.utils.find(view.skip_string, COMMAND_PREFIX) discord.utils.find(view.skip_string, COMMAND_PREFIX) # This is fairly worthless. While it can purge the message, everyone will still get a notification that there # was a message for them. That's on Discord themselves to correct if the message is deleted. if "@everyone" in message.content: await Moderation(CLIENT).purge_everyone_message(message) if invoked_prefix is None: return invoker = view.get_word() if invoker in CLIENT.commands: # If the message content is a command within the whitelist, run the command; otherwise, they must have accepted # the bot terms before the command can be used. if message.content in whitelist: await CLIENT.process_commands(message) else: can_use = BotResources().check_accepted(message.author.id) message_channel_valid = False if not message.channel.is_private: message_channel_valid = BotResources().get_tos_channel_valid(message.server.id) if can_use: await CLIENT.process_commands(message) elif not can_use and message_channel_valid: if message.author.id != CLIENT.user.id: message_channel_id = ConfigLoader().load_server_int_setting( message.server.id, 'ConfigSettings', 'not_accepted_channel_id') bot_message = await CLIENT.send_message( discord.Object(id=message_channel_id), NOT_ACCEPTED_MESSAGE.replace( "{user}", message.author.mention).replace( "{prefix}", COMMAND_PREFIX)) await asyncio.sleep(20) await CLIENT.delete_message(bot_message) else: # This is needed to prevent infinite looping message posting if message.author.id != CLIENT.user.id: bot_message = await CLIENT.send_message( discord.Object(id=message.channel.id), NOT_ACCEPTED_MESSAGE.replace( "{user}", message.author.mention).replace( "{prefix}", COMMAND_PREFIX)) await asyncio.sleep(20) await CLIENT.delete_message(bot_message)
def process_commands(self, message): bot = self.bot log_channel = bot.get_server("107883969424396288").get_channel("257926036728184832") error_channel = bot.get_server("107883969424396288").get_channel("257922447205072897") _internal_channel = message.channel _internal_author = message.author self = bot view = StringView(message.content) if self._skip_check(message.author, self.user): pass prefix = yield from self._get_prefix(message) invoked_prefix = prefix if not isinstance(prefix, (tuple, list)): if not view.skip_string(prefix): return else: invoked_prefix = discord.utils.find(view.skip_string, prefix) if invoked_prefix is None: return if invoked_prefix is "c." and message.author != message.server.me: return invoker = view.get_word() invoker_orig = invoker diff = difflib.get_close_matches(invoker, self.commands, n=1, cutoff=0.8) if diff != []: invoker = diff[0] tmp = { 'bot': self, 'invoked_with': invoker, 'message': message, 'view': view, 'prefix': invoked_prefix } ctx = Context(**tmp) del tmp if invoker in self.commands: command = self.commands[invoker] self.dispatch('command', command, ctx) try: yield from command.invoke(ctx) except discord.ext.commands.errors.DisabledCommand as e: yield from self.say("*`{}` is disabled*".format(str(e).split(" ")[0])) except discord.ext.commands.errors.CheckFailure as e: yield from self.say("```You do not have permission for this command!```") except discord.ext.commands.errors.CommandOnCooldown as e: yield from self.say("```{}```".format(str(e))) except discord.ext.commands.errors.BadArgument as e: yield from self.say("```{}```".format(str(e))) except discord.ext.commands.errors.CommandError as e: ctx.command.dispatch_error(e, ctx) yield from self.say("An Error Has Occurred: ```py\n{}```".format(traceback.format_exc().replace("/home/seacow/Discord-Bot/","./").split("The above exception was the direct cause of the following exception:")[0])) if not message.author == message.server.me: yield from self.send_message(error_channel,"{}```py\n{}```".format("\"{}\" produced an error on \"{}\" / \"{}\" | Invoked by \"{}\"".format(message.content, _internal_channel.name, _internal_channel.server.name, _internal_author.name+"#"+_internal_author.discriminator), traceback.format_exc().replace("/home/seacow/Discord-Bot/","./").replace("\"penny123\"", "********").split("The above exception was the direct cause of the following exception:")[0])) except discord.ext.commands.errors.MissingRequiredArgument as e: yield from self.say("```{}```".format(str(e))) except: pass else: self.dispatch('command_completion', command, ctx) elif invoker: close_matches = difflib.get_close_matches(invoker, self.commands) extra = "" if close_matches != []: extra = "\nDid you mean?: {}{}".format(invoked_prefix, ", {}".format(invoked_prefix).join(close_matches)) yield from self.say("```\"{}\" is not a command{}```".format(invoked_prefix+invoker, extra)) exc = discord.ext.commands.errors.CommandNotFound('Command "{}" is not found'.format(invoker)) logging.warning('Command "{}" is not found'.format(invoker)) self.dispatch('command_error', exc, ctx)
def check(prefix): view = StringView(message.content) return view.skip_string(prefix) and view.get_word().lower() in cmds
async def get_context(self, message, *, cls=Context): """Defaults to check for prefix first.""" view = StringView(message.content) ctx = cls(prefix=None, suffix=None, view=view, bot=self, message=message) if self._skip_check(message.author.id, self.user.id): return ctx prefix = await self.get_prefix(message) suffix = await self.get_suffix(message) if prefix is not None: if isinstance(prefix, str): if view.skip_string(prefix): invoked_prefix = prefix else: try: if message.content.startswith(tuple(prefix)): invoked_prefix = discord.utils.find(view.skip_string, prefix) except TypeError: if not isinstance(prefix, list): raise TypeError("get_prefix must return either a string or a list of string, " "not {}".format(prefix.__class__.__name__)) for value in prefix: if not isinstance(value, str): raise TypeError("Iterable command_prefix or list returned from get_prefix must " "contain only strings, not {}".format(value.__class__.__name__)) raise else: if isinstance(suffix, str): if _suffix_used(suffix, message.content): invoked_suffix = suffix else: return ctx else: try: invoked_suffixes = [s for s in suffix if _suffix_used(s, message.content)] if not invoked_suffixes: return ctx for suf in invoked_suffixes: invoker = view.get_word()[:-len(suf)] command = self.all_commands.get(invoker) if command is not None: view.undo() invoked_suffix = suf break else: return ctx except TypeError: if not isinstance(suffix, list): raise TypeError("get_suffix must return either a string or a list of string, " "not {}".format(suffix.__class__.__name__)) for value in suffix: if not isinstance(value, str): raise TypeError("Iterable command_suffix or list returned from get_suffix must " "contain only strings, not {}".format(value.__class__.__name__)) raise invoker = view.get_word() try: ctx.suffix = invoked_suffix except NameError: try: ctx.prefix = invoked_prefix except NameError: pass else: invoker = invoker[:-len(invoked_suffix)] ctx.invoked_with = invoker ctx.command = self.all_commands.get(invoker) return ctx
async def invoke(self, ctx, piped): if piped and ctx.piped: not_owner = not await self.is_owner(ctx.author) if not_owner: await self.check_cooldown( 1, ctx, "\N{NO ENTRY} **Cooldown** `Cannot pipe for another {:.2f} seconds.`", True) lp = len(ctx.piped) it = time() for idx, p in enumerate(ctx.piped): e = discord.Embed(title=p[0][:256]) if idx != 0: # Re-init StringView view = StringView( f"{p[0]} {' '.join(filter(lambda x: isinstance(x, str), ctx.cached))}" ) # Clear the output cache for the next run ctx.cached.clear() ctx.view = view view.skip_string("") view.get_word() ctx.command = p[1] else: if not ctx.channel.permissions_for(ctx.me).embed_links: raise CannotPaginate( 'Bot does not have `embed_links` permission for piping.' ) e.description = f"\N{HOURGLASS WITH FLOWING SAND} Piping {lp} commands" # Don't need NotSoContext.send, can't mention ping in embeds m = await super(ctx.__class__, ctx).send(embed=e) self.bot.command_messages[ctx.message.id][2].append(m.id) # Return on cooldown if ctx.cached: return await m.edit(content=ctx.cached[0].decode()) is_last = (idx + 1) == lp t = time() # 5 min cache for last result, 10s + current index to circumvent discord cache ctx.cached.append(300 if is_last else 60 + idx) # Wait on ratelimit to prevent cooldown on cooldown messages try: await self.bot.invoke(ctx) except commands.CommandOnCooldown as e: if not_owner: ra = e.retry_after # Let the user know e.description = f"\N{TIMER CLOCK} Waiting {ra:.2f} seconds for cooldown." await m.edit(embed=e) # Sleep then bypass checks await asyncio.sleep(ra) await ctx.reinvoke() # Using embed as a progress "bar" through images e.timestamp = datetime.datetime.now() if is_last: e.set_footer( text="\N{HOLE} Piping took {:.01f}s".format(time() - it)) else: e.set_footer( text=f"\N{HOLE} Piping in progress: {idx + 1}/{lp}") # Set embed for c in ctx.cached[:3]: if isinstance(c, int): continue # Differentiate between imis cache and text content if isinstance(c, str): e.set_image(url=c) else: e.description = c.decode() # Don't update the embed too fast if (time() - t) < 1: await asyncio.sleep(1.5) # Edit with new results or create message and add to cmessages await m.edit(embed=e) else: await self.bot.invoke(ctx)
def process_commands(self, message): bot = self.bot log_channel = bot.get_server("107883969424396288").get_channel( "257926036728184832") error_channel = bot.get_server("107883969424396288").get_channel( "257922447205072897") _internal_channel = message.channel _internal_author = message.author self = bot view = StringView(message.content) if self._skip_check(message.author, self.user): pass prefix = yield from self._get_prefix(message) invoked_prefix = prefix if not isinstance(prefix, (tuple, list)): if not view.skip_string(prefix): return else: invoked_prefix = discord.utils.find(view.skip_string, prefix) if invoked_prefix is None: return if invoked_prefix is "c." and message.author != message.server.me: return invoker = view.get_word() invoker_orig = invoker diff = difflib.get_close_matches(invoker, self.commands, n=1, cutoff=0.8) if diff != []: invoker = diff[0] tmp = { 'bot': self, 'invoked_with': invoker, 'message': message, 'view': view, 'prefix': invoked_prefix } ctx = Context(**tmp) del tmp if invoker in self.commands: command = self.commands[invoker] self.dispatch('command', command, ctx) try: yield from command.invoke(ctx) except discord.ext.commands.errors.DisabledCommand as e: yield from self.say("*`{}` is disabled*".format( str(e).split(" ")[0])) except discord.ext.commands.errors.CheckFailure as e: yield from self.say( "```You do not have permission for this command!```") except discord.ext.commands.errors.CommandOnCooldown as e: yield from self.say("```{}```".format(str(e))) except discord.ext.commands.errors.BadArgument as e: yield from self.say("```{}```".format(str(e))) except discord.ext.commands.errors.CommandError as e: ctx.command.dispatch_error(e, ctx) yield from self.say( "An Error Has Occurred: ```py\n{}```". format(traceback.format_exc( ).replace("/home/seacow/Discord-Bot/", "./").split( "The above exception was the direct cause of the following exception:" )[0])) if not message.author == message.server.me: yield from self.send_message( error_channel, "{}```py\n{}```".format( "\"{}\" produced an error on \"{}\" / \"{}\" | Invoked by \"{}\"" .format( message.content, _internal_channel.name, _internal_channel.server.name, _internal_author.name + "#" + _internal_author.discriminator), traceback.format_exc().replace( "/home/seacow/Discord-Bot/", "./" ).replace("\"penny123\"", "********").split( "The above exception was the direct cause of the following exception:" )[0])) except discord.ext.commands.errors.MissingRequiredArgument as e: yield from self.say("```{}```".format(str(e))) except: pass else: self.dispatch('command_completion', command, ctx) elif invoker: close_matches = difflib.get_close_matches(invoker, self.commands) extra = "" if close_matches != []: extra = "\nDid you mean?: {}{}".format( invoked_prefix, ", {}".format(invoked_prefix).join(close_matches)) yield from self.say("```\"{}\" is not a command{}```".format( invoked_prefix + invoker, extra)) exc = discord.ext.commands.errors.CommandNotFound( 'Command "{}" is not found'.format(invoker)) logging.warning('Command "{}" is not found'.format(invoker)) self.dispatch('command_error', exc, ctx)