diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..43e9051 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,41 @@ +import { Message, EmbedOptions } from 'eris'; + +declare module 'eris-pagination' { + + /** + * An optional options object for overwriting defaults + */ + interface PaginationOptions { + /** Whether or not to show the current page index over the embed. Defaults to: true */ + showPageNumbers?: boolean; + /** Whether or not to show extended control buttons besides standard pagination (First & Last page, deleting) */ + extendedButtons?: boolean; + /** Cycle through all embeds jumping from the first page to the last page on going back and from the last page to the first page going forth. Defaults to: false */ + cycling?: boolean; + /** How often the reaction handler should listen for a reaction (How often the paginator can be used). Defaults to: 50. Maximum: 100 */ + maxMatches?: number; + /** How long the paginator should work before the reaction listener times out. Defaults to: 300000ms (5 minutes). Maximum: 900000ms (15 minutes) */ + timeout?: number; + /** Emoji which should be used as the delete button. This MUST be a unicode emoji! Defaults to: 🗑 */ + deleteButton?: string; + /** Emoji which should be used as the first page button. This MUST be a unicode emoji! Defaults to: ⏮ */ + firstButton?: string; + /** Emoji which should be used as the last page button. This MUST be a unicode emoji! Defaults to: ⏭ */ + lastButton?: string; + /** Emoji which should be used as the back button. This MUST be a unicode emoji! Defaults to: ⬅ */ + backButton?: string; + /** Emoji which should be used as the forth button. This MUST be a unicode emoji! Defaults to: ➡ */ + forthButton?: string; + /** Which page of the submitted embed array should be shown first. Defaults to: 1 (The 1st page / element in the array) */ + startPage?: number; + } + + /** + * Create an Embed Paginator + * @param message A message object emitted from a messageCreate event coming from Eris, used as an invoker. If sent by the client, the message will be edited. + * @param pages An array containing all embed objects + * @param options An optional options object for overwriting defaults + */ + function createPaginationEmbed(message: Message, pages: EmbedOptions[], options?: PaginationOptions): Promise; + +} \ No newline at end of file diff --git a/lib/PaginationEmbed.js b/lib/PaginationEmbed.js index eb48184..fce8d82 100755 --- a/lib/PaginationEmbed.js +++ b/lib/PaginationEmbed.js @@ -2,6 +2,22 @@ const ReactionHandler = require('eris-reactions'); +/** + * @typedef {import('eris').EmbedBase} EmbedBase + * @typedef {import('eris').Message} Message + * @typedef {Object} PaginationOptions An optional options object for overwriting defaults + * @property {Boolean} [showPageNumbers] Whether or not to show the current page index over the embed. Defaults to: true + * @property {Boolean} [extendedButtons] Whether or not to show extended control buttons besides standard pagination (First & Last page, deleting) + * @property {Boolean} [cycling] Cycle through all embeds jumping from the first page to the last page on going back and from the last page to the first page going forth. Defaults to: false + * @property {Number} [maxMatches] How often the reaction handler should listen for a reaction (How often the paginator can be used). Defaults to: 50. Maximum: 100 + * @property {Number} [timeout] How long the paginator should work before the reaction listener times out. Defaults to: 300000ms (5 minutes). Maximum: 900000ms (15 minutes) + * @property {String} [deleteButton] Emoji which should be used as the delete button. This MUST be a unicode emoji! Defaults to: 🗑 + * @property {String} [firstButton] Emoji which should be used as the first page button. This MUST be a unicode emoji! Defaults to: ⏮ + * @property {String} [lastButton] Emoji which should be used as the last page button. This MUST be a unicode emoji! Defaults to: ⏭ + * @property {String} [backButton] Emoji which should be used as the back button. This MUST be a unicode emoji! Defaults to: ⬅ + * @property {String} [forthButton] Emoji which should be used as the forth button. This MUST be a unicode emoji! Defaults to: ➡ + * @property {Number} [startPage] Which page of the submitted embed array should be shown first. Defaults to: 1 (The 1st page / element in the array) + */ /** * Embed Pagination class * @class PaginationEmbed @@ -10,20 +26,9 @@ const ReactionHandler = require('eris-reactions'); class PaginationEmbed { /** * Constructor for the Embed Paginator - * @param {Eris#Message} message A message object emitted from a messageCreate event coming from Eris, used as an invoker. - * @param {Object[]} pages An array containing all embed objects - * @param {Object} options An optional options object for overwriting defaults - * @property {Boolean} options.showPageNumbers Whether or not to show the current page index over the embed. Defaults to: true - * @property {Boolean} options.extendedButtons Whether or not to show extended control buttons besides standard pagination (First & Last page, deleting) - * @property {Boolean} options.cycling Cycle through all embeds jumping from the first page to the last page on going back and from the last page to the first page going forth. Defaults to: false - * @property {Number} options.maxMatches How often the reaction handler should listen for a reaction (How often the paginator can be used). Defaults to: 50. Maximum: 100 - * @property {Number} options.timeout How long the paginator should work before the reaction listener times out. Defaults to: 300000ms (5 minutes). Maximum: 900000ms (15 minutes) - * @property {String} options.deleteButton Emoji which should be used as the delete button. This MUST be a unicode emoji! Defaults to: 🗑 - * @property {String} options.firstButton Emoji which should be used as the first page button. This MUST be a unicode emoji! Defaults to: ⏮ - * @property {String} options.lastButton Emoji which should be used as the last page button. This MUST be a unicode emoji! Defaults to: ⏭ - * @property {String} options.backButton Emoji which should be used as the back button. This MUST be a unicode emoji! Defaults to: ⬅ - * @property {String} options.forthButton Emoji which should be used as the forth button. This MUST be a unicode emoji! Defaults to: ➡ - * @property {Number} options.startPage Which page of the submitted embed array shoulb be shown first. Defaults to: 1 (The 1st page / element in the array) + * @param {Message} message A message object emitted from a messageCreate event coming from Eris, used as an invoker. If sent by the client, the message will be edited. + * @param {EmbedBase[]} pages An array containing all embed objects + * @param {PaginationOptions} [options] An optional options object for overwriting defaults */ constructor(message, pages = [], options = {}) { this.pages = pages; @@ -62,11 +67,17 @@ class PaginationEmbed { if (this.timeout > 900000) { return Promise.reject(new Error('Embed Timeout too high! Maximum pagination lifespan allowed is 15 minutes (900000 ms)!')); } - - this.message = await this.invoker.channel.createMessage({ + + const messageContent = { content: (this.showPages) ? `Page **${this.page}** of **${this.pages.length}**` : undefined, embed: this.pages[this.page - 1] - }); + } + + if (this.invoker.author.id === this.invoker._client.user.id) { + this.message = await this.invoker.edit(messageContent); + } else { + this.message = await this.invoker.channel.createMessage(messageContent) + } this.handler = new ReactionHandler.continuousReactionStream(this.message, (userID) => userID === this.invoker.author.id, false, { maxMatches: this.maxMatches, time: this.timeout }); @@ -92,6 +103,14 @@ class PaginationEmbed { }); } + /** + * Check if the client can remove the reaction + * @returns {Boolean} + */ + checkPerms() { + return this.message.channel.guild && this.message.channel.permissionsOf(this.message._client.user.id).has('manageMessages'); + } + /** * Main method handling the reaction listening and content updating */ @@ -100,7 +119,9 @@ class PaginationEmbed { switch (event.emoji.name) { case this.firstPage: { if (this.advanced) { - await this.message.removeReaction(this.firstPage, this.invoker.author.id); + if (this.checkPerms()) { + await this.message.removeReaction(this.firstPage, this.invoker.author.id); + } if (this.page > 1) { this.page = 1; @@ -112,7 +133,9 @@ class PaginationEmbed { } case this.back: { - await this.message.removeReaction(this.back, this.invoker.author.id); + if (this.checkPerms()) { + await this.message.removeReaction(this.back, this.invoker.author.id); + } if (this.page > 1) { this.page--; @@ -126,7 +149,9 @@ class PaginationEmbed { } case this.forth: { - await this.message.removeReaction(this.forth, this.invoker.author.id); + if (this.checkPerms()) { + await this.message.removeReaction(this.forth, this.invoker.author.id); + } if (this.page < this.pages.length) { this.page++; @@ -141,7 +166,9 @@ class PaginationEmbed { case this.lastPage: { if (this.advanced) { - await this.message.removeReaction(this.lastPage, this.invoker.author.id); + if (this.checkPerms()) { + await this.message.removeReaction(this.lastPage, this.invoker.author.id); + } if (this.page < this.pages.length) { this.page = this.pages.length; @@ -156,10 +183,14 @@ class PaginationEmbed { case this.delete: { if (this.advanced) { - return new Promise((resolve) => { - this.message.removeReactions().then(() => { - resolve(); - }); + return new Promise((resolve, reject) => { + if (this.checkPerms()) { + this.message.removeReactions().then(() => { + resolve(); + }); + } else { + reject(new Error('Insufficient permissions to remove reactions')) + } }); } @@ -171,6 +202,13 @@ class PaginationEmbed { } module.exports = { + /** + * Create an Embed Paginator + * + * @param {Message} message A message object emitted from a messageCreate event coming from Eris, used as an invoker. If sent by the client, the message will be edited. + * @param {EmbedBase[]} pages An array containing all embed objects + * @param {PaginationOptions} [options] An optional options object for overwriting defaults + */ createPaginationEmbed: async (message, pages, options) => { const paginationEmbed = new PaginationEmbed(message, pages, options); await paginationEmbed.initialize(); diff --git a/package-lock.json b/package-lock.json index 26ab30e..6a7f9ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { "name": "eris-pagination", - "version": "0.4.0", + "version": "0.5.2", "lockfileVersion": 1, "requires": true, "dependencies": { "eris-reactions": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/eris-reactions/-/eris-reactions-0.1.2.tgz", - "integrity": "sha512-p497xAdNsw3RRfAoklYemWRk1HT22rBmRaiemG6TVZ1yPTuQf41r4GteyKOJZ3hkphD3Rte7/1GiZwPzUNOHcw==" + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/eris-reactions/-/eris-reactions-0.1.4.tgz", + "integrity": "sha512-U2rMtfywnhh4TmqFcF7uo/ciyQN8vb9ptwSJMQs/uaY1a401f+t3sei1R3IR2gYqaFejJzgjTmzBMT6jIBPYYQ==" } } } diff --git a/package.json b/package.json index 39a41d2..1d5ca9d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eris-pagination", - "version": "0.4.0", + "version": "0.5.2", "description": "An extremely easy to use Embed Paginator for the Eris Discord Library", "main": "index.js", "scripts": { @@ -25,6 +25,9 @@ }, "homepage": "https://github.com/riyacchi/eris-pagination#readme", "dependencies": { - "eris-reactions": "^0.1.2" + "eris-reactions": "^0.1.4" + }, + "peerDependencies": { + "eris": "^0.13.1" } }