async def removal(self, ctx: commands.Context, action: str): message = "Would you like to reset the {}?".format(action) can_react = ctx.channel.permissions_for(ctx.me).add_reactions if not can_react: message += " (y/n)" question: discord.Message = await ctx.send(message) if can_react: start_adding_reactions( question, ReactionPredicate.YES_OR_NO_EMOJIS ) pred = ReactionPredicate.yes_or_no(question, ctx.author) event = "reaction_add" else: pred = MessagePredicate.yes_or_no(ctx) event = "message" try: await ctx.bot.wait_for(event, check=pred, timeout=20) except asyncio.TimeoutError: await question.delete() await ctx.send("Okay then :D") if not pred.result: await question.delete() return await ctx.send("Canceled!") else: if can_react: with suppress(discord.Forbidden): await question.clear_reactions() await self.config.guild(ctx.guild).set_raw(action, value=None) await ctx.send("Removed the {}!".format(action)) pred = ReactionPredicate.yes_or_no(question, ctx.author) event = "reaction_add"
async def one_from(ctx,user,list): #user needs to be a discord.member object. list is a namestring of a droplist of items here. chance = getattr(Treasure, list) itemname = random.choice(list(chance.keys())) item = chance[itemname] if item['slot'] == ['consumable']: item['uses'] = random.randint(1,item['uses']) await ctx.send("```css\n{} found {} ({}x).```".format(user.display_name,itemname,item['uses'])) msg = await ctx.send("Do you want to use, put in backpack or sell this item?") start_adding_reactions(msg, Treasure.controls.keys()) if hasattr(user, "id"): pred = ReactionPredicate.with_emojis(tuple(Treasure.controls.keys()), msg, user) else: pred = ReactionPredicate.with_emojis(tuple(Treasure.controls.keys()), msg, ctx.author) react = None try: react, user = await ctx.bot.wait_for("reaction_add", check=pred, timeout=60) except asyncio.TimeoutError: await ctx.send("Item claim timed out after one minute. Selling...") react_emoji = "💰" try: await msg.clear_reactions() except discord.Forbidden: # cannot remove all reactions for key in Treasure.controls.keys(): await msg.remove_reaction(key, ctx.bot.user) if react != None: react_emoji = react.emoji return {"itemname": itemname,"item":item,"equip":Treasure.controls[react_emoji]} else: if len(item["slot"]) == 2: # two handed weapons add their bonuses twice hand = "two handed" att = item["att"]*2 cha = item["cha"]*2 else: if item["slot"][0] == "right" or item["slot"][0] == "left": hand = item["slot"][0] + " handed" else: hand = item["slot"][0] + " slot" att = item["att"] cha = item["cha"] await ctx.send("```css\n{} found a {}. (Attack: {}, Charisma: {} [{}])```".format(user.display_name,itemname,str(att),str(cha),hand)) msg = await ctx.send("Do you want to equip, put in backpack or sell this item?") start_adding_reactions(msg, Treasure.controls.keys()) pred = ReactionPredicate.with_emojis(tuple(Treasure.controls.keys()), msg, user) react = None try: react, user = await ctx.bot.wait_for("reaction_add", check=pred, timeout=60) except asyncio.TimeoutError: await ctx.send("Item claim timed out after one minute. Selling...") react_emoji = "💰" try: await msg.clear_reactions() except discord.Forbidden: # cannot remove all reactions for key in Treasure.controls.keys(): await msg.remove_reaction(key, ctx.bot.user) if react != None: react_emoji = react.emoji return {"itemname": itemname,"item":item,"equip":Treasure.controls[react_emoji]}
async def find_wiki_name(self, ctx, wiki_name): wikis = await self.get_wikis(ctx) match = get_close_matches(wiki_name, wikis.keys(), 1, 0.3) if not match: # No match found, list of wikis returned instead return msg = await ctx.send( f'I can\'t find a wiki called {wiki_name}. Did you mean`{match[0]}`?' ) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) try: #waiting for reaction pred = ReactionPredicate.yes_or_no(msg, ctx.author) await ctx.bot.wait_for("reaction_add", check=pred, timeout=15) except asyncio.TimeoutError: await ctx.send("You didn\'t react in time, cancelled.") try: # Delete reactions from question message if ctx.channel.permissions_for(ctx.me).manage_messages: await msg.clear_reactions() except: pass if pred.result is not True: return # User didn't responded with tick wiki_name = match[0] return wiki_name
async def confirm(self, ctx, type: str, cost: int): msg = await ctx.send( f"Please confirm that you would like to purchase a {type} for {cost}." ) pred = ReactionPredicate.yes_or_no(msg, ctx.author) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) try: await self.bot.wait_for("reaction_add", check=pred, timeout=30) except asyncio.TimeoutError: await msg.delete() await ctx.send(f":x: You took too long to respond.") if not pred.result: await ctx.send("Okay. No changes have been made.") else: try: await msg.delete() await bank.withdraw_credits(ctx.author, cost) crooks = await self.config.user(ctx.author).crooks() crooks += 1 await self.config.user(ctx.author).crooks.set(crooks) await ctx.send(f"Done. A {type} was successfully purchased for {cost}.") except ValueError: await ctx.send( f"You do not have enough cash! A crook costs {cost}, you have {await bank.get_balance(ctx.author)}." )
async def _send_check_out_message(self, ctx, user, match_day, tier): embed = discord.Embed( title="Check Out", description= "You are currently checked in as available for the following match day and tier. " "Do you wish to take yourself off the availability list? To confirm you want to check out, react with {}" .format(ReactionPredicate.YES_OR_NO_EMOJIS[0]), colour=discord.Colour.blue()) embed.add_field(name="Match Day", value=match_day, inline=True) embed.add_field(name="Tier", value=tier, inline=True) react_msg = await user.send(embed=embed) start_adding_reactions(react_msg, ReactionPredicate.YES_OR_NO_EMOJIS) try: pred = ReactionPredicate.yes_or_no(react_msg, user) await ctx.bot.wait_for("reaction_add", check=pred, timeout=verify_timeout) if pred.result is True: await self._unregister_user(ctx, user, match_day, tier) await user.send( "You have been removed from the list. Thank you for updating your availability!" ) else: await user.send( "Still checked in. If you wish to check out use the command again." ) except asyncio.TimeoutError: await user.send( "Sorry, you didn't react quick enough. Please try again.")
async def _send_check_in_message(self, ctx, user, match_day, tier): embed = discord.Embed( title="Check In", description= "By checking in you are letting GMs know that you are available to play " "on the following match day in the following tier. To confirm react with {}" .format(ReactionPredicate.YES_OR_NO_EMOJIS[0]), colour=discord.Colour.blue()) embed.add_field(name="Match Day", value=match_day, inline=True) embed.add_field(name="Tier", value=tier, inline=True) react_msg = await user.send(embed=embed) start_adding_reactions(react_msg, ReactionPredicate.YES_OR_NO_EMOJIS) try: pred = ReactionPredicate.yes_or_no(react_msg, user) await ctx.bot.wait_for("reaction_add", check=pred, timeout=verify_timeout) if pred.result is True: await self._register_user(ctx, user, match_day, tier) await user.send( "Thank you for checking in! GMs will now be able to see that you're available." ) else: await user.send( "Not checked in. If you wish to check in use the command again." ) except asyncio.TimeoutError: await user.send( "Sorry, you didn't react quick enough. Please try again.")
async def delete_letter(self, ctx: commands.Context, letter_id: str): """ Delete a specific letter. """ letters = await self.config.custom("LetterBox", ctx.author.id).letterbox() if letter_id not in letters: await ctx.send("This letter is not in your letterbox.") return msg = await ctx.send( bold( "Are you sure you want to delete this letter? This action " + underline("cannot be") + " recovered.", escape_formatting=False, )) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(msg, ctx.author) try: await self.bot.wait_for("reaction_add", check=pred, timeout=60) except AsyncTimeoutError: return None if pred.result: await self.config.custom( "LetterBox", ctx.author.id).letterbox.clear_raw(letter_id) await msg.edit(content="Deleted your letter.") else: await msg.edit(content="I won't touch it then!")
async def _react_prompt(self, ctx, prompt, if_not_msg=None, embed: discord.Embed = None): user = ctx.message.author if embed: embed.description = prompt react_msg = await ctx.send(embed=embed) else: react_msg = await ctx.send(prompt) start_adding_reactions(react_msg, ReactionPredicate.YES_OR_NO_EMOJIS) try: pred = ReactionPredicate.yes_or_no(react_msg, user) await ctx.bot.wait_for("reaction_add", check=pred, timeout=verify_timeout) if pred.result: return True if if_not_msg: await ctx.send(if_not_msg) return False except asyncio.TimeoutError: await ctx.send( "Sorry {}, you didn't react quick enough. Please try again.". format(user.mention)) return False
async def _confirm(ctx: commands.Context) -> bool: """Ask "Are you sure?" and get the response as a bool.""" if ctx.guild is None or ctx.guild.me.permissions_in( ctx.channel).add_reactions: msg = await ctx.send(_("Are you sure?")) # noinspection PyAsyncCall task = start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(msg, ctx.author) try: await ctx.bot.wait_for("reaction_add", check=pred, timeout=30) except asyncio.TimeoutError: await ctx.send(_("Response timed out.")) return False else: task.cancel() agreed = pred.result finally: await msg.delete() else: await ctx.send(_("Are you sure? (y/n)")) pred = MessagePredicate.yes_or_no(ctx) try: await ctx.bot.wait_for("message", check=pred, timeout=30) except asyncio.TimeoutError: await ctx.send(_("Response timed out.")) return False else: agreed = pred.result if agreed is False: await ctx.send(_("Action cancelled.")) return agreed
async def create_tag( self, ctx: commands.Context, tag_name: str, tagscript: str, *, global_tag: bool = False ): kwargs = {"author_id": ctx.author.id} if global_tag: guild = None tag = self.get_tag(None, tag_name, global_priority=True) else: guild = ctx.guild tag = self.get_tag(guild, tag_name, check_global=False) kwargs["guild_id"] = guild.id self.validate_tag_count(guild) if tag: tag_prefix = tag.name_prefix msg = await ctx.send( f"`{tag_name}` is already a registered {tag_prefix.lower()}. Would you like to overwrite it?" ) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(msg, ctx.author) try: await ctx.bot.wait_for("reaction_add", check=pred, timeout=30) except asyncio.TimeoutError: return await ctx.send(f"{tag_prefix} edit cancelled.") if pred.result is False: return await ctx.send(f"{tag_prefix} edit cancelled.") await ctx.send(await tag.edit_tagscript(tagscript)) return tag = Tag(self, tag_name, tagscript, **kwargs) await ctx.send(await tag.initialize())
async def _confirm(ctx: commands.Context) -> bool: """Ask "Are you sure?" and get the response as a bool.""" if ctx.guild is None or ctx.guild.me.permissions_in(ctx.channel).add_reactions: msg = await ctx.send(_("Are you sure?")) # noinspection PyAsyncCall task = start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS, ctx.bot.loop) pred = ReactionPredicate.yes_or_no(msg, ctx.author) try: await ctx.bot.wait_for("reaction_add", check=pred, timeout=30) except asyncio.TimeoutError: await ctx.send(_("Response timed out.")) return False else: task.cancel() agreed = pred.result finally: await msg.delete() else: await ctx.send(_("Are you sure? (y/n)")) pred = MessagePredicate.yes_or_no(ctx) try: await ctx.bot.wait_for("message", check=pred, timeout=30) except asyncio.TimeoutError: await ctx.send(_("Response timed out.")) return False else: agreed = pred.result if agreed is False: await ctx.send(_("Action cancelled.")) return agreed
async def _profile_delete(self, ctx: commands.Context): """Deletes your profile permanently""" try: exists_msg = await ctx.author.send( "This cannot be undone and you will have to create a new profile, " "do you want to continue? (y/n)" ) start_adding_reactions(exists_msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(exists_msg, ctx.author) await self.bot.wait_for("reaction_add", check=pred) except discord.Forbidden: return await ctx.send(f"I can't DM you, {ctx.author.mention}") if pred.result: user_group = self.profileConfig.user(ctx.author) async with user_group() as user_data: user_data.clear() account_group = self.config.user(ctx.author) async with account_group() as account_data: account_data.clear() await ctx.author.send( f"To created a new one please run `{self._profile_create.qualified_name}`" ) else: await ctx.author.send("Your profile hasn't been touched")
async def reactrole_delete( self, ctx: commands.Context, message: Union[discord.Message, ObjectConverter], ): """Delete an entire reaction role for a message.""" message_data = await self.config.custom("GuildMessage", ctx.guild.id, message.id).all() if not message_data["reactroles"]["react_to_roleid"]: return await ctx.send("There are no reaction roles set up for that message.") msg = await ctx.send( "Are you sure you want to remove all reaction roles for that message?" ) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(msg, ctx.author) try: await self.bot.wait_for("reaction_add", check=pred, timeout=60) except asyncio.TimeoutError: await ctx.send("Action cancelled.") if pred.result: await self.config.custom("GuildMessage", ctx.guild.id, message.id).clear() await ctx.send("Reaction roles cleared for that message.") self._edit_cache(message.id, True) else: await ctx.send("Action cancelled.")
async def einfo(self, ctx, *, emoji: Union[discord.Emoji, discord.PartialEmoji] = None): """Get info about emoji""" if emoji is None: if ctx.channel.permissions_for(ctx.author).add_reactions: m = await ctx.send(_("React to this message with your emoji")) try: reaction = await ctx.bot.wait_for( "reaction_add", check=ReactionPredicate.same_context(message=m, user=ctx.author), timeout=30, ) emoji = reaction[0].emoji except AsyncTimeoutError: return finally: await m.delete(delay=0) else: await ctx.send_help() return em = await self.emoji_embed(ctx, emoji) await ctx.send(embed=em)
async def add_reactions_with_cancel( ctx: Context, msg: discord.Message, emojis: Iterable[Union[str, discord.Emoji]], timeout: int = 30, with_keep: bool = False, ): """Add reactions with, for a limited time, author-only cancel.""" _emojis = [emojis] if isinstance(emojis, str) else list(emojis) extra_emojis = [] cancel = "\N{CROSS MARK}" _emojis.append(cancel) extra_emojis.append(cancel) if with_keep: keep = "\N{WHITE HEAVY CHECK MARK}" _emojis.append(keep) extra_emojis.append(keep) start_adding_reactions(msg, _emojis) pred = ReactionPredicate.with_emojis(extra_emojis, msg, user=ctx.author) try: await ctx.bot.wait_for("reaction_add", check=pred, timeout=timeout) if pred.result == 0: with contextlib.suppress(discord.HTTPException): await msg.delete() return True except asyncio.TimeoutError: pass with contextlib.suppress(discord.HTTPException): for emoji in extra_emojis: await msg.clear_reaction(emoji) return False
async def delete_trigger(self, payload: discord.RawReactionActionEvent) -> None: """Enables and disables triggers""" member = self.ctx.guild.get_member(payload.user_id) if await self.cog.can_edit(member, self.source.selection): msg = await self.ctx.send( _("Are you sure you want to delete trigger {name}?").format( name=self.source.selection.name)) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(msg, self.ctx.author) await self.ctx.bot.wait_for("reaction_add", check=pred) if pred.result: await msg.delete() self.source.selection.disable() done = await self.cog.remove_trigger( payload.guild_id, self.source.selection.name) if done: page = await self._source.get_page(self.current_page) kwargs = await self._get_kwargs_from_page(page) await self.message.edit( content=_("This trigger has been deleted."), embed=kwargs["embed"]) for t in self.cog.triggers[self.ctx.guild.id]: if t.name == self.source.selection.name: self.cog.triggers[self.ctx.guild.id].remove(t)
async def _choose_player( self, ctx: commands.Context, players: Tuple[rlapi.Player, ...] ) -> rlapi.Player: players_len = len(players) if players_len > 1: description = "" for idx, player in enumerate(players, 1): description += "\n{}. {} account with username: {}".format( idx, player.platform, player.user_name ) msg = await ctx.send( embed=discord.Embed( title="There are multiple accounts with provided name:", description=description, ) ) emojis = ReactionPredicate.NUMBER_EMOJIS[1 : players_len + 1] start_adding_reactions(msg, emojis) pred = ReactionPredicate.with_emojis(emojis, msg) try: await ctx.bot.wait_for("reaction_add", check=pred, timeout=15) except asyncio.TimeoutError: raise errors.NoChoiceError( "User didn't choose profile he wants to check" ) finally: await msg.delete() return players[pred.result] return players[0]
async def manifest(self, ctx: commands.Context) -> None: """ See the current manifest version and optionally re-download it """ version = await self.config.manifest_version() if not version: version = "Not Downloaded" await ctx.send( _("Current manifest version is {version}").format(version=version)) await ctx.trigger_typing() msg = await ctx.send(_("Would you like to re-download the manifest?")) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(msg, ctx.author) try: react, user = await self.bot.wait_for("reaction_add", check=pred, timeout=15) except asyncio.TimeoutError: await msg.delete() if pred.result: try: version = await self.get_manifest() except Exception: return await ctx.send( _("There was an issue downloading the manifest.")) await msg.delete() await ctx.send(f"Manifest {version} was downloaded.") else: await msg.delete()
async def verify_game_results(self, ctx, game, blue_team_wins, orange_team_wins, verifier: discord.Member): msg = await ctx.send( "{0} Please verify the results:\n**{1}** {2} - {3} **{4}**".format( verifier.mention, game.blue.name, blue_team_wins, orange_team_wins, game.orange.name)) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) game.scoreReported = True pred = ReactionPredicate.yes_or_no(msg, verifier) try: await ctx.bot.wait_for("reaction_add", check=pred, timeout=verify_timeout) if pred.result is True: return True else: game.scoreReported = False await ctx.send( ":x: Ladder game result not verified. To report the result you will need to use the `{0}lr` command again." .format(ctx.prefix)) return False except asyncio.TimeoutError: game.scoreReported = False await ctx.send( ":x: Ladder game result not verified in time. To report the result you will need to use the `{0}lr` command again.\n" "**If one of the captains is afk, have someone from that team use the command.**" .format(ctx.prefix)) return False
async def check_clear_event(self, ctx: commands.Context) -> bool: msg = await ctx.send( "You already have an event running, would you like to cancel it?") start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(msg, ctx.author) await ctx.bot.wait_for("reaction_add", check=pred) return pred.result
async def _embed_react_prompt(self, ctx, embed, existing_message=None, success_embed=None, reject_embed=None, clear_after_confirm=True): user = ctx.message.author if existing_message: react_msg = existing_message await react_msg.edit(embed=embed) else: react_msg = await ctx.send(embed=embed) start_adding_reactions(react_msg, ReactionPredicate.YES_OR_NO_EMOJIS) try: pred = ReactionPredicate.yes_or_no(react_msg, user) await ctx.bot.wait_for("reaction_add", check=pred, timeout=verify_timeout) if pred.result: await react_msg.edit(embed=success_embed) if clear_after_confirm: await react_msg.clear_reactions() return True if reject_embed: await react_msg.edit(embed=reject_embed) return False except asyncio.TimeoutError: await react_msg.edit(embed=reject_embed) await ctx.send( "Sorry {}, you didn't react quick enough. Please try again.". format(user.mention)) return False
async def buy_gem_skin(self, ctx: Context, user: discord.User, config: Config, item_data: dict): brawler = item_data["brawler"] cost = item_data["cost"] skin = item_data["skin"] gems = await config.user(user).gems() if gems < cost: await ctx.send(f"You do not have enough gems! ({gems}/{cost})") return False msg = await ctx.send( f"{user.mention} Buying **{skin} {brawler}**" f" skin will cost {emojis['gem']} {cost}. Continue?") start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(msg, user) await ctx.bot.wait_for("reaction_add", check=pred) if pred.result: # User responded with tick pass else: # User responded with cross await ctx.send("Purchase cancelled.") return False async with config.user(user).brawlers() as brawlers: brawlers[brawler]["skins"].append(skin) await config.user(user).gems.set(gems - cost) await ctx.send(f"Bought {skin} {brawler} skin!") return True
async def setup_delete_definition(self, ctx: commands.Context, definition_name:str) -> None: """Delete a defined game Note that this does delete any files or folders. Parameters ---------- definition_name: str Name of the game to delete. """ game_defs = await self._conf.game_defs() if definition_name not in game_defs.keys(): return await self._embed_msg( ctx, title=_("No Such Definition"), description=_(f"{name} does not exist."), error=True ) # Ask the user if they are really sure about this info_msg = _( "Are you sure you want to delete?:\n" "```\n" f"{definition_name}\n" "```\n" ) info = await ctx.maybe_send_embed(info_msg) start_adding_reactions(info, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(info, ctx.author) await ctx.bot.wait_for("reaction_add", check=pred) # If user said no if not pred.result: with contextlib.suppress(discord.HTTPException): await info.delete() return else: # If an instance is running, shut it down if self._locks.get(definition_name, None) is not None: async with self._locks[definition_name]: if self._instances.get(definition_name, None) is not None: if self._instances[definition_name].isRunning(): self._instances[definition_name].stop() # Delete it from the list del game_defs[definition_name] await self._conf.game_defs.set(game_defs) # Delete the channel registrations defs_to_channels = await self._conf.defs_to_channels() channels_to_defs = await self._conf.channels_to_defs() for channel_id in channels_to_defs.keys(): del channels_to_defs[channel_id] await self._conf.channels_to_defs.set(channels_to_defs) del defs_to_channels[definition_name] await self._conf.defs_to_channels.set(defs_to_channels) # Report success return await self._embed_msg( ctx, title=_("Deletion Successful"), description=_(f"{definition_name} has been deleted."), success=True )
async def convert( self, ctx: Context, argument: str ) -> Optional[Union[List[Dict[str, dict]], str]]: result: Optional[Union[List[Dict[str, dict]], str]] = [] team_list = await check_valid_team(argument) my_perms = ctx.channel.permissions_for(ctx.guild.me) if team_list == []: raise BadArgument('Team "{}" not found'.format(argument)) if len(team_list) == 1: result = team_list[0] else: # This is just some extra stuff to correct the team picker msg = _("There's multiple teams with that name, pick one of these:\n") new_msg = None if my_perms.add_reactions and my_perms.use_external_emojis: new_msg = await ctx.send(msg) team_emojis = [ await EmojiConverter().convert(ctx, "<:" + TEAMS[team]["emoji"] + ">") for team in team_list ] log.debug(team_emojis) log.debug(team_list) pred = ReactionPredicate.with_emojis(team_emojis, message=new_msg) start_adding_reactions(new_msg, team_emojis) try: reaction, user = await ctx.bot.wait_for("reaction_add", check=pred, timeout=60) except asyncio.TimeoutError: await new_msg.edit(content=_("I guess not.")) return None else: result = team_list[pred.result] log.debug(result) else: for i, team_name in enumerate(team_list): msg += "{}: {}\n".format(i + 1, team_name) def msg_check(m): return m.author == ctx.message.author try: msg = await ctx.bot.wait_for("message", check=msg_check, timeout=60) except asyncio.TimeoutError: await new_msg.edit(content=_("I guess not.")) return None if msg.content.isdigit(): msg = int(msg.content) - 1 try: result = team_list[msg] except (IndexError, ValueError, AttributeError): pass else: return_team = None for team in team_list: if msg.content.lower() in team.lower(): return_team = team result = return_team if new_msg: await new_msg.delete() return result
async def find_game_name(self, ctx, game_name): games = await self.get_games(ctx) match = get_close_matches(game_name, games.keys(), 1, 0.3) if not match: # No match was found. Returing a list of games. return # Found a match. msg = await ctx.send(f'I can\'t find a game called `{game_name}`.\nDid you mean `{match[0]}`?') start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) try: # Wait for a reaction on question pred = ReactionPredicate.yes_or_no(msg, ctx.author) await ctx.bot.wait_for("reaction_add", check=pred, timeout=15) except asyncio.TimeoutError: await ctx.send("You didn\'t react in time, cancelled.") try: # Delete reactions from question message if ctx.channel.permissions_for(ctx.me).manage_messages: await msg.clear_reactions() except: pass if pred.result is not True: return # User didn't responded with tick game_name = match[0] return game_name
async def leave_guilds(self, ctx: commands.Context, guilds: list, message: str): data = await self.config.all() unwl_guilds = [guild for guild in guilds if guild.id not in data["whitelist"]] if not unwl_guilds: await ctx.send("There are no servers to leave that aren't whitelisted.") return name_ids = "\n".join([f"{guild.name} - ({guild.id})" for guild in unwl_guilds][:5]) guild_preview = name_ids + ( f"\nand {len(unwl_guilds) - 5} other guilds.." if len(unwl_guilds) > 5 else "" ) msg = await ctx.send( f"Are you sure you want me to leave the following {len(unwl_guilds)} guilds?\n" + box(guild_preview, "py") ) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(msg, ctx.author) try: await self.bot.wait_for("reaction_add", check=pred, timeout=60) except asyncio.TimeoutError: await ctx.send("Action cancelled.") if pred.result is True: async with ctx.typing(): for guild in unwl_guilds: await self.notify_guild(guild, message) await guild.leave() await self.baron_log("mass_leave", guilds=unwl_guilds, author=ctx.author) await ctx.send(f"Done. I left {len(unwl_guilds)} servers.") else: await ctx.send("Action cancelled.")
async def tag_global_add(self, ctx: commands.Context, tag_name: TagName, *, tagscript: TagScriptConverter): """ Add a global tag with TagScript. [Tag usage guide](https://phen-cogs.readthedocs.io/en/latest/blocks.html#usage) """ tag = self.get_tag(None, tag_name, check_global=True) if tag: msg = await ctx.send( f"`{tag_name}` is already registered global tag. Would you like to overwrite it?" ) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(msg, ctx.author) try: await ctx.bot.wait_for("reaction_add", check=pred, timeout=30) except asyncio.TimeoutError: return await ctx.send("Global tag edit cancelled.") if pred.result is False: return await ctx.send("Global tag edit cancelled.") tag.tagscript = tagscript await tag.update_config() await ctx.send(f"Global tag `{tag}` edited.") return tag = Tag(self, tag_name, tagscript, author_id=ctx.author.id) self.global_tag_cache[tag_name] = tag await tag.update_config() await ctx.send(f"Global tag `{tag}` added.")
async def yes_or_no(ctx, message) -> bool: msg = await ctx.send(message) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) pred = ReactionPredicate.yes_or_no(msg, ctx.author) await ctx.bot.wait_for("reaction_add", check=pred) await msg.delete() return pred.result
async def icon_emoji(self, ctx, *, emoji: Union[discord.Emoji, discord.PartialEmoji] = None): """Change icon of personal role using emoji""" role = await self.config.member(ctx.author).role() role = ctx.guild.get_role(role) if not emoji: if ctx.channel.permissions_for(ctx.author).add_reactions: m = await ctx.send(_("React to this message with your emoji")) try: reaction = await ctx.bot.wait_for( "reaction_add", check=ReactionPredicate.same_context(message=m, user=ctx.author), timeout=30, ) emoji = reaction[0].emoji except AsyncTimeoutError: return finally: await m.delete(delay=0) else: await ctx.send_help() return try: if isinstance(emoji, (discord.Emoji, discord.PartialEmoji)): await edit_role_icon( self.bot, role, icon=await emoji.url_as(format="png").read(), reason=get_audit_reason(ctx.author, _("Personal Role")), ) else: await edit_role_icon( self.bot, role, unicode_emoji=emoji, reason=get_audit_reason(ctx.author, _("Personal Role")), ) except discord.Forbidden: ctx.command.reset_cooldown(ctx) await ctx.send( chat.error( _("Unable to edit role.\nRole must be lower than my top role" ))) except discord.InvalidArgument: await ctx.send( chat.error( _("This image type is unsupported, or link is incorrect"))) except discord.HTTPException as e: ctx.command.reset_cooldown(ctx) await ctx.send(chat.error(_("Unable to edit role: {}").format(e))) else: await ctx.send( _("Changed icon of {user}'s personal role").format( user=ctx.message.author.name))
async def choose_cog(self, ctx: commands.Context, cogs: List[commands.Cog]) -> Optional[commands.Cog]: """Ask user to choose a cog from provided `cogs` list.""" if len(cogs) == 1: return cogs[0] cogs = sorted(cogs[:9], key=lambda cog: cog.qualified_name) emojis = ReactionPredicate.NUMBER_EMOJIS[1:len(cogs) + 1] use_embeds = await ctx.embed_requested() lines = [] if use_embeds: for idx, cog in enumerate(cogs, 1): cog_name = cog.qualified_name short_doc, *_ = cog.format_help_for_context(ctx).partition( "\n\n") if len(short_doc) > 70: short_doc = f"{short_doc[:67]}..." lines.append(f"{idx}. {bold(cog_name)} - {short_doc}") description = "\n".join(lines) embed = discord.Embed( title="There are multiple categories with provided name:", description=description, ) msg = await ctx.send(embed=embed) else: # all cog names should have the same width since only casing differs doc_max_width = 80 - len(cogs[0].qualified_name) for idx, cog in enumerate(cogs, 1): cog_name = cog.qualified_name short_doc, *_ = cog.format_help_for_context(ctx).partition( "\n\n") if len(short_doc) > doc_max_width: short_doc = f"{short_doc[: doc_max_width - 3]}..." lines.append(f"{idx}. {cog_name}: {short_doc}") description = "\n".join(lines) msg = await ctx.send( f"There are multiple categories with provided name: {box(description)}" ) start_adding_reactions(msg, emojis) pred = ReactionPredicate.with_emojis(emojis, msg) try: await ctx.bot.wait_for("reaction_add", check=pred, timeout=30) except asyncio.TimeoutError: return None finally: await msg.delete() result = cast(int, pred.result) return cogs[result]
async def clean(self, ctx: commands.Context): """ Dehoist all members in the guild. NOTE: If the server owner is hoisted, [botname] cannot change their nickname. """ hoisted_count = await self.get_hoisted_count(ctx) guild_config = await self.config.guild(ctx.guild).all() nickname = guild_config["nickname"] ignored_users = guild_config["ignored_users"] if not hoisted_count: return await ctx.send("There are no hoisted members.") if not ctx.channel.permissions_for(ctx.me).add_reactions: return await ctx.send("I cannot add reactions.") if not ctx.channel.permissions_for(ctx.me).manage_nicknames: return await ctx.send("I do not have permission to edit nicknames." ) msg = await ctx.send( f"Are you sure you would like to dehoist {hoisted_count} hoisted users? " f"This may take a few moments.\nTheir nickname's will be changed to `{nickname}`, " f"you can cancel now and change this nickname via `{ctx.clean_prefix}hoist set nickname` " "if you wish.") pred = ReactionPredicate.yes_or_no(msg, ctx.author) start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS) try: await self.bot.wait_for("reaction_add", check=pred, timeout=30) except asyncio.TimeoutError: await msg.delete() return await ctx.send(f"You took too long to respond.") if pred.result: await ctx.trigger_typing() exceptions = 0 for m in ctx.guild.members: if m.display_name.startswith( HOIST) and not m.bot and m.id not in ignored_users: try: await m.edit( nick=await self.config.guild(ctx.guild).nickname()) except discord.Forbidden: # This exception will only occur if an attempt is made to dehoist server owner exceptions += 1 await ctx.send( f"I could not change {ctx.guild.owner.name}'s nickname because I cannot edit owner nicknames." ) await ctx.send( f"{hoisted_count - exceptions} users have been dehoisted.") else: await ctx.send("No changes have been made.")
async def _cog_update(self, ctx, cog_name: InstalledCog = None): """Update all cogs, or one of your choosing.""" installed_cogs = set(await self.installed_cogs()) async with ctx.typing(): if cog_name is None: updated = await self._repo_manager.update_all_repos() else: try: updated = await self._repo_manager.update_repo(cog_name.repo_name) except KeyError: # Thrown if the repo no longer exists updated = {} updated_cogs = set(cog for repo in updated for cog in repo.available_cogs) installed_and_updated = updated_cogs & installed_cogs if installed_and_updated: await self._reinstall_requirements(installed_and_updated) await self._reinstall_cogs(installed_and_updated) await self._reinstall_libraries(installed_and_updated) message = _("Cog update completed successfully.") cognames = {c.name for c in installed_and_updated} message += _("\nUpdated: ") + humanize_list(tuple(map(inline, cognames))) else: await ctx.send(_("All installed cogs are already up to date.")) return await ctx.send(message) cognames &= set(ctx.bot.extensions.keys()) # only reload loaded cogs if not cognames: return await ctx.send( _("None of the updated cogs were previously loaded. Update complete.") ) message = _("Would you like to reload the updated cogs?") can_react = ctx.channel.permissions_for(ctx.me).add_reactions if not can_react: message += " (y/n)" query: discord.Message = await ctx.send(message) if can_react: # noinspection PyAsyncCall start_adding_reactions(query, ReactionPredicate.YES_OR_NO_EMOJIS, ctx.bot.loop) pred = ReactionPredicate.yes_or_no(query, ctx.author) event = "reaction_add" else: pred = MessagePredicate.yes_or_no(ctx) event = "message" try: await ctx.bot.wait_for(event, check=pred, timeout=30) except asyncio.TimeoutError: await query.delete() return if pred.result is True: if can_react: with contextlib.suppress(discord.Forbidden): await query.clear_reactions() await ctx.invoke(ctx.bot.get_cog("Core").reload, *cognames) else: if can_react: await query.delete() else: await ctx.send(_("OK then."))