async def _make_embed_reddit_simple(self, ctx: commands.Context, sub: str, name: str, emoji: str): """Function to make the embed for all Reddit API images.""" try: url, subr = await asyncio.wait_for( self._get_reddit_imgs_simple(ctx, sub=sub), 3) except asyncio.TimeoutError: await ctx.send( "Failed to get an image.\n" "(Timeout error, it most likely means that Reddit API haven't returned images for 3 seconds)" ) return if not url: return em = "" # FIXME That thing is dumb. if url.endswith(GOOD_EXTENSIONS): em = await self._embed( color=await ctx.embed_colour(), title=(_("Here is {name} ... ") + emoji).format(name=name), description=bold( _("[Link if you don't see image]({url})")).format(url=url), image=url, footer=_("Requested by {req} • From r/{r}").format( req=ctx.author.display_name, r=subr), ) elif url.startswith("https://gfycat.com"): em = (_("Here is {name} gif ... ") + emoji + _("\n\nRequested by {req} • From {r}\n{url}")).format( name=name, req=bold(ctx.author.display_name), r=bold(subr), url=url) return em
async def _make_embed_reddit_details(self, ctx, sub, name, emoji, url): """Function to make the embed for all Reddit API images with details.""" url, subr, author, title, post = await self._get_reddit_imgs_details( ctx, sub=sub) if url is None: return if url.endswith(GOOD_EXTENSIONS): em = await self._embed( color=await ctx.embed_colour(), title=(_("Here is {name} ... ") + emoji).format(name=name), description=(_( "**Reddit Author:** {author}\n**Title:** {title}\n" "**[Link if you don't see image]({url})\n[Link of Reddit post]({post})**" )).format(author=author, title=title, url=url, post=post), image=url, footer=_("Requested by {req} • From r/{r}").format( req=ctx.author.display_name, r=subr), ) if url.startswith("https://gfycat.com"): em = (_("Here is {name} gif ... ") + emoji + _( "\n{url}\n\n**Reddit Author:** {author}\n**Title:** {title}\n" "Requested by {req} • From r/{r}\n**Link of Reddit post** {post}" )).format( url=url, name=name, author=author, title=title, req=bold(ctx.author.display_name), r=bold(subr), post=post, ) return em
async def _make_embed(self, ctx, sub, name, url): """Function to make the embed for all Reddit API images.""" url, subr = await self._get_imgs(ctx, sub=sub, url=None, subr=None) if url is None: return if url.endswith(GOOD_EXTENSIONS): em = await self._embed( color=0x891193, title=(("Here, have some {name} ") + " \N{EYES}").format(name=name), description=bold(("[Click here if don't see image]({url})")).format(url=url), image=url, footer=("Requested by {req} {emoji} • From r/{r}").format( req=ctx.author.display_name, emoji=await self.emoji(), r=subr ), ) if url.startswith("https://gfycat.com"): em = ( ("Here is a {name} gif ...") + " \N{EYES}\n\n" + ("Requested by {req} {emoji} • From {r}\n{url}") ).format( name=name, req=bold(f"{ctx.author.display_name}"), emoji=await self.emoji(), r=bold(f"r/{subr}"), url=url, ) return em
async def _make_embed(self, ctx, sub, subr, name, url): url, subr = await self._get_imgs(ctx, sub=sub, url=None, subr=None) if url.endswith(GOOD_EXTENSIONS): em = await self._embed( ctx, color=0x891193, title=(_("Here is {name} image ...") + " \N{EYES}").format(name=name), description=bold( _("[Link if you don't see image]({url})")).format(url=url), image=url, text=_("Requested by {req} {emoji} • From r/{r}").format( req=ctx.author.display_name, emoji=await self.emoji(), r=subr), ) if url.startswith("https://gfycat.com"): em = (_("Here is {name} gif ...") + " \N{EYES}\n\n" + _("Requested by {req} {emoji} • From {r}\n{url}")).format( name=name, req=bold(f"{ctx.author.display_name}"), emoji=await self.emoji(), r=bold(f"r/{subr}"), url=url, ) return em
async def _make_embed(self, ctx: commands.Context, sub: str, name: str): """Function to make the embed for all Reddit API images.""" try: url, subr = await asyncio.wait_for(self._get_imgs(ctx, sub=sub), 3) except asyncio.TimeoutError: await ctx.send( "Failed to get an image. Please try again later. (Timeout error)" ) return if not url: return if url.endswith(GOOD_EXTENSIONS): em = await self._embed( color=0x891193, title=(_("Here is {name} image ...") + " \N{EYES}").format(name=name), description=bold( _("[Link if you don't see image]({url})").format(url=url), escape_formatting=False, ), image=url, footer=_("Requested by {req} {emoji} • From r/{r}").format( req=ctx.author.display_name, emoji=emoji(), r=subr), ) if url.startswith("https://gfycat.com"): em = (_("Here is {name} gif ...") + " \N{EYES}\n\n" + _("Requested by {req} {emoji} • From {r}\n{url}")).format( name=name, req=bold(ctx.author.display_name), emoji=emoji(), r=bold(f"r/{subr}"), url=url, ) return em
async def ip(self, ctx): """Display the server IP and port.""" ip = await self.config.guild(ctx.guild).ip() game_port = await self.config.guild(ctx.guild).game_port() if ip and game_port: await ctx.send("The server ip is " + bold(ip) + ":" + bold(game_port) + ".") else: await ctx.send("This information is not yet configured.")
async def _game(self, ctx, game: str = None): """Set the game.""" if game is not None: await self.config.guild(ctx.guild).game.set(game) await ctx.send("GameServerQuery game is set to " + bold(game) + ".") else: info = self.query_info(ctx) await self.config.guild(ctx.guild).game.set(info.folder) await ctx.send("GameServerQuery used query info and set game to " + bold(game) + ".")
async def _list(self, ctx): """List the current voting channels.""" channels = await self.config.guild(ctx.guild).channels() if channels: await ctx.send( bold("Current channels with VoteChannel:\n") + ", ".join(self.bot.get_channel(c).mention for c in channels)) else: await ctx.send( bold("No channels are being used for VoteChannel yet."))
async def serversregions(self, ctx): """Show total of regions where the bot is.""" regions = { "vip-us-east": ":flag_us:" + _(" __VIP__ US East"), "vip-us-west": ":flag_us:" + _(" __VIP__ US West"), "vip-amsterdam": ":flag_nl:" + _(" __VIP__ Amsterdam"), "eu-west": ":flag_eu:" + _(" EU West"), "eu-central": ":flag_eu:" + _(" EU Central"), "london": ":flag_gb:" + _(" London"), "frankfurt": ":flag_de:" + _(" Frankfurt"), "amsterdam": ":flag_nl:" + _(" Amsterdam"), "us-west": ":flag_us:" + _(" US West"), "us-east": ":flag_us:" + _(" US East"), "us-south": ":flag_us:" + _(" US South"), "us-central": ":flag_us:" + _(" US Central"), "singapore": ":flag_sg:" + _(" Singapore"), "sydney": ":flag_au:" + _(" Sydney"), "brazil": ":flag_br:" + _(" Brazil"), "hongkong": ":flag_hk:" + _(" Hong Kong"), "russia": ":flag_ru:" + _(" Russia"), "japan": ":flag_jp:" + _(" Japan"), "southafrica": ":flag_za:" + _(" South Africa"), "india": ":flag_in:" + _(" India"), } region = {} for guild in self.bot.guilds: if str(guild.region): if str(guild.region) not in region: region[str(guild.region)] = 0 region[str(guild.region)] += 1 divided = [] for k, v in region.items(): divided.append([k, v]) divided = sorted(divided, key=lambda x: x[1], reverse=True) new = {} for entry in divided: new[entry[0]] = entry[1] msg = "" for k, v in new.items(): msg += regions[str(k)] + f": `{v}`\n" guilds = len(self.bot.guilds) try: em = discord.Embed( color=await ctx.embed_colour(), title=_("Servers regions stats:"), description=msg ) em.set_footer(text=_("For a total of {} servers").format(guilds)) await ctx.send(embed=em) except discord.Forbidden: await ctx.send( bold(_("Servers regions stats:\n\n")) + msg + bold(_("\nFor a total of {} servers").format(guilds)) )
async def pay_winners(self, multiplier: float): """Pay the winner(s) of this trivia session. Payout only occurs if there are at least 3 human contestants. If a tie occurs the payout is split evenly among the winners. Parameters ---------- multiplier : float The coefficient of the winning score, used to determine the amount paid. """ if not self.scores: return top_score = self.scores.most_common(1)[0][1] winners = [] num_humans = 0 for (player, score) in self.scores.items(): if not player.bot: if score == top_score: winners.append(player) num_humans += 1 if not winners or num_humans < 3: return payout = int(top_score * multiplier / len(winners)) if payout <= 0: return for winner in winners: LOG.debug("Paying trivia winner: %d credits --> %s", payout, winner.name) try: await bank.deposit_credits(winner, payout) except errors.BalanceTooHigh as e: await bank.set_balance(winner, e.max_balance) if len(winners) > 1: msg = _( "Congratulations {users}! You have each received {num} {currency} for winning!" ).format( users=humanize_list( [bold(winner.display_name) for winner in winners]), num=payout, currency=await bank.get_currency_name(self.ctx.guild), ) else: msg = _( "Congratulations {user}! You have received {num} {currency} for winning!" ).format( user=bold(winners[0].display_name), num=payout, currency=await bank.get_currency_name(self.ctx.guild), ) await self.ctx.send(msg)
async def prefix(self, ctx): """Show all prefixes of the bot""" if hasattr(self.bot, "_config"): # Red > 3.2 default_prefixes = await self.bot._config.prefix() try: guild_prefixes = await self.bot._config.guild(ctx.guild ).prefix() except AttributeError: guild_prefixes = False else: # Red < 3.2 default_prefixes = await self.bot.db.prefix() try: guild_prefixes = await self.bot.db.guild(ctx.guild).prefix() except AttributeError: guild_prefixes = False bot_name = ctx.bot.user.name avatar = self.bot.user.avatar_url_as(static_format="png") if not guild_prefixes: to_send = [f"`\u200b{p}\u200b`" for p in default_prefixes] plural = _("es") if len(default_prefixes) >= 2 else "" try: em = discord.Embed(color=await ctx.embed_colour()) em.add_field( name=_("Prefix{es} of {name}:").format(es=plural, name=bot_name), value=" ".join(to_send), ) em.set_thumbnail(url=avatar) await ctx.send(embed=em) except discord.Forbidden: await ctx.send( bold(_("Prefix{es} of {name}:\n")).format( es=plural, name=bot_name) + " ".join(to_send)) else: to_send = [f"`\u200b{p}\u200b`" for p in guild_prefixes] plural = _("es") if len(guild_prefixes) >= 2 else "" try: em = discord.Embed(color=await ctx.embed_colour()) em.add_field( name=_("Server prefix{es} of {name}:").format( es=plural, name=bot_name), value=" ".join(to_send), ) em.set_thumbnail(url=avatar) await ctx.send(embed=em) except discord.Forbidden: await ctx.send( bold(_("Server prefix{es} of {name}:\n")).format( es=plural, name=bot_name) + " ".join(to_send))
async def _make_embed_others( self, ctx, name, api_category=None): # TODO: Catch exception when API's down. api = subs.NEKOBOT_BASEURL + random.choice(api_category) async with self.session.get(api) as i: data = await i.json(content_type=None) url = data["message"] embed = await self._embed( ctx, color=0x891193, title=(_("Here is {name} image ...") + " \N{EYES}").format(name=name), description=bold( _("[Link if you don't see image]({url})")).format(url=url), image=url, text=_("Requested by {req} {emoji} • From Nekobot API").format( req=ctx.author.display_name, emoji=await self.emoji()), ) async with ctx.typing(): if not ctx.guild or ctx.message.channel.is_nsfw(): embed = embed return await self._maybe_embed( ctx, embed=(await self._nsfw_channel_check(ctx) if (hasattr(ctx.channel, "is_nsfw") and (not (ctx.channel.is_nsfw()))) else embed), )
def _new_match_embed(metadata: InvMetaData, matches: MatchesDict, exact: bool) -> List[discord.Embed]: count = 0 match_type = "exact" if exact else "possible" lines: List[str] = [] for reftype, refspec_list in matches.items(): lines.append(chatutils.bold(reftype)) for refspec in refspec_list: count += 1 # The zero-width space is necessary to make sure discord doesn't remove # leading spaces at the start of an embed. lines.append("\u200b" + (" " * 4) + f"[{refspec.display_name}]({refspec.url})") plural = "es" if count > 1 else "" description = "\n".join(lines) ret: List[discord.Embed] = [] for page in chatutils.pagify(description, page_length=2048): # my little hack to make sure pagify doesn't strip the initial indent if not page.startswith("**"): page = " " * 4 + page ret.append(discord.Embed(description=page)) ret[0].title = f"Found {count} {match_type} match{plural}." ret[-1].set_footer(text=f"{metadata.projname} {metadata.version}") return ret
async def captcha_type_setter(self, ctx: commands.Context, captcha_type: str): """ Change the type of Captcha challenge. You choose the following type of Captcha: - image: A normal captcha image, hardest to understand. - wheezy: A less complex captcha image, easier than image method. - plain: Plain text captcha. Easiest to read, cannot be copy/pasted. """ available = ("wheezy", "image", "plain") captcha_type = captcha_type.lower() if captcha_type not in available: await ctx.send_help() await ctx.send( form.error( form.bold( "{type} is not a valid Captcha type option.".format( type=form.bordered(captcha_type))))) return await self.data.guild(ctx.guild).type.set(captcha_type) await ctx.send( form.info( "Captcha type registered: {type}".format(type=captcha_type)))
async def _make_embed_others_facts( self, ctx: commands.Context, name: str, emoji: str, img_url: str, facts_url: str, fact_arg: str, img_arg: str, source: str, ): """Function to make the embed for all others APIs images.""" data = await self._get_others_imgs(ctx, facts=True, img_url=img_url, facts_url=facts_url) if not data: return em = await self._embed( color=await ctx.embed_colour(), title=(_("Here is {name} ... ") + emoji).format(name=name), description=bold( _("{fact}\n[Link if you don't see image]({url})")).format( fact=data["fact"][fact_arg], url=data["img"][img_arg]), image=data["img"][img_arg], footer=_("Requested by {req} • From {source}").format( req=ctx.author.display_name, source=source), ) return em
async def custom_trivia_list(self, ctx: commands.Context): """List uploaded custom trivia.""" personal_lists = sorted( [p.resolve().stem for p in cog_data_path(self).glob("*.yaml")]) no_lists_uploaded = _("No custom Trivia lists uploaded.") if not personal_lists: if await ctx.embed_requested(): await ctx.send( embed=discord.Embed(colour=await ctx.embed_colour(), description=no_lists_uploaded)) else: await ctx.send(no_lists_uploaded) return if await ctx.embed_requested(): await ctx.send(embed=discord.Embed( title=_("Uploaded trivia lists"), colour=await ctx.embed_colour(), description=", ".join(sorted(personal_lists)), )) else: msg = box( bold(_("Uploaded trivia lists")) + "\n\n" + ", ".join(sorted(personal_lists))) if len(msg) > 1000: await ctx.author.send(msg) else: await ctx.send(msg)
async def dblwidget(self, ctx, *, bot: Union[int, discord.Member, discord.User, None] = None): """Send the widget of a chosen bot on DBL.""" key = await ctx.bot.db.api_tokens.get_raw("dbl", default=None) if key is None: return await ctx.send( _("Owner of this bot need to set an API key first !")) if bot is None: return await ctx.send_help() if isinstance(bot, int): try: bot = await self.bot.fetch_user(bot) except discord.NotFound: return await ctx.send(str(bot) + _(" is not a Discord user.")) if not bot.bot: return await ctx.send( _("This is not a bot user, please try again with a bot.")) async with ctx.typing(): data = await self._get_data(ctx, bot=bot.id) if data is None: return em = discord.Embed( color=discord.Color.blurple(), description=bold(_("[DBL Page]({})")).format( f"https://discordbots.org/bot/{bot.id}"), ) em.set_image( url=f"https://discordbots.org/api/widget/{bot.id}.png") await ctx.send(embed=em)
async def _role(self, ctx, gm_role: str = None): """Set the discord GM role.""" if gm_role is not None: await self.config.guild(ctx.guild).gm_role.set(gm_role) await ctx.send("GameServerQuery GM role is set to " + bold(gm_role) + ".") else: await ctx.send_help()
async def theme_list(self, ctx, *, user: discord.User = None): """ Lists your currently set themes. """ if not user: user = ctx.author themes = await self.maybe_bot_themes(ctx, user) if themes: message = self.pretty_themes( bold(_("{}'s Themes")).format(user.name), themes) else: message = "{}\n\n{}".format( bold(_("{0}'s Themes")), italics(_("{0} has not set any themes."))).format(user.name) for msg in pagify(message): await ctx.maybe_send_embed(msg)
async def _make_embed_other(self, ctx: commands.Context, name: str, url: str, arg: str, source: str): """Function to make the embed for all others APIs images.""" try: data = await asyncio.wait_for(self._get_others_imgs(ctx, url=url), 3) except asyncio.TimeoutError: await ctx.send( "Failed to get an image. Please try again later. (Timeout error)" ) return if not data: return em = await self._embed( color=0x891193, title=(_("Here is {name} image ...") + " \N{EYES}").format(name=name), description=bold( _("[Link if you don't see image]({url})").format( url=data["img"][arg]), escape_formatting=False, ), image=data["img"][arg], footer=_("Requested by {req} {emoji} • From {source}").format( req=ctx.author.display_name, emoji=emoji(), source=source), ) return em
async def _ip(self, ctx, ip: str = None): """Set the ip.""" if ip is not None: await self.config.guild(ctx.guild).ip.set(ip) await ctx.send("GameServerQuery ip is set to " + bold(ip) + ".") else: await ctx.send_help()
async def send_to(self, ctx: Context, content=None): if await ctx.embed_requested(): return await ctx.send(content=content, embed=self) content = str(content) if content is not None else None if content: content = [content, ""] else: content = [] next_break = False title = self._("title") if title: content.append(CF.bold(title)) next_break = True name = self._("author.name") if name: content.append(CF.italics(name)) next_break = True url = self._("thumbnail.url") if url and not url.startswith("attachment://"): content.append(f"<{url}>") next_break = True description = self._("description") if description: content.append(CF.box(CF.escape(description, formatting=True))) next_break = False if next_break: content.append("") next_break = False for i in range(len(self.fields)): inline, name, value = ( self._("fields", i, "inline"), self._("fields", i, "name"), self._("fields", i, "value"), ) if not inline or len(name) + len( value) > 78 or "\n" in name or "\n" in value: content.append(name) content.append(CF.box(CF.escape(value, formatting=True))) next_break = False else: content.append(f"{name}: {value}") next_break = True if next_break: content.append("") next_break = False url = self._("image.url") if url and not url.startswith("attachment://"): content.append(f"<{url}>") url = self._("video.url") if url and not url.startswith("attachment://"): content.append(f"<{url}>") text, timestamp = self._("footer.text"), self._("timestamp") if text and timestamp: content.append(f"{text} | {timestamp}") elif text: content.append(text) elif timestamp: content.append(f"{timestamp} UTC") content = list(CF.pagify("\n".join(map(str, content)), shorten_by=0)) return await ctx.send_interactive(content)
async def run(self): """Run the trivia session. In order for the trivia session to be stopped correctly, this should only be called internally by `TriviaSession.start`. """ await self._send_startup_msg() max_score = self.settings["max_score"] delay = self.settings["delay"] timeout = self.settings["timeout"] for question, answers in self._iter_questions(): async with self.ctx.typing(): await asyncio.sleep(3) self.count += 1 msg = bold(_("Question number {num}!").format( num=self.count)) + "\n\n" + question await self.ctx.send(msg) continue_ = await self.wait_for_answer(answers, delay, timeout) if continue_ is False: break if any(score >= max_score for score in self.scores.values()): await self.end_game() break else: await self.ctx.send(_("There are no more questions!")) await self.end_game()
async def trivia_info(self, ctx: commands.Context, category: str): """Show the description of a trivia category.""" try: dict_ = self.get_trivia_list(category.lower()) except FileNotFoundError: await ctx.send( f"Invalid category `{category.lower()}`. See `{ctx.prefix}trivia list` for" " a list of trivia categories.") except InvalidListError: await ctx.send( f"There was an error parsing the trivia list for `{category.lower()}`." " It may be formatted incorrectly.") else: title = f"{category.lower()}" count = f"({get_trivia_list_size(dict_)} questions" if 'AUTHOR' in dict_: count += f" by {dict_['AUTHOR']})" else: count += ")" desc = dict_.get('DESC', None) if await ctx.embed_requested(): await ctx.send( embed=discord.Embed(title=f"{title} {count}", colour=await ctx.embed_colour(), description=desc)) else: msg = bold(f"{title} {count}") msg += ("\n\n{desc}" if desc else "") await ctx.send(box(msg))
async def rpsls(self, ctx, choice: str): """ Play rock, paper, scizzors, lizard, spock. Use `[p]rpsls help` for a diagram.""" choice = choice.lower() if choice == "help": with open(Path(__file__).parent / "info.json") as fp: return await ctx.send(json.load(fp)["diagram"]) if not choice in choices: return await ctx.send("Please enter a valid choice.") b = self.converter(pick(choices)) h = self.converter(choice) k = {0:[1,3],1:[2,4],2:[3,0],3:[4,1],4:[0,2]} if h == b: title = f"{emojis[h]} vs {emojis[b]}" description = f"It's a draw." color = 0x87ceeb elif b in k[h]: title = f"{emojis[h]} vs {emojis[b]}" description = f"You win!" color = 0x22ce70 else: title = f"{emojis[h]} vs {emojis[b]}" description = f"{ctx.me.name} wins." color = 0xff5151 kwargs = {"title": title,"description": description, "color": color} if await ctx.embed_requested(): await ctx.send(embed=discord.Embed(**kwargs)) else: await ctx.send(bold(title) + '\n' + description)
async def timing(self, ctx, interval_min: int, interval_max: int, bang_timeout: int): """ Change the hunting timing. `interval_min` = Minimum time in seconds for a new bird. (120s min) `interval_max` = Maximum time in seconds for a new bird. (240s min) `bang_timeout` = Time in seconds for users to shoot a bird before it flies away. (10s min) """ message = "" if interval_min > interval_max: return await ctx.send( "`interval_min` needs to be lower than `interval_max`.") if interval_min < 0 and interval_max < 0 and bang_timeout < 0: return await ctx.send("Please no negative numbers!") if interval_min < 120: interval_min = 120 message += "Minimum interval set to minimum of 120s.\n" if interval_max < 240: interval_max = 240 message += "Maximum interval set to minimum of 240s.\n" if bang_timeout < 10: bang_timeout = 10 message += "Bang timeout set to minimum of 10s.\n" await self.config.guild(ctx.guild ).hunt_interval_minimum.set(interval_min) await self.config.guild(ctx.guild ).hunt_interval_maximum.set(interval_max) await self.config.guild(ctx.guild ).wait_for_bang_timeout.set(bang_timeout) message += f"Timing has been set:\nMin time {interval_min}s\nMax time {interval_max}s\nBang timeout {bang_timeout}s" await ctx.send(bold(message))
async def _game_port(self, ctx, game_port: str = None): """Set the game port.""" if game_port is not None: await self.config.guild(ctx.guild).game_port.set(game_port) await ctx.send("GameServerQuery game port is set to " + bold(game_port) + ".") else: await ctx.send_help()
async def dblwidget(self, ctx: commands.Context, *, bot: discord.User): """ Send the widget of a chosen bot on Top.gg. `bot`: Can be a mention or ID of a bot. If not provided will default to the used bot. """ if bot is None: bot = self.bot.user if not bot.bot: return await ctx.send(_("This is not a bot user, please try again with a bot.")) async with ctx.typing(): try: await self.dbl.get_guild_count(bot.id) url = await self.dbl.get_widget_large(bot.id) except dbl.NotFound: return await ctx.send(_("That bot isn't validated on Top.gg.")) except dbl.errors.HTTPException as error: log.error("Failed to fetch Top.gg API.", exc_info=error) return await ctx.send(_("Failed to contact Top.gg API. Please try again later.")) file = await download_widget(self.session, url) em = discord.Embed( color=discord.Color.blurple(), description=bold(_("[Top.gg Page]({})")).format(f"https://top.gg/bot/{bot.id}"), ) if file: filename = f"{bot.id}_topggwidget_{int(time.time())}.png" em.set_image(url=f"attachment://{filename}") return await ctx.send(file=discord.File(file, filename=filename), embed=em) em.set_image(url=url) return await ctx.send(embed=em)
async def _title_choose(list_of_music: list): """Function to return for requesting user's prompt, asking what music to choose. Parameters ---------- list_of_music: list A list containing musics. Returns ------- tuple: A tuple that contain a string with the message to send and a dict with methods available. """ message = ( "Please select the music you wish to get the lyrics by selecting the corresponding " "number (Say `-1` to abort):\n\n" ) method = {} n = 0 for music in list_of_music: # noinspection PyUnresolvedReferences if not isinstance(music, ksoftapi.models.LyricResult): continue # Not a music year = music.album_year[0] message += "`{number}` - {title} by {author}{year}\n".format( number=n, title=music.name, author=music.artist, year=" (" + bold(str(year)) + ")" if year and int(year) > 1970 else "", ) method[str(n)] = music n += 1 return message, method
async def _query_port(self, ctx, query_port: str = None): """Set the query port.""" if query_port is not None: await self.config.guild(ctx.guild).query_port.set(query_port) await ctx.send("GameServerQuery query port is set to " + bold(query_port) + ".") else: await ctx.send_help()