async def begone(self, ctx, message: Optional[discord.Message] = None): if message is not None and ctx.message.reference is not None: raise commands.TooManyArguments( "Please only either reply to the problemed message or add it to the end of this message not both" ) message = message if message is not None else ctx.message.reference.resolved if ctx.message.reference is not None else None if message is None: raise commands.MessageNotFound( "Please either reply to the message with this command or add the message to the end of this command" ) if message.author != ctx.guild.me: raise commands.CommandError( "I will not delete messages that I didn't author with this command" ) reference = await ctx.channel.fetch_message( message.reference.message_id) if reference.author != ctx.author: raise commands.CommandError( "You are not the author of that message, I will only 'begone' messages that referenced a message authored by you" ) await asyncio.gather( relay_info( f"**Begone**\nUSER: {reference.clean_content}\nME: {message.clean_content}```{message}```", self.bot, webhook=self.bot.log.log_chat), message.delete(), ctx.reply(embed=embed(title="Message has been removed"), delete_after=10), ctx.message.delete(delay=10))
async def convert(self, ctx: commands.Context, argument: str) -> list[float]: arguments = re.split(r",\s*|\s+(?=\d)", argument) arguments = [ self.strip(argument) for argument in arguments if argument ] if arguments.__len__() > 2: raise commands.TooManyArguments( "More than two coordinate arguments were passed.") elif arguments.__len__() < 2: raise commands.BadArgument( "Less than two coordinate arguments were passed.") arguments = [ re.split(r"(?i)(?<=\d)(?:Degrees|Deg(\.)?|°)?(?!\d)", argument) for argument in arguments ] arguments = [[i for i in index if i] for index in arguments] coords: list[float | None] = [None, None] for i, arg in enumerate(arguments): len = arg.__len__() if not (1 <= len <= 2): raise commands.BadArgument( "More or less than two coordinate arguments were passed") if len == 1: try: coords[i] = float(arg[0]) except ValueError as e: raise commands.BadArgument( "Invalid coordinate arguments passed") from e elif len == 2: try: coord_name = arg[1][0].lower() if coord_name == "n": coords[0] = float(arg[0]) elif coord_name == "e": coords[1] = float(arg[0]) elif coord_name == "w": coords[1] = -float(arg[0]) elif coord_name == "s": coords[0] = -float(arg[0]) except (ValueError, KeyError) as e: raise commands.BadArgument( "Invalid coordinate arguments passed") from e resp = [self.assert_float(coord) for coord in coords] if abs(resp[0]) > 90: raise commands.BadArgument( f"Latitude cannot exceed 90 degrees (given latitude: {resp[0]})." ) elif abs(resp[1]) > 180: raise commands.BadArgument( f"Longitude cannot exceed 180 degrees (given longitude: {resp[1]})." ) return resp
async def _parse_arguments(self, ctx: Context): ctx.args = args = [ctx] if self.instance is None else [ self.instance, ctx ] ctx.kwargs = kwargs = {} view = ctx.view iterator = iter(self.params.items()) if self.instance is not None: # we have 'self' as the first parameter so just advance # the iterator and resume parsing try: next(iterator) except StopIteration: raise discord.ClientException( f'Callback for {self.name} command is missing "self" parameter.' ) # next we have the 'ctx' as the next parameter try: next(iterator) except StopIteration: raise discord.ClientException( f'Callback for {self.name} command is missing "ctx" parameter.' ) for name, param in iterator: if param.kind == param.POSITIONAL_OR_KEYWORD: transformed = await self.transform(ctx, param) args.append(transformed) elif param.kind == param.KEYWORD_ONLY: # kwarg only param denotes "consume rest" semantics if self.rest_is_raw: converter = self._get_converter(param) argument = view.read_rest() kwargs[name] = await self.do_conversion( ctx, converter, argument) break kwargs[name] = await self.transform(ctx, param) elif param.kind == param.VAR_POSITIONAL: while not view.eof: try: transformed = await self.transform(ctx, param) args.append(transformed) except RuntimeError: break if not self.ignore_extra: if not view.eof: raise commands.TooManyArguments( f'Too many arguments passed to {self.qualified_name}')
async def _parse_arguments(self, ctx): ctx.args = [ctx] if self.cog is None else [self.cog, ctx] ctx.kwargs = {} args = ctx.args kwargs = ctx.kwargs view = ctx.view iterator = iter(self.params.items()) if self.cog is not None: # we have 'self' as the first parameter so just advance # the iterator and resume parsing try: next(iterator) except StopIteration: raise discord.ClientException( f'Callback for {self.name} command is missing "self" parameter.' ) # next we have the 'ctx' as the next parameter try: next(iterator) except StopIteration: raise discord.ClientException( f'Callback for {self.name} command is missing "ctx" parameter.' ) for name, param in iterator: if param.kind == param.POSITIONAL_OR_KEYWORD: transformed = await self.transform(ctx, param) args.append(transformed) elif param.kind == param.KEYWORD_ONLY: # kwarg only param denotes "consume rest" semantics kwargs[ name] = await self.callback.__lightning_argparser__.parse_args( ctx) break elif param.kind == param.VAR_POSITIONAL: if view.eof and self.require_var_positional: raise commands.MissingRequiredArgument(param) while not view.eof: try: transformed = await self.transform(ctx, param) args.append(transformed) except RuntimeError: break elif param.kind == param.VAR_KEYWORD: await self._parse_flag_args(ctx) break if not self.ignore_extra: if not view.eof: raise commands.TooManyArguments( 'Too many arguments passed to ' + self.qualified_name)
def validate_attachment(msg): """Checks if a message includes 1 image attachment Returns the image's proxy_url """ if len(msg.attachments) != 1: raise commands.TooManyArguments('needs one file attachment.') attachment = msg.attachments[0] if attachment.height is None or attachment.width is None: raise commands.BadArgument('file attachment must be an image.') return attachment.proxy_url
async def command_poll(self, context, name, *options): """ Starts a poll Use quotation marks if you want whole phrases as name/options. If just the poll name is given, options will be yes/no/maybe, otherwise each option will have a letter associated. ex: `<prefix>poll` "Is this a cool poll command?" `<prefix>poll` "Favourite icecream?" chocolate strawberry banana concrete """ if len(options) <= 20: message = await context.send( embed=self.create_poll_embed(name, options)) await self.react_with_options(message, options) else: raise commands.TooManyArguments("Maximum number of options is 20")
async def poll(self, ctx, title, *choices): if len(choices) >= 21: raise commands.TooManyArguments() emoji = 0x0001f1e6 # 絵文字定数(A) num = 0 emojis = [] content = "" if len(choices) == 0: choices = ["そう思う", "そう思わない"] for num, choice in enumerate(choices): reaction = chr(emoji + num) content += f"{reaction}:{choice}\n" emojis.append(reaction) embed = discord.Embed( title=title, description=content, color=0x3aee67) msg = await ctx.send(embed=embed) await ctx.message.delete() [await msg.add_reaction(e) for e in emojis]
async def pick_player(self, ctx: commands.context.Context): """ Adds player to calling captains team. SYNOPSIS .tm_pick_player @mention """ if len(ctx.message.raw_mentions) > 1: raise commands.TooManyArguments( "Captain attempted to pick too many players.") captain_id = ctx.message.author.id try: pick = ctx.message.mentions[0] except IndexError: raise commands.MissingRequiredArgument(param=inspect.Parameter( name="Player", kind=inspect.Parameter.POSITIONAL_ONLY)) captain_team_status = self.__ongoing.get_captain_team_status( captain_id) last_pick = self.__ongoing.pick_player(pick.id, captain_id) role_config_property = Config.get_config_property( "tenman", "team{0}".format(captain_team_status.name), "playerRole") role = find(lambda r: r.name == role_config_property, ctx.guild.roles) await ctx.message.mentions[0].add_roles(role) embed = discord.Embed(title="Player Selected", color=discord.Color.red() if captain_team_status == TeamStatus.A else discord.Color.blue()) embed.add_field(name="Name", value=ctx.message.mentions[0].name) embed.add_field(name="Picked By", value="Team {0}".format(captain_team_status.name)) embed.add_field(name="Ten Man Status", value="[Link]({0})".format( self.__status_message.jump_url)) embed.set_thumbnail(url=pick.avatar_url) await ctx.channel.send(embed=embed) try: await self.__move_user_to_proper_voice(ctx, ctx.message.mentions[0], captain_team_status) except discord.errors.HTTPException: pass status_embed = self.__status_message.embeds[0] team_field = status_embed.fields[4 if captain_team_status == TeamStatus.A else 5] status_embed.set_field_at( index=(4 if captain_team_status == TeamStatus.A else 5), name=team_field.name, value=(team_field.value + "\n" + pick.name)) if last_pick[0] is not None and last_pick[1] is not None: last_pick_profile = find(lambda p: p.id == last_pick[0], ctx.guild.members) role_config_property_lp = Config.get_config_property( "tenman", "team{0}".format(last_pick[1].name), "playerRole") role_lp = find(lambda r: r.name == role_config_property_lp, ctx.guild.roles) await last_pick_profile.add_roles(role_lp) embed_lp = discord.Embed(title="Last Pick", color=discord.Color.red() if last_pick[1] == TeamStatus.A else discord.Color.blue()) embed_lp.set_thumbnail(url=last_pick_profile.avatar_url) embed_lp.add_field(name="Name", value=last_pick_profile.name) embed_lp.add_field(name="Picked for", value="Team {0}".format(last_pick[1].name)) embed_lp.add_field(name="Ten Man Status", value="[Link]({0})".format( self.__status_message.jump_url)) await ctx.channel.send(embed=embed_lp) status_embed.remove_field(index=3) status_embed.set_field_at( index=(3 if last_pick[0] == TeamStatus.A else 4), name=team_field.name, value="{0}\n{1}".format(team_field.value, last_pick_profile.name)) status_embed.set_field_at(index=5, name=status_embed.fields[5].name, value=status_embed.fields[5].value, inline=True) else: rp_field = status_embed.fields[3] status_embed.set_field_at( index=3, name=rp_field.name, value="\n".join([ find(lambda u: u.id == rp, ctx.guild.members).name for rp in self.__ongoing.get_remaining_participant_ids() ])) status_embed.set_field_at(index=5, name=status_embed.fields[5].name, value=status_embed.fields[5].value, inline=True) await self.__status_message.edit(embed=status_embed) if self.__display_help: try: message = "***Help Message:***\nIt is Team {0}'s turn to pick the next player.\nThey can do so by " \ "using the command\n`.pick_player @player`".format(self.__ongoing.peek_next_player_pick().name) except IndexError: map_pick_ban_entry = self.__ongoing.peek_next_map_pick_ban() message = "***Help Message:***\nIt is now time to move on to the map pick/ban phase. Team " \ "{0.get_team_status().name} can {0.get_mode().name.lower()} the first map.\nThey can do so" \ "by using the command\n`{0.get_mode().name.lower()}_map map`".format(map_pick_ban_entry) await ctx.channel.send(message)
async def pick_captains(self, ctx: commands.context.Context): """ Makes mentioned players captain or selects two captains at random if none are provided SYNOPSIS .tm_pick_captains [@mention @mention] """ # Caller tried to manually select too many captains if len(ctx.message.mentions) > 2: raise commands.TooManyArguments( "Attempted to pick too many captains.") # Create role objects for config captain_a_role = find( lambda r: r.name == Config.get_config_property( "tenman", "teamA", "captainRole"), ctx.guild.roles) captain_b_role = find( lambda r: r.name == Config.get_config_property( "tenman", "teamB", "captainRole"), ctx.guild.roles) # Get captains either randomly or manually (based on # of mentioned users) captain_ids = ctx.message.raw_mentions captains = self.__ongoing.set_or_pick_captains(captain_ids) captain_a = find(lambda c: c.id == captains[0], ctx.guild.members) captain_b = find(lambda c: c.id == captains[1], ctx.guild.members) await captain_a.add_roles(captain_a_role) await captain_b.add_roles(captain_b_role) # Pretty output for discord embed_a = discord.Embed(title="Captain Selected", color=discord.Color.red()) embed_a.set_thumbnail(url=captain_a.avatar_url) embed_a.add_field(name="Name", value=captain_a.name) embed_a.add_field( name="Selection Type", value="Manual" if len(ctx.message.mentions) == 2 else "Random") embed_a.add_field(name="Ten Man Status", value="[Link](" + self.__status_message.jump_url + ")") embed_b = discord.Embed(title="Captain Selected", color=discord.Color.blue()) embed_b.set_thumbnail(url=captain_b.avatar_url) embed_b.add_field(name="Name", value=captain_b.name) embed_b.add_field( name="Selection Type", value="Manual" if len(ctx.message.mentions) == 2 else "Random") embed_b.add_field(name="Ten Man Status", value="[Link](" + self.__status_message.jump_url + ")") await ctx.channel.send(embed=embed_a) await ctx.channel.send(embed=embed_b) try: await self.__move_user_to_proper_voice(ctx, captain_a, TeamStatus.A) await self.__move_user_to_proper_voice(ctx, captain_b, TeamStatus.B) except discord.errors.HTTPException: pass status_embed = self.__status_message.embeds[0] rp_field = status_embed.fields[3] status_embed.set_field_at( index=3, name=rp_field.name, value="\n".join([ find(lambda u: u.id == rp, ctx.guild.members).name for rp in self.__ongoing.get_remaining_participant_ids() ])) status_embed.insert_field_at(index=4, name="Team A", value=captain_a.name, inline=True) status_embed.insert_field_at(index=5, name="Team B", value=captain_b.name, inline=True) await self.__status_message.edit(embed=status_embed) if self.__display_help: message = "***Help Message***:\nNow that captains have been selected, it is time for the captain of Team" \ "A to pick a player. They can do so by using the command\n`.pick_player @mention`" await ctx.channel.send(message)