async def parse(bot, msg, view: StringView, command: str, discord: bool): args = [] v = view.get_quoted_word() while v: args.append(v.strip()) v = view.get_quoted_word() if discord: try: await parse_discord_specifics(bot, msg, command, args) except Exception as e: ctx = await bot.get_context(msg) await ctx.paginate("".join( traceback.format_exception(type(e), e, e.__traceback__))) return None
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
def get_extra_args_from_alias(self, message: discord.Message, prefix: str) -> str: """ When an alias is executed by a user in chat this function tries to get any extra arguments passed in with the call. Whitespace will be trimmed from both ends. :param message: :param prefix: :param alias: :return: """ known_content_length = len(prefix) + len(self.name) extra = message.content[known_content_length:] view = StringView(extra) view.skip_ws() extra = [] while not view.eof: prev = view.index word = view.get_quoted_word() if len(word) < view.index - prev: word = "".join( (view.buffer[prev], word, view.buffer[view.index - 1])) extra.append(word) view.skip_ws() return extra
async def newcontributors_interactive(self, ctx: GuildContext) -> None: """Interactively add contributors. Integrates with Red. """ member_converter = commands.MemberConverter() pending_contributors = await self.__config.pending_contributors() new_added_contributors = {} early_exit = False for user_id, author_data in pending_contributors.items(): discord_user_id_line = ( f"**Discord user ID:** {discord_user_id}\n" if (discord_user_id := author_data.get('discord_user_id')) is not None else "" ) bot_msg = await ctx.send( f"**GitHub Username:** {author_data['username']}\n" f"**Commit author name:** {author_data['name']}\n" f"**Commit author email:** {author_data['email']}\n" f"{discord_user_id_line}" "Use Red's `?assign` command or send user ID to add contributor." " Type `exit` to finish, use `skip` to skip the contributor." ) while not early_exit: user_msg = await self.bot.wait_for( "message_without_command", check=MessagePredicate.same_context(ctx) ) content = user_msg.content if content == "exit": early_exit = True continue if content == "skip": break if user_msg.content.startswith("?assign "): view = StringView(user_msg.content) view.skip_string("?assign ") content = view.get_quoted_word() try: member = await member_converter.convert(ctx, content) except commands.BadArgument as e: await ctx.send( f"{e}. Please try passing user ID" " or using `?assign` command again." ) continue author_data["discord_user_id"] = member.id new_added_contributors[user_id] = author_data break else: # early-exit by breaking out of for loop await safe_delete_message(bot_msg) break await safe_delete_message(bot_msg)
async def convert(self, ctx, argument): converted = [] view = StringView(argument) while not view.eof: args = [] for converter in self.converters: view.skip_ws() arg = view.get_quoted_word() if arg is None: raise commands.UserInputError(_('Not enough arguments.')) args.append(await self._do_conversion(ctx, converter, arg)) converted.append(tuple(args)) return converted
async def _get_roles_from_content(ctx, content): # greedy = Greedy[RoleConverter] view = StringView(content) rc = RoleConverter() # "Borrowed" from discord.ext.commands.Command._transform_greedy_pos result = [] while not view.eof: # for use with a manual undo previous = view.index view.skip_ws() try: argument = view.get_quoted_word() value = await rc.convert(ctx, argument) except (CommandError, ArgumentParsingError): view.index = previous break else: result.append(value) return [r.id for r in result]