async def search(self, ctx: context.CustomContext, *, query: str): """Search for a global or local tag on this server""" db_query = """SELECT tag.name, tag.title FROM tag JOIN tag_lookup l on l.tag_id = tag.id WHERE (tag.global = true OR tag.guild_id = $2) AND (lower(l.alias) % $1 OR lower(l.alias) LIKE '%' || $1 || '%' OR lower(tag.title) LIKE '%' || $1 || '%' OR lower(tag.content) LIKE '%' || $1 || '%') ORDER BY similarity(l.alias, $1) DESC LIMIT 20 """ guild_id = 0 if not ctx.guild else ctx.guild.id icon = self.bot.user.display_avatar.url if not ctx.guild else ctx.guild_icon tags = await self.bot.db.fetch(db_query, query.lower(), guild_id) pretty_names = ( {} ) # Abuse dict as ordered set since you can't use DISTINCT in above SQL query for record in tags: pretty_names[ f"`{config.BOT_PREFIX}{record['name']}` {record['title']}" ] = None pages = paginator.SimplePages( entries=list(pretty_names), author=f"Tags matching '{query}'", icon=icon, empty_message="Nothing found.", per_page=12, ) await pages.start(ctx)
async def _list_webhooks( self, ctx, *, endpoint: str, webhook_name: str, command_name: str, icon: str, fmt: typing.Callable, ): webhooks = await self.bot.api_request("GET", f"{endpoint}{ctx.guild.id}") entries = [] for webhook in webhooks["webhooks"]: try: discord_webhook = await self.bot.fetch_webhook( webhook["webhook_id"]) except discord.HTTPException: continue entries.append(fmt(webhook, discord_webhook)) pages = paginator.SimplePages( author=f"{webhook_name.title()} on {ctx.guild.name}", icon=icon, entries=entries, per_page=12, empty_message= f"This server does not have any {webhook_name} yet.\n\nAdd some " f"with `{config.BOT_PREFIX}server {command_name} add`.", ) await pages.start(ctx)
async def banana(self, ctx): """List all bank accounts with the Banana Coin currency""" response = await self.request(BankRoute("GET", "accounts/currency/BNC")) json = await response.json() desc = [] accounts_by_person = collections.defaultdict(list) for account in json: fmt = ( f"{account['iban']}: " f"`{self.get_currency(account['balance_currency']).with_amount(account['balance'])}`" ) accounts_by_person[account["pretty_holder"]].append(fmt) for person, accounts in accounts_by_person.items(): person = discord.utils.remove_markdown(person) fmt = "\n".join(accounts) desc.append(f"**__{person}__**\n{fmt}\n") pages = paginator.SimplePages( entries=desc, icon=self.bot.mk.NATION_ICON_URL or self.bot.dciv.icon.url, author=f"All Bank Accounts with Banana Coin ({len(json)})", ) await pages.start(ctx)
async def _paginate_all_(self, ctx, *, model): per_page = None if model is models.Bill: all_objects = await self.bot.db.fetch("SELECT id FROM bill ORDER BY id;") elif model is models.Law: all_objects = await self.bot.db.fetch( "SELECT id FROM bill WHERE status = $1 ORDER BY id;", models.BillIsLaw.flag.value, ) elif model is models.Motion: per_page = 12 all_objects = await self.bot.db.fetch("SELECT id FROM motion ORDER BY id;") formatted = [] for record in all_objects: obj = await model.convert(ctx, record["id"]) formatted.append(obj.formatted) if model is models.Law: title = f"All Laws in {self.bot.mk.NATION_NAME}" empty_message = f"There are no laws yet." else: title = f"All Submitted {model.__name__}s" empty_message = f"No one has submitted any {model.__name__.lower()}s yet." pages = paginator.SimplePages( entries=formatted, icon=self.bot.mk.NATION_ICON_URL, author=title, empty_message=empty_message, per_page=per_page, ) await pages.start(ctx)
async def list_npcs( self, ctx: CustomContext, *, person: Fuzzy[ converter.CaseInsensitiveMember, converter.CaseInsensitiveUser, FuzzySettings(weights=(5, 1)), ] = None, ): """List every NPC you or someone else has access to **Example** `{PREFIX}{COMMAND}` list all of your NPCs `{PREFIX}{COMMAND} @DerJonas` to see what NPCs someone else has access to `{PREFIX}{COMMAND} DerJonas#8036` `{PREFIX}{COMMAND} Jonas`""" member = person or ctx.author npcs = [self._npc_cache[i] for i in self._npc_access_cache[member.id]] npcs.sort(key=lambda npc: npc["id"]) pretty_npcs = [] for record in npcs: avatar = ( f"[Avatar]({record['avatar_url']})\n" if record["avatar_url"] else "" ) owner = self.bot.get_user(record["owner_id"]) owner_value = ( "\n" if not owner else f"Owner: {owner.mention} {escape_markdown(str(owner))}\n" ) pretty_npcs.append( f"**__NPC #{record['id']} - {escape_markdown(record['name'])}__**" ) pretty_npcs.append( f"{avatar}Trigger Phrase: `{escape_markdown(record['trigger_phrase'])}`" ) pretty_npcs.append(owner_value) if pretty_npcs: pretty_npcs.insert( 0, f"You can create a new NPC with `{config.BOT_PREFIX}npc create`, " f"or edit the name, avatar and/or trigger phrase of an existing one with " f"`{config.BOT_PREFIX}npc edit <npc>`.\n", ) pages = paginator.SimplePages( author=f"{member.display_name}'s NPCs", icon=member.display_avatar.url, entries=pretty_npcs, per_page=20, empty_message="This person hasn't made any NPCs yet.", ) await pages.start(ctx)
async def _from( self, ctx: context.CustomContext, *, person: Fuzzy[ CaseInsensitiveMember, CaseInsensitiveUser, FuzzySettings(weights=(5, 1)) ] = None, ): """List the tags that someone made on this server""" member = person or ctx.author all_tags = await self.bot.db.fetch( "SELECT * FROM tag WHERE author = $1 AND guild_id = $2 ORDER BY uses desc", member.id, ctx.guild.id, ) pretty_tags = [] for record in all_tags: pretty_tags.append( f"`{config.BOT_PREFIX}{record['name']}` {escape_markdown(record['title'])}" ) pages = paginator.SimplePages( entries=pretty_tags, author=f"Tags from {member.display_name}", icon=member.display_avatar.url, empty_message=f"{member} hasn't made any tags on this server yet.", per_page=12, ) await pages.start(ctx)
async def _from_person_model(self, ctx, *, member_or_party, model, paginate=True): member = member_or_party or ctx.author submit_term = "written" if model is models.Law else "submitted" per_page = None if isinstance(member, converter.PoliticalParty): name = member.role.name members = [m.id for m in member.role.members] empty = ( f"No member of {name} has {submit_term} a {model.__name__.lower()} yet." ) title = f"{model.__name__}s from members of {name}" icon = await member.get_logo() or self.bot.mk.NATION_ICON_URL or EmptyEmbed else: name = member.display_name members = [member.id] empty = f"{name} hasn't {submit_term} any {model.__name__.lower()}s yet." title = f"{model.__name__}s from {name}" icon = member.display_avatar.url if model is models.Bill: objs_from_thing = await self.bot.db.fetch( "SELECT id FROM bill WHERE submitter = ANY($1::bigint[]) ORDER BY id;", members, ) elif model is models.Law: objs_from_thing = await self.bot.db.fetch( "SELECT id FROM bill WHERE submitter = ANY($1::bigint[]) AND status = $2 ORDER BY id;", members, models.BillIsLaw.flag.value, ) else: objs_from_thing = await self.bot.db.fetch( "SELECT id FROM motion WHERE submitter = ANY($1::bigint[]) ORDER BY id;", members, ) per_page = 12 formatted = [] for record in objs_from_thing: obj = await model.convert(ctx, record["id"]) formatted.append(obj.formatted) if not paginate: return formatted pages = paginator.SimplePages( entries=formatted, author=title, icon=icon, per_page=per_page, empty_message=empty, ) await pages.start(ctx)
async def search(self, ctx, *, query: str): """Search for laws""" results = await self._search_model(ctx, model=models.Law, query=query) pages = paginator.SimplePages( entries=results, icon=self.bot.mk.NATION_ICON_URL, author=f"Laws matching '{query}'", empty_message="Nothing found.", ) await pages.start(ctx)
async def lyrics(self, ctx, *, query: str): """Find lyrics for a song **Usage** `{PREFIX}{COMMAND} <query>` to search for lyrics that match your query """ if len(query) < 3: return await ctx.send( f"{config.NO} The query to search for has to be more than 3 characters!" ) async with ctx.typing(): async with self.bot.session.get( f"https://some-random-api.ml/lyrics?title={query}" ) as response: if response.status == 200: lyrics = await response.json() else: return await ctx.send( f"{config.NO} Genius could not suggest me anything related to `{query}`." ) try: lyrics["lyrics"] = lyrics["lyrics"].replace("[", "**[").replace( "]", "]**") if len(lyrics["lyrics"]) <= 2048: embed = text.SafeEmbed( title=lyrics["title"], description=lyrics["lyrics"], colour=0x2F3136, url=lyrics["links"]["genius"], ) embed.set_author(name=lyrics["author"]) embed.set_thumbnail(url=lyrics["thumbnail"]["genius"]) return await ctx.send(embed=embed) pages = paginator.SimplePages( entries=lyrics["lyrics"].splitlines(), title=lyrics["title"], title_url=lyrics["links"]["genius"], author=lyrics["author"], thumbnail=lyrics["thumbnail"]["genius"], colour=0x2F3136, ) except KeyError: return await ctx.send( f"{config.NO} Genius could not suggest me anything related to `{query}`." ) await pages.start(ctx)
async def automatic(self, ctx: CustomContext): """Automatically write as an NPC in a specific channel or channel category without having to use its trigger phrase""" automatic_channel = await self.bot.db.fetch( "SELECT npc_automatic_mode.npc_id, npc_automatic_mode.channel_id FROM npc_automatic_mode " "WHERE npc_automatic_mode.user_id = $1 " "AND npc_automatic_mode.guild_id = $2", ctx.author.id, ctx.guild.id, ) grouped_by_npc = collections.defaultdict(list) pretty = [ f"If you want to automatically speak as an NPC in a certain channel or channel category " f"without having to use the trigger phrase, use `{config.BOT_PREFIX}npc automatic " f"on <npc>`, or disable it with " f"`{config.BOT_PREFIX}npc automatic off <npc>`.\n\nYou can only have one " f"automatic NPC per channel.\n\nIf you have one NPC as automatic in an entire category, " f"but a different NPC in a single channel that is that same category, and you write " f"something in that channel, you will only speak as the NPC for that " f"specific channel, and not as both NPCs.\n\n" ] for record in automatic_channel: grouped_by_npc[record["npc_id"]].append( ctx.guild.get_channel(record["channel_id"]) ) for k, v in grouped_by_npc.items(): npc = self._npc_cache[k] pretty_chan = [ f"- {c.mention if type(c) is discord.TextChannel else f'{c.name} Category'}" for c in v ] pretty_chan = "\n".join(pretty_chan) pretty.append(f"**__{npc['name']}__**\n{pretty_chan}\n") if len(pretty) > 1: pages = paginator.SimplePages( entries=pretty, icon=ctx.guild_icon, per_page=15, author=f"{ctx.author.display_name}'s Automatic NPCs", ) await pages.start(ctx) else: embed = text.SafeEmbed(description=pretty[0]) embed.set_author( name=f"{ctx.author.display_name}'s Automatic NPCs", icon_url=ctx.guild_icon, ) await ctx.send(embed=embed)
async def match(self, ctx, *, query): """Extract information from bills, laws & motions with Natural Language Processing:tm: This is an experimental command and probably still a work-in-progress.""" if self.bot.mk.IS_MULTICIV: return await ctx.send( f"{config.NO} This command is disabled during Multiciv MKs.") async with ctx.typing(): response = await self.bot.api_request("POST", "ml/information_extraction", json={"question": query}) if not response: return await ctx.send( f"{config.NO} I couldn't find anything that matches `{query}`. Sorry!" ) fmt = [ "This uses Natural Language Processing to topic match your query against all existing bills & motions " "and shows the most closely corresponding excerpts. Using full, grammatical expressions with " f"no spelling errors will improve the quality of your results.\n\nShould this feature come out of " f"beta, then it will probably be integrated into the `{config.BOT_PREFIX}laws search` and " f"`{config.BOT_PREFIX}legislature bills search` commands.\n\n" ] for result in response: thing, thing_id = result["document_label"].split("_") if thing == "bill": obj = await models.Bill.convert(ctx, thing_id) elif thing == "motion": obj = await models.Motion.convert(ctx, thing_id) else: continue txt = discord.utils.escape_markdown(result["text"]) fmt.append(f"**__{obj.formatted}__**") fmt.append(f"```{txt}```\n") pages = paginator.SimplePages( entries=fmt, icon=self.bot.mk.NATION_ICON_URL, author=f"[BETA] Results for '{query}'", ) await pages.start(ctx)
async def _show_bill_text(self, ctx, bill: models.Bill, *, ephemeral_webhook=None): entries = bill.content.splitlines() entries.insert( 0, f"[Link to the Google Docs document of this Bill]({bill.link})\n" f"*Am I showing you outdated or wrong text? Tell the {self.bot.mk.speaker_term} to " f"synchronize this text with the Google Docs text of this bill with " f"`{config.BOT_PREFIX}{self.bot.mk.LEGISLATURE_COMMAND} bill synchronize {bill.id}`.*\n\n", ) pages = paginator.SimplePages( entries=entries, icon=self.bot.mk.NATION_ICON_URL, author=f"{bill.name} (#{bill.id})", ephemeral_webhook=ephemeral_webhook, ) await pages.start(ctx)
async def nationroles(self, ctx): """List all nation-specific roles that can be given out with `{PREFIX}nation roles toggle`""" predicate = lambda r: r.name.lower().startswith( self.bot.mk.NATION_ROLE_PREFIX.lower()) found = filter(predicate, ctx.guild.roles) fmt = [r.mention for r in found] fmt.insert( 0, f"These roles can be given out with `{config.BOT_PREFIX}nation roles toggle` by you.\n", ) pages = paginator.SimplePages( entries=fmt, author=f"Nation Roles", icon=self.bot.mk.safe_flag, empty_message="There are no roles that you can give out.", per_page=12, ) await pages.start(ctx)
async def local(self, ctx: context.CustomContext): """List all non-global tags on this server""" all_tags = await self.bot.db.fetch( "SELECT * FROM tag WHERE guild_id = $1 AND global = false " "ORDER BY uses desc", ctx.guild.id, ) pretty_tags = [] for record in all_tags: pretty_tags.append( f"`{config.BOT_PREFIX}{record['name']}` {escape_markdown(record['title'])}" ) pages = paginator.SimplePages( entries=pretty_tags, author=f"Local Tags in {ctx.guild.name}", icon=ctx.guild_icon, empty_message="There are no local tags on this server.", per_page=12, ) await pages.start(ctx)
async def exclude( self, ctx, *, channel: Fuzzy[converter.CaseInsensitiveTextChannel, converter.CaseInsensitiveCategoryChannel, ] = None, ): """Hide a channel or category from your server's log channel Both text channels and entire categories can be hidden. Threads inherit whether they are hidden from the channel they belong to. **Usage** `{PREFIX}{COMMAND}` to see all hidden channels/categories `{PREFIX}{COMMAND} <channel>` to hide or unhide a channel or category """ channel: typing.Union[discord.TextChannel, discord.CategoryChannel] settings = await self.ensure_guild_settings(ctx.guild.id) current_logging_channel = await self.bot.get_logging_channel(ctx.guild) if current_logging_channel is None: return await ctx.send( f"{config.NO} This server currently has no logging channel. " f"Please set one with `{config.BOT_PREFIX}server logs`.") help_description = ( f"When you hide a channel, it (and all its threads) will no longer show up in {current_logging_channel.mention}.\n\nAdditionally," f" :star: reactions for the starboard will no longer count in that channel (and in all its threads).\n\nYou can hide a channel, " f"or even an entire category at once, with " f"`{config.BOT_PREFIX}server hidechannel <channel_name>`\n\n__**Hidden Channels**__" ) private_channels = settings["private_channels"] if not channel: current_excluded_channels_by_name = [help_description] if not private_channels: return await ctx.send( f"{config.NO} There are no hidden channels on this server yet. " f"You can hide a channel so that it no longer shows up in " f"{current_logging_channel.mention} with " f"`{config.BOT_PREFIX}server hidechannel <channel_name>`." f"\n{config.HINT} You can also hide entire categories! Just hide the category " f"and every channel in that category will be hidden automatically. " f"Note that if channel is hidden, :star: reactions for the starboard will no " f"longer count in it.") for channel_id in private_channels: channel = self.bot.get_channel(channel_id) if channel: current_excluded_channels_by_name.append(channel.mention) pages = paginator.SimplePages( entries=current_excluded_channels_by_name, author=f"Hidden Channels on {ctx.guild.name}", icon=ctx.guild_icon, empty_message="There are no hidden channels on this server.", ) return await pages.start(ctx) else: is_category = isinstance(channel, discord.CategoryChannel) # Remove channel if channel.id in private_channels: await self.bot.db.execute( "DELETE FROM guild_private_channel WHERE guild_id = $1 AND channel_id = $2", ctx.guild.id, channel.id, ) await self.bot.update_guild_config_cache() if is_category: star = ( f"\n{config.HINT} *Note that :star: reactions for the starboard will now count again in every one of these channels and their threads.*" if ctx.guild.id == self.bot.dciv.id and config.STARBOARD_ENABLED else "") await ctx.send( f"{config.YES} The {channel} category **is no longer hidden**, and all channels in it and their threads " f"will show up in {current_logging_channel.mention} again.{star}" ) else: star = ( f"\n{config.HINT} *Note that :star: reactions for the starboard will now count again in this channel and in all its threads.*" if ctx.guild.id == self.bot.dciv.id and config.STARBOARD_ENABLED else "") await ctx.send( f"{config.YES} {channel.mention} **is no longer hidden**, " f"and it and all its threads will show up in {current_logging_channel.mention} again.{star}" ) # Add channel elif channel.id not in private_channels: await self.bot.db.execute( "INSERT INTO guild_private_channel (guild_id, channel_id) VALUES ($1, $2)", ctx.guild.id, channel.id, ) if is_category: star = ( f"\n{config.HINT} *Note that :star: reactions for the starboard will also no longer count in any of these channels and their threads.*" if ctx.guild.id == self.bot.dciv.id and config.STARBOARD_ENABLED else "") await ctx.send( f"{config.YES} The {channel} category **is now hidden**, and all the channels in it and their threads " f"will no longer show up in {current_logging_channel.mention}.{star}" ) else: star = ( f"\n{config.HINT} *Note that :star: reactions for the starboard will also no longer count in this channel and its threads.*" if ctx.guild.id == self.bot.dciv.id and config.STARBOARD_ENABLED else "") await ctx.send( f"{config.YES} {channel.mention} (and all its threads) **are now hidden** and will no longer show up " f"in {current_logging_channel.mention}.{star}") await self.bot.update_guild_config_cache()
async def accounts(self, ctx): """See the balance of every bank account you have access to""" await self.is_connected_with_bank_user(ctx) if ctx.guild: embed = text.SafeEmbed( title=f"{config.HINT} Privacy Prompt", description="Are you sure that you want to proceed?\n\n" "Everyone in this channel would be able to see the balance of all bank accounts " "you have access to.\n\n*Using this command in DMs with me does not " "trigger this question.*", ) privacy_q = await ctx.send(embed=embed) reaction = await ctx.confirm(message=privacy_q) await privacy_q.delete() if not reaction: return response = await self.request( BankRoute("GET", f"accounts/{ctx.author.id}/")) if response.status != 200: raise BankError( f"{config.NO} {self.bot.owner.mention}, something went wrong!") json = await response.json() desc = ["\n"] total_per_currency = {} for account in json: if ctx.guild: name = "__*Bank Account Name Censored - Use command in DMs to reveal*__" else: if not account["corporate_holder"]: name = f"__**{account['name']}**__" else: name = f"__**{account['corporate_holder']['name']}: {account['name']}**__" amount = self.get_currency( account["balance_currency"]).with_amount(account["balance"]) desc.append(f"{name}\n*{account['iban']}*\n```diff\n+ {amount}```") if not account["is_reserve"]: try: total_per_currency[ account["pretty_balance_currency"]] += decimal.Decimal( account["balance"]) except KeyError: total_per_currency[ account["pretty_balance_currency"]] = decimal.Decimal( account["balance"]) prepend_desc = [ "**Total Balance per Currency**\n*Reserve accounts aren't counted*" ] for cur, amount in total_per_currency.items(): prepend_desc.append(f"{cur}: {amount}") desc.append("\n".join(prepend_desc)) pages = paginator.SimplePages( entries=desc, author=f"{ctx.author.display_name}'s Bank Accounts", icon=ctx.author_icon, per_page=12, ) await pages.start(ctx)
async def ask(self, ctx, batch_size: typing.Optional[int] = 1, *, question): """Get answers to a legal question with Deep (Machine) Learning:tm: and Neural Networks:tm: This is an experimental command and probably still a work-in-progress.""" if self.bot.mk.IS_MULTICIV: return await ctx.send( f"{config.NO} This command is disabled during Multiciv MKs.") wait = await ctx.send( f"{config.HINT} This might take 30 to 60 seconds. Should this feature make it out " f"of beta, the time it takes will *hopefully* be sped up to just a couple of seconds by " f"switching to more powerful server hardware.\n:arrows_counterclockwise: Thinking " f"really hard about your question...") async with ctx.typing(): start = time.time() response = await self.bot.api_request( "POST", "ml/question_answering", json={ "question": question, "batch_size": batch_size }, ) end = time.time() duration = end - start await wait.delete() if not response: return await ctx.send( f"{config.NO} I couldn't find an answer to that question. Sorry!" ) fmt = [ "This uses deep learning, a particular machine learning method, with neural networks to try to " "find answers to a legal question you're asking. All currently existing bills & motions are taken into " "account to try to find the best answer. Google's BERT model in combination with Tensorflow Keras " "are used here.\n\nThis comes with no guarantees about the correctness of the answers. Do not expect " "this to be free of wrong, misleading or irrelevant answers.\n\n" ] for result in response: if result["score"] * 100 <= 1: continue if len(result["full_answer"]) - len(result["answer"]) <= 3: cntxt = [] else: cntxt = [ f"__Context__", f"```{discord.utils.escape_markdown(result['full_answer'])}```", ] thing, thing_id = result["document"].split("_") if thing == "bill": obj = await models.Bill.convert(ctx, thing_id) elif thing == "motion": obj = await models.Motion.convert(ctx, thing_id) else: continue fmt.append( f"**__Found answer in {obj.formatted} with a confidence of {result['score'] * 100:.2f}%__**" ) fmt.append( f"```{discord.utils.escape_markdown(result['answer'])}```") fmt.extend(cntxt) pages = paginator.SimplePages( entries=fmt, author=f"[BETA] Results for '{question}'", icon=self.bot.mk.NATION_ICON_URL, reply=True, ) await ctx.reply( f"{config.HINT} Keep in mind that this feature is still a work-in-progress in Beta. " f"Question answering took ~{duration:.2f} seconds with a batch size of {batch_size}." ) await pages.start(ctx)
async def tags(self, ctx: context.CustomContext, *, tag: Fuzzy[Tag] = None): """Access a tag or list all tags on this server **Example** `{PREFIX}{COMMAND}` to get a list of all tags on this server `{PREFIX}{COMMAND} constitution` to see the {PREFIX}constitution tag""" if tag: tag_content_type = self.get_tag_content_type(tag.content) if tag.is_embedded: if tag_content_type is TagContentType.IMAGE: # invisible colour=0x2F3136 embed = text.SafeEmbed(title=tag.title) embed.set_image(url=tag.content) try: return await ctx.send(embed=embed) except discord.HTTPException: return await ctx.send(tag.clean_content) elif tag_content_type is TagContentType.VIDEO: # discord doesn't allow videos in embeds return await ctx.send(tag.clean_content) embed = text.SafeEmbed(title=tag.title, description=tag.content) return await ctx.send(embed=embed) else: return await ctx.send(tag.clean_content) global_tags = await self.bot.db.fetch( "SELECT * FROM tag WHERE global = true ORDER BY uses desc" ) pretty_tags = [] if global_tags: pretty_tags = [ f"**__Global Tags__**\n*Tags can only be made global by {self.bot.dciv.name} " f"Moderation and Nation Admins. Global tags work in every server I am in, as well as in DMs with me.*\n" ] for record in global_tags: pretty_tags.append( f"`{config.BOT_PREFIX}{record['name']}` {escape_markdown(record['title'])}" ) if ctx.guild: all_tags = await self.bot.db.fetch( "SELECT * FROM tag WHERE guild_id = $1 AND global = false" " ORDER BY uses desc", ctx.guild.id, ) if all_tags: pretty_tags.append( f"\n\n**__Local Tags__**\n*Every Tag that was not explicitly made global by " f"{self.bot.dciv.name} Moderation or a Nation Admin is a local tag, " f"and only works in the server it was made in.*\n" ) for record in all_tags: pretty_tags.append( f"`{config.BOT_PREFIX}{record['name']}` {escape_markdown(record['title'])}" ) author = f"All Tags in {ctx.guild.name}" icon = ctx.guild_icon empty_message = "There are no tags on this server." else: author = "All Global Tags" icon = self.bot.user.display_avatar.url empty_message = "There are no global tags yet." if len(pretty_tags) < 2: pretty_tags = [] pages = paginator.SimplePages( entries=pretty_tags, author=author, icon=icon, empty_message=empty_message, per_page=12, ) await pages.start(ctx)