""" Credits to Rapptz/RoboDanny https://github.com/Rapptz/RoboDanny/blob/0dfa21599da76e84c2f8e7fde0c132ec93c840a8/cogs/utils/paginator.py """ import asyncio import discord from discord.ext.commands import Paginator as CommandPaginator from discord.ext import menus class RoboPages(menus.MenuPages): def __init__(self, source): super().__init__(source=source, check_embeds=True) self.input_lock = asyncio.Lock() async def finalize(self, timed_out): try: if timed_out: await self.message.clear_reactions() else: await self.message.delete() except discord.HTTPException: pass @menus.button("\N{INFORMATION SOURCE}\ufe0f", position=menus.Last(3)) async def show_help(self): """shows this message""" embed = discord.Embed( title="Paginator help", description="Hello! Welcome to the help page.", ) messages = [] for (emoji, button) in self.buttons.items(): messages.append(f"{emoji}: {button.action.__doc__}") embed.add_field( name="What are these reactions for?", value="\n".join(messages), inline=False, ) embed.set_footer( text=f"We were on page {self.current_page + 1} before this message." ) await self.message.edit(content=None, embed=embed) async def go_back_to_current_page(): await asyncio.sleep(30.0) await self.show_page(self.current_page) self.bot.loop.create_task(go_back_to_current_page()) @menus.button( "\N{INPUT SYMBOL FOR NUMBERS}", position=menus.Last(1.5), lock=False ) async def numbered_page(self, payload): """lets you type a page number to go to""" if self.input_lock.locked(): return async with self.input_lock: channel = self.message.channel author_id = payload.user_id to_delete = [] to_delete.append( await channel.send("What page do you want to go to?") ) def message_check(m): return ( m.author.id == author_id and channel == m.channel and m.content.isdigit() ) try: msg = await self.bot.wait_for( "message", check=message_check, timeout=30.0 ) except asyncio.TimeoutError: to_delete.append(await channel.send("Took too long.")) await asyncio.sleep(5) else: page = int(msg.content) to_delete.append(msg) await self.show_checked_page(page - 1) try: await channel.delete_messages(to_delete) except Exception: pass class FieldPageSource(menus.ListPageSource): """A page source that requires (field_name, field_value) tuple items.""" def __init__(self, entries, *, per_page=12): super().__init__(entries, per_page=per_page) self.embed = discord.Embed(colour=discord.Colour.blurple()) # pylint: disable=arguments-differ async def format_page(self, menu, entries): self.embed.clear_fields() self.embed.description = discord.Embed.Empty for key, value in entries: self.embed.add_field(name=key, value=value, inline=False) maximum = self.get_max_pages() if maximum > 1: text = f"Page {menu.current_page + 1}/{maximum} ({len(self.entries)} entries)" self.embed.set_footer(text=text) return self.embed class TextPageSource(menus.ListPageSource): def __init__(self, text, *, prefix="```", suffix="```", max_size=2000): pages = CommandPaginator( prefix=prefix, suffix=suffix, max_size=max_size - 200 ) for line in text.split("\n"): pages.add_line(line) super().__init__(entries=pages.pages, per_page=1) # pylint: disable=arguments-differ async def format_page(self, menu, content): maximum = self.get_max_pages() if maximum > 1: return f"{content}\nPage {menu.current_page + 1}/{maximum}" return content class SimplePageSource(menus.ListPageSource): def __init__(self, entries, *, per_page=12): super().__init__(entries, per_page=per_page) self.initial_page = True # pylint: disable=arguments-differ async def format_page(self, menu, entries): pages = [] for index, entry in enumerate( entries, start=menu.current_page * self.per_page ): pages.append(f"{index + 1}. {entry}") maximum = self.get_max_pages() if maximum > 1: footer = f"Page {menu.current_page + 1}/{maximum} ({len(self.entries)} entries)" menu.embed.set_footer(text=footer) if self.initial_page and self.is_paginating(): pages.append("") pages.append( "Confused? React with \N{INFORMATION SOURCE} for more info." ) self.initial_page = False menu.embed.description = "\n".join(pages) return menu.embed class SimplePages(RoboPages): """A simple pagination session reminiscent of the old Pages interface. Basically an embed with some normal formatting. """ def __init__(self, entries, *, per_page=12): super().__init__(SimplePageSource(entries, per_page=per_page)) self.embed = discord.Embed(colour=discord.Colour.blurple())