async def cc_list(self, ctx): """Shows custom commands list""" response = await CommandObj.get_commands(self.config.guild(ctx.guild)) if not response: await ctx.send( _("There are no custom commands in this server." " Use `{}` to start adding some.").format( "{}customcom add".format(ctx.prefix))) return results = [] for command, body in response.items(): responses = body["response"] if isinstance(responses, list): result = ", ".join(responses) elif isinstance(responses, str): result = responses else: continue results.append("{command:<15} : {result}".format(command=command, result=result)) commands = "\n".join(results) if len(commands) < 1500: await ctx.send(box(commands)) else: for page in pagify(commands, delims=[" ", "\n"]): await ctx.author.send(box(page))
async def economyset(self, ctx: commands.Context): """Changes economy module settings""" guild = ctx.guild if ctx.invoked_subcommand is None: if await bank.is_global(): slot_min = await self.config.SLOT_MIN() slot_max = await self.config.SLOT_MAX() slot_time = await self.config.SLOT_TIME() payday_time = await self.config.PAYDAY_TIME() payday_amount = await self.config.PAYDAY_CREDITS() else: slot_min = await self.config.guild(guild).SLOT_MIN() slot_max = await self.config.guild(guild).SLOT_MAX() slot_time = await self.config.guild(guild).SLOT_TIME() payday_time = await self.config.guild(guild).PAYDAY_TIME() payday_amount = await self.config.guild(guild).PAYDAY_CREDITS() register_amount = await bank.get_default_balance(guild) msg = box( _( "Minimum slot bid: {}\n" "Maximum slot bid: {}\n" "Slot cooldown: {}\n" "Payday amount: {}\n" "Payday cooldown: {}\n" "Amount given at account registration: {}" "" ).format( slot_min, slot_max, slot_time, payday_amount, payday_time, register_amount ), _("Current Economy settings:"), ) await ctx.send(msg)
async def send_leaderboard(self, ctx: commands.Context, data: dict, key: str, top: int): """Send the leaderboard from the given data. Parameters ---------- ctx : commands.Context The context to send the leaderboard to. data : dict The data for the leaderboard. This must map `discord.Member` -> `dict`. key : str The field to sort the data by. Can be ``wins``, ``total_score``, ``games`` or ``average_score``. top : int The number of members to display on the leaderboard. Returns ------- `list` of `discord.Message` The sent leaderboard messages. """ if not data: await ctx.send("There are no scores on record!") return leaderboard = self._get_leaderboard(data, key, top) ret = [] for page in pagify(leaderboard): ret.append(await ctx.send(box(page, lang="py"))) return ret
async def set_cases(self, ctx: commands.Context, action: str = None): """Enables or disables case creation for each type of mod action""" guild = ctx.guild if action is None: # No args given casetypes = await modlog.get_all_casetypes(guild) await ctx.send_help() title = _("Current settings:") msg = "" for ct in casetypes: enabled = await ct.is_enabled() value = "enabled" if enabled else "disabled" msg += "%s : %s\n" % (ct.name, value) msg = title + "\n" + box(msg) await ctx.send(msg) return casetype = await modlog.get_casetype(action, guild) if not casetype: await ctx.send(_("That action is not registered")) else: enabled = await casetype.is_enabled() await casetype.set_enabled(True if not enabled else False) msg = _("Case creation for {} actions is now {}.").format( action, "enabled" if not enabled else "disabled") await ctx.send(msg)
async def selfrole_list(self, ctx: commands.Context): """ Lists all available selfroles. """ selfroles = await self._valid_selfroles(ctx.guild) fmt_selfroles = "\n".join(["+ " + r.name for r in selfroles]) msg = "Available Selfroles:\n{}".format(fmt_selfroles) await ctx.send(box(msg, "diff"))
async def discover_guild( self, author: discord.User, *, mod: bool = False, permissions: Union[discord.Permissions, dict] = None, prompt: str = "", ): """ discovers which of shared guilds between the bot and provided user based on conditions (mod or permissions is an or) prompt is for providing a user prompt for selection """ shared_guilds = [] if permissions is None: perms = discord.Permissions() elif isinstance(permissions, discord.Permissions): perms = permissions else: perms = discord.Permissions(**permissions) for guild in self.bot.guilds: x = guild.get_member(author.id) if x is not None: if await self.internal_filter(x, mod, perms): shared_guilds.append(guild) if len(shared_guilds) == 0: raise ValueError("No Qualifying Shared Guilds") if len(shared_guilds) == 1: return shared_guilds[0] output = "" guilds = sorted(shared_guilds, key=lambda g: g.name) for i, guild in enumerate(guilds, 1): output += "{}: {}\n".format(i, guild.name) output += "\n{}".format(prompt) for page in pagify(output, delims=["\n"]): dm = await author.send(box(page)) def pred(m): return m.author == author and m.channel == dm.channel try: message = await self.bot.wait_for("message", check=pred, timeout=45) except asyncio.TimeoutError: await author.send(_("You took too long to select. Try again later.")) return None try: message = int(message.content.strip()) guild = guilds[message - 1] except (ValueError, IndexError): await author.send(_("That wasn't a valid choice.")) return None else: return guild
async def trivia_list(self, ctx: commands.Context): """List available trivia categories.""" lists = set(p.stem for p in self._all_lists()) msg = box("**Available trivia lists**\n\n{}".format(", ".join(sorted(lists)))) if len(msg) > 1000: await ctx.author.send(msg) return await ctx.send(msg)
async def _list_global_alias(self, ctx: commands.Context): """ Lists the available global aliases on this bot. """ names = [_("Aliases:")] + sorted( ["+ " + a.name for a in await self.unloaded_global_aliases()]) if len(names) == 0: await ctx.send(_("There are no aliases on this server.")) else: await ctx.send(box("\n".join(names), "diff"))
async def dataconversioncommand(self, ctx: commands.Context, v2path: str): """ Interactive prompt for importing data from Red v2 Takes the path where the v2 install is Overwrites values which have entries in both v2 and v3, use with caution. """ resolver = SpecResolver(Path(v2path.strip())) if not resolver.available: return await ctx.send( _("There don't seem to be any data files I know how to " "handle here. Are you sure you gave me the base " "installation path?")) while resolver.available: menu = _( "Please select a set of data to import by number, or 'exit' to exit" ) for index, entry in enumerate(resolver.available, 1): menu += "\n{}. {}".format(index, entry) menu_message = await ctx.send(box(menu)) def pred(m): return m.channel == ctx.channel and m.author == ctx.author try: message = await self.bot.wait_for("message", check=pred, timeout=60) except asyncio.TimeoutError: return await ctx.send( _("Try this again when you are more ready")) else: if message.content.strip().lower() in [ "quit", "exit", "-1", "q", "cancel" ]: return await ctx.tick() try: message = int(message.content.strip()) to_conv = resolver.available[message - 1] except (ValueError, IndexError): await ctx.send(_("That wasn't a valid choice.")) continue else: async with ctx.typing(): await resolver.convert(self.bot, to_conv) await ctx.send(_("{} converted.").format(to_conv)) await menu_message.delete() else: return await ctx.send( _("There isn't anything else I know how to convert here." "\nThere might be more things I can convert in the future."))
async def _repo_info(self, ctx, repo_name: Repo): """ Lists information about a single repo """ if repo_name is None: await ctx.send(_("There is no repo `{}`").format(repo_name.name)) return msg = _("Information on {}:\n{}").format(repo_name.name, repo_name.description or "") await ctx.send(box(msg))
async def _repo_list(self, ctx): """ Lists all installed repos. """ repos = self._repo_manager.get_all_repo_names() repos = sorted(repos, key=str.lower) joined = _("Installed Repos:\n\n") for repo_name in repos: repo = self._repo_manager.get_repo(repo_name) joined += "+ {}: {}\n".format(repo.name, repo.short or "") for page in pagify(joined, ["\n"], shorten_by=16): await ctx.send(box(page.lstrip(" "), lang="diff"))
async def _cog_info(self, ctx, repo_name: Repo, cog_name: str): """ Lists information about a single cog. """ cog = discord.utils.get(repo_name.available_cogs, name=cog_name) if cog is None: await ctx.send( _("There is no cog `{}` in the repo `{}`").format( cog_name, repo_name.name)) return msg = _("Information on {}:\n{}\n\nRequirements: {}").format( cog.name, cog.description or "", ", ".join(cog.requirements) or "None") await ctx.send(box(msg))
async def triviaset(self, ctx: commands.Context): """Manage trivia settings.""" if ctx.invoked_subcommand is None: settings = self.conf.guild(ctx.guild) settings_dict = await settings.all() msg = box( "**Current settings**\n" "Bot gains points: {bot_plays}\n" "Answer time limit: {delay} seconds\n" "Lack of response timeout: {timeout} seconds\n" "Points to win: {max_score}\n" "Reveal answer on timeout: {reveal_answer}\n" "Payout multiplier: {payout_multiplier}\n" "Allow lists to override settings: {allow_override}" "".format(**settings_dict), lang="py", ) await ctx.send(msg)
async def bankset(self, ctx: commands.Context): """Base command for bank settings""" if ctx.invoked_subcommand is None: if await bank.is_global(): bank_name = await bank._conf.bank_name() currency_name = await bank._conf.currency() default_balance = await bank._conf.default_balance() else: if not ctx.guild: return bank_name = await bank._conf.guild(ctx.guild).bank_name() currency_name = await bank._conf.guild(ctx.guild).currency() default_balance = await bank._conf.guild(ctx.guild ).default_balance() settings = _( "Bank settings:\n\nBank name: {}\nCurrency: {}\nDefault balance: {}" ).format(bank_name, currency_name, default_balance) await ctx.send(box(settings))
async def _cog_list(self, ctx, repo_name: Repo): """ Lists all available cogs from a single repo. """ installed = await self.installed_cogs() installed_str = "" if installed: installed_str = _("Installed Cogs:\n") + "\n".join([ "- {}{}".format(i.name, ": {}".format(i.short) if i.short else "") for i in installed if i.repo_name == repo_name.name ]) cogs = repo_name.available_cogs cogs = _("Available Cogs:\n") + "\n".join([ "+ {}: {}".format(c.name, c.short or "") for c in cogs if not (c.hidden or c in installed) ]) cogs = cogs + "\n\n" + installed_str for page in pagify(cogs, ["\n"], shorten_by=16): await ctx.send(box(page.lstrip(" "), lang="diff"))
async def findcog(self, ctx: commands.Context, command_name: str): """ Figures out which cog a command comes from. Only works with loaded cogs. """ command = ctx.bot.all_commands.get(command_name) if command is None: await ctx.send(_("That command doesn't seem to exist.")) return # Check if in installed cogs cog_name = self.cog_name_from_instance(command.instance) installed, cog_installable = await self.is_installed(cog_name) if installed: msg = self.format_findcog_info(command_name, cog_installable) else: # Assume it's in a base cog msg = self.format_findcog_info(command_name, command.instance) await ctx.send(box(msg))
async def send_table(self): """Send a table of scores to the session's channel.""" table = "+ Results: \n\n" for user, score in self.scores.most_common(): table += "+ {}\t{}\n".format(user, score) await self.ctx.send(box(table, lang="diff"))
async def send_interactive(self, messages: Iterable[str], box_lang: str = None, timeout: int = 15) -> List[discord.Message]: """Send multiple messages interactively. The user will be prompted for whether or not they would like to view the next message, one at a time. They will also be notified of how many messages are remaining on each prompt. Parameters ---------- messages : `iterable` of `str` The messages to send. box_lang : str If specified, each message will be contained within a codeblock of this language. timeout : int How long the user has to respond to the prompt before it times out. After timing out, the bot deletes its prompt message. """ messages = tuple(messages) ret = [] more_check = lambda m: (m.author == self.author and m.channel == self. channel and m.content.lower() == "more") for idx, page in enumerate(messages, 1): if box_lang is None: msg = await self.send(page) else: msg = await self.send(box(page, lang=box_lang)) ret.append(msg) n_remaining = len(messages) - idx if n_remaining > 0: if n_remaining == 1: plural = "" is_are = "is" else: plural = "s" is_are = "are" query = await self.send( "There {} still {} message{} remaining. " "Type `more` to continue." "".format(is_are, n_remaining, plural)) try: resp = await self.bot.wait_for("message", check=more_check, timeout=timeout) except asyncio.TimeoutError: await query.delete() break else: try: await self.channel.delete_messages((query, resp)) except (discord.HTTPException, AttributeError): # In case the bot can't delete other users' messages, # or is not a bot account # or chanel is a DM await query.delete() return ret