Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full V13 support: Interactions (buttons and select menus) and reactions! #17

Open
wants to merge 41 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
959f7b6
Replace unary operators
psibean Jan 17, 2021
cc73965
Add custom footer and page resolvers, shift all optional and default …
psibean Jan 18, 2021
0e71be1
Ignore vscode
psibean Jan 18, 2021
12a3845
Remove the now redundant emojiList length check
psibean Jan 18, 2021
1c6ce1a
Expose user on the collect event, await the reaction removal.
psibean Jan 18, 2021
914781d
Remove unnecessary footerResolver param comment line
psibean Jan 18, 2021
57d0605
Prevent crash if message is deleted before reactions are applied.
psibean Jan 18, 2021
92b9cc8
Always filter against bots, always ensure emoji is in list, apply cus…
psibean Jan 18, 2021
e9308fd
Shift collection reactor setup prior to the bot adding reactions.
psibean Jan 18, 2021
94018c4
Expose the message to the pageResolver
psibean Jan 18, 2021
9f65ab3
Mark resolvers optional in typings
psibean Jan 18, 2021
1008e1d
Pass in the correct message to the pageResolver
psibean Jan 18, 2021
25ccae7
Fix emoji list typing
psibean Jan 18, 2021
a076510
Additional page message delete guard
psibean Jan 18, 2021
9350fca
Typing syntax ',' to ';', add sendMessage property of PaginationOptions.
psibean Jan 19, 2021
d03d148
Remove uinnecessary deleted check and try/catch, add defaultCollector…
psibean Jan 19, 2021
c9947e3
Add missing async, fix paghe > page typo
psibean Jan 19, 2021
aa984dc
Rename page > currentPageIndex
psibean Jan 20, 2021
770615c
Rename curPage > paginatedEmbedMessage
psibean Jan 20, 2021
0515379
Remove useUtils from PaginationOptions, type parameter name clarifica…
psibean Jan 20, 2021
06bfba1
Add collectErrorHandler
psibean Jan 20, 2021
db34587
Update example usage
psibean Jan 20, 2021
637147b
Remove redundant useUtil
psibean Jan 20, 2021
c5fcf45
Remove unnecessary explicit async/await.
psibean Jan 20, 2021
d347174
Re-add MessageEmbed require to example
psibean Jan 20, 2021
62a7c1b
Fix indentation
psibean Jan 20, 2021
4a221d9
Fix indentation
psibean Jan 20, 2021
a0087cc
amend merge
psibean Jan 20, 2021
1646e3a
Update index.js
psibean Jan 20, 2021
5b56e3a
Fix example usage syntax error
psibean Jan 20, 2021
8b71d00
Merge branch 'master' of https://github.com/psibean/discord.js-pagina…
psibean Jan 20, 2021
8091a75
Add deleted guard on end (in case ended by other means)
psibean Jan 22, 2021
9ee632a
Destructure params - optional, delegate end handler, expose messages …
psibean Feb 25, 2021
9d17bd3
Update error handler example
psibean Feb 25, 2021
44a4b0c
Fix collector filter typing, adjust consistent syntax
psibean Feb 25, 2021
1641156
Update with initial discordjs v13 support
psibean Aug 7, 2021
ab92780
Update index typings
psibean Aug 7, 2021
1f9349a
Update readme installation and version support information
psibean Aug 7, 2021
cbaf404
Bump major
psibean Aug 7, 2021
97fcb6d
Fix async/await defaults, fix collectorFilter destruct params
psibean Aug 7, 2021
4f774fe
Add missing filter return, add interaction typing
psibean Aug 8, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,6 @@ typings/

# next.js build output
.next

# vscode
.vscode/
14 changes: 14 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { EmojiIdentifierResolvable, Message, MessageEmbed, MessageReaction, ReactionCollectorOptions, User } from "discord.js";

interface PaginationOptions extends ReactionCollectorOptions {
deleteOnEnd?: boolean,
useUtil?: boolean,
emojiList?: EmojiIdentifierResolvable[],
collectorFilter?(reaction: MessageReaction, user: User): boolean | Promise<boolean>
psibean marked this conversation as resolved.
Show resolved Hide resolved
footerResolver?(pageIndex: number, pagesLength: number): string,
pageResolver?(msg: Message, pages: MessageEmbed[], emojiList: string[], currentPageIndex: number, reaction: MessageReaction): number | Promise<number>
psibean marked this conversation as resolved.
Show resolved Hide resolved
}

declare function paginationEmbed (msg: Message, pages: MessageEmbed[], paginationOptions?: PaginationOptions): Promise<Message>
psibean marked this conversation as resolved.
Show resolved Hide resolved

export = paginationEmbed;
90 changes: 69 additions & 21 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,81 @@
const paginationEmbed = async (msg, pages, emojiList = ['⏪', '⏩'], timeout = 120000) => {
/**
*
* @param {MessageEmbed[]} pages
* @param {EmojiIdentifierResolvable[]} emojiList
* @param {number} currentPageIndex
* @param {MessageReaction} reaction
* @returns {number} - the new page index.
*/
const defaultPageResolver = async (_, pages, emojiList, currentPageIndex, reaction) => {
let newPage = currentPageIndex;
switch (reaction.emoji.name) {
case emojiList[0]:
newPage = currentPageIndex > 0 ? currentPageIndex - 1 : pages.length - 1;
break;
case emojiList[1]:
newPage = currentPageIndex + 1 < pages.length ? currentPageIndex + 1 : 0;
break;
default:
return currentPageIndex;
}
return newPage;
};

const defaultFooterResolver = (currentPageIndex, pagesLength) =>`Page ${currentPageIndex + 1} / ${pagesLength}`;
psibean marked this conversation as resolved.
Show resolved Hide resolved

/**
*
* @param {Message} msg - the message
* @param {MessageEmbed[]} pages - array of message embeds to use as each page.
* @param {PaginationOptions} paginationOptions - exposes collector options, provides customization.
*/
const paginationEmbed = async (
msg, pages,
psibean marked this conversation as resolved.
Show resolved Hide resolved
{
deleteOnEnd = false, useUtil = false,
emojiList = ['⏪', '⏩'],
collectorFilter = null,
footerResolver = defaultFooterResolver,
pageResolver = defaultPageResolver,
timeout = 120000,
...rest
} = {}) => {
if (!msg && !msg.channel) throw new Error('Channel is inaccessible.');
if (!pages) throw new Error('Pages are not given.');
if (emojiList.length !== 2) throw new Error('Need two emojis.');
let page = 0;
const curPage = await msg.channel.send(pages[page].setFooter(`Page ${page + 1} / ${pages.length}`));
for (const emoji of emojiList) await curPage.react(emoji);
pages[page].setFooter(footerResolver(page, pages.length));
const curPage = useUtil ? await msg.util.reply(pages[page]) : await msg.channel.send(pages[page]);
psibean marked this conversation as resolved.
Show resolved Hide resolved
const reactionCollector = curPage.createReactionCollector(
(reaction, user) => emojiList.includes(reaction.emoji.name) && !user.bot,
{ time: timeout }
(reaction, user) => emojiList.includes(reaction.emoji.name) && !user.bot
psibean marked this conversation as resolved.
Show resolved Hide resolved
&& (collectorFilter ? collectorFilter(reaction, user, emojiList) : true),
psibean marked this conversation as resolved.
Show resolved Hide resolved
{ time: timeout, ...rest }
);
reactionCollector.on('collect', reaction => {
reaction.users.remove(msg.author);
switch (reaction.emoji.name) {
case emojiList[0]:
page = page > 0 ? --page : pages.length - 1;
break;
case emojiList[1]:
page = page + 1 < pages.length ? ++page : 0;
break;
default:
break;
}
curPage.edit(pages[page].setFooter(`Page ${page + 1} / ${pages.length}`));
reactionCollector.on('collect', async (reaction, user) => {
// In case a react deletes the curPage msg in the pageResolver and another react is quickly made.
if (curPage.deleted) return;
psibean marked this conversation as resolved.
Show resolved Hide resolved
await reaction.users.remove(user.id);
const currentPage = page;
page = await pageResolver(curPage, pages, emojiList, page, reaction);

if ( !curPage.deleted && currentPage != page && page >= 0 && page < pages.length)
curPage.edit(pages[page].setFooter(footerResolver(page, pages.length)));
});
reactionCollector.on('end', () => {
reactionCollector.on('end', async () => {
if (!curPage.deleted) {
curPage.reactions.removeAll()
if (deleteOnEnd)
await curPage.delete();
else
curPage.reactions.removeAll();
}
});
// This will fail if the message is deleted before the reactions are all added, bail before reactor creation
try {
for (const emoji of emojiList) await curPage.react(emoji);
} catch (error) {
reactionCollector.stop();
psibean marked this conversation as resolved.
Show resolved Hide resolved
throw error;
}
return curPage;
};

module.exports = paginationEmbed;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "1.0.3",
"description": "A simple utility to paginate discord embeds. ",
"main": "index.js",
"types": "index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
Expand Down