Created
April 22, 2019 23:07
-
-
Save Baysul/e7f23a75724fd776b0c4ec321505f714 to your computer and use it in GitHub Desktop.
Paginator for discord.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import collections.abc | |
| import typing | |
| import itertools | |
| import asyncio | |
| import discord | |
| from discord.ext import commands | |
| class Paginator: | |
| def __init__(self, ctx: commands.Context, entries: list, | |
| information: typing.Optional[collections.abc.Iterable] = None, | |
| formatter: typing.Callable = None, | |
| max_per_page: int = 5, reaction_timeout: float = 40.0): | |
| self.index = 0 | |
| self.limit = max_per_page | |
| self.timeout = reaction_timeout | |
| self.pages = self.paginate(entries) | |
| self.count = len(self.pages) | |
| self.formatter = formatter if formatter is not None else self.format | |
| self.title, self.description = information if information else ('Please specify a title.', | |
| 'Please specify a description.') | |
| self.channel: discord.TextChannel = ctx.channel | |
| self.bot: commands.Bot = ctx.bot | |
| self.message: discord.Message = None | |
| self.reactions = { | |
| '⏮': self.front, | |
| '⬅': self.previous, | |
| '➡': self.next, | |
| '⏭': self.end | |
| } | |
| def format(self, elements: collections.abc.Iterable): | |
| return "\n".join((element for element in elements if element is not None)) | |
| def paginate(self, iterable: collections.abc.Iterable): | |
| args = [iter(iterable)] * self.limit | |
| return tuple(itertools.zip_longest(*args)) | |
| async def start(self): | |
| await self.turn() | |
| def check(reaction: discord.Reaction, user): | |
| return str(reaction.emoji) in self.reactions and not user.bot | |
| while True: | |
| try: | |
| reaction, user = await self.bot.wait_for('reaction_add', check=check, timeout=self.timeout) | |
| await self.reactions[str(reaction.emoji)]() | |
| await self.message.remove_reaction(str(reaction.emoji), user) | |
| except asyncio.TimeoutError: | |
| await self.message.clear_reactions() | |
| break | |
| async def turn(self): | |
| content = self.pages[self.index] | |
| formatted = self.formatter(content) | |
| if not isinstance(formatted, discord.Embed): | |
| embed = discord.Embed(title=self.title, description=self.description) | |
| embed.add_field(name=f'Page {self.index + 1} of {self.count}', value=formatted) | |
| else: | |
| embed = formatted | |
| if self.message is not None: | |
| await self.message.clear_reactions() | |
| await self.message.edit(embed=embed) | |
| else: | |
| self.message = await self.channel.send(embed=embed) | |
| if self.index > 0: | |
| await self.message.add_reaction('⏮') | |
| await self.message.add_reaction('⬅') | |
| if self.index < self.count - 1: | |
| await self.message.add_reaction('➡') | |
| if self.index <= self.count - 2: | |
| await self.message.add_reaction('⏭') | |
| async def next(self): | |
| self.index += 1 | |
| await self.turn() | |
| async def previous(self): | |
| self.index -= 1 | |
| await self.turn() | |
| async def front(self): | |
| self.index = 0 | |
| await self.turn() | |
| async def end(self): | |
| self.index = self.count - 1 | |
| await self.turn() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment