discord-paginator.js/index.js

125 lines
3.4 KiB
JavaScript

let djs
try {
djs = require('discord.js')
} catch {
throw new Error('Paginator: ' + 'Please install discord.js package manually')
}
const defaultOpts = {
pages: [],
remove: '🗑️',
reset: '🔁',
reaction: ['⬅️', '➡️'],
removeReaction: true,
removeAtEnd: true,
timeout: 60000,
filter: (reaction, user) => true
}
function none() {}
class Paginator {
constructor(opts = defaultOpts) {
Object.assign(this, defaultOpts)
Object.assign(this, opts)
}
async spawn(channel) {
const opts = {
remove: this.remove,
reset: this.reset,
reaction: this.reaction,
removeReaction: this.removeReaction,
removeAtEnd: this.removeAtEnd,
timeout: this.timeout,
filter: this.filter
}
const pages = [...this.pages]
let page = 0
if (!pages.length) throw new Error('Paginator: ' + 'Empty pages')
let message = await channel.send(pages[page])
if (!Array.isArray(opts.reaction) || opts.reaction.length < 2) throw new Error('Paginator: ' + 'Must be two reactions given in \'reaction\' options')
if (typeof opts.filter != 'function') throw new Error('Paginator: ' + 'Expecting a function in \'filter\' options')
if (opts.timeout < 1000 || opts.timeout > 259200000) throw new Error('Paginator: ' + 'Spawner timeout must be between 1 second and 3 days')
const reactions = {}
if (typeof opts.reset == 'string' && pages.length > 1) {
reactions.reset = await message.react(opts.reset).catch(none)
if (!reactions.reset) return
}
if (pages.length > 1) {
reactions.left = await message.react(opts.reaction[0]).catch(none)
if (!reactions.left) return
reactions.right = await message.react(opts.reaction[1]).catch(none)
}
if (typeof opts.remove == 'string') {
reactions.remove = await message.react(opts.remove).catch(none)
if (!reactions.remove) return
}
async function filter(reaction, user) {
const bool = [false, await opts.filter(reaction, user)]
if (reactions.reset) bool[0] = reaction.emoji.toString() == reactions.reset.emoji.toString()
if (!bool[0] && reactions.remove) bool[0] = reaction.emoji.toString() == reactions.remove.emoji.toString()
if (!bool[0]) bool[0] = reaction.emoji.toString() == reactions.left.emoji.toString() || reaction.emoji.toString() == reactions.right.emoji.toString()
return bool.every(condition => condition)
}
const collector = message.createReactionCollector(filter, { time: opts.timeout })
collector.on('collect', async (reaction, user) => {
if (reactions.reset && reaction.emoji.toString() == reactions.reset.emoji.toString()) {
page = 0
await message.edit(pages[page])
} else if (reactions.remove && reaction.emoji.toString() == reactions.remove.emoji.toString()) {
collector.stop('123M0V3')
return
} else if (reaction.emoji.toString() == reactions.left.emoji.toString()) {
if (pages[page - 1]) {
page--
await message.edit(pages[page])
}
} else if (reaction.emoji.toString() == reactions.right.emoji.toString()) {
if (pages[page + 1]) {
page++
await message.edit(pages[page])
}
}
reaction.users.remove(user.id).catch(none)
})
collector.on('end', async (collected, reason) => {
if (opts.removeAtEnd && reason != '123M0V3') {
for (const reaction of Object.values(reactions)) {
await reaction.remove().catch(none)
}
}
if (reason == '123M0V3') await message.delete()
})
}
}
module.exports = Paginator