Skip to content

Instantly share code, notes, and snippets.

@Baysul
Created April 22, 2019 23:07
Show Gist options
  • Select an option

  • Save Baysul/e7f23a75724fd776b0c4ec321505f714 to your computer and use it in GitHub Desktop.

Select an option

Save Baysul/e7f23a75724fd776b0c4ec321505f714 to your computer and use it in GitHub Desktop.
Paginator for discord.py
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