curate/src/structures/GenericPager.js
2022-11-10 14:37:18 -06:00

103 lines
No EOL
3.4 KiB
JavaScript

const Paginator = require('./Paginator');
const lodash = require('lodash');
const config = require('config');
/**
* A generic pager that shows a list of items
*/
class GenericPager extends Paginator {
/**
* @param {TrelloBot} client The client to use
* @param {Message} message The user's message to read permissions from
* @param {Object} options The options for the pager
* @param {Array} options.items The items the paginator will display
* @param {number} [options.itemsPerPage=15] How many items a page will have
* @param {Function} [options.display] The function that will be used to display items on the prompt
* @param {Object} [options.embedExtra] The embed object to add any extra embed elements to the prompt
* @param {string} [options.itemTitle='words.item.many'] The title to use for the items
* @param {string} [options.header] The text to show above the prompt
* @param {string} [options.footer] The text to show below the prompt
*/
constructor(client, message, {
items = [], itemsPerPage = 15,
display = item => item.toString(),
embedExtra = {}, itemTitle = 'Items',
header = null, footer = null
} = {}) {
super(client, message, { items, itemsPerPage });
this.displayFunc = display;
this.embedExtra = embedExtra;
this.itemTitle = itemTitle;
this.header = header;
this.footer = footer;
}
/**
* Whether or not this instance can use embed
* @returns {boolean}
*/
canEmbed() {
return this.message.channel.type === 1 ||
this.message.channel.permissionsOf(this.client.user.id).has('EMBED_LINKS');
}
/**
* Updates the current message
* @returns {Promise}
*/
updateMessage() {
return this.message.edit(this.currentMessage).catch(() => {});
}
/**
* The message for the current page
* @type {Object|string}
*/
get currentMessage() {
const displayPage = this.page.map((item, index) =>
this.displayFunc(item, index, ((this.pageNumber - 1) * this.itemsPerPage) + index));
if (this.canEmbed()) {
const embed = lodash.defaultsDeep({
title: `${this.itemTitle} ` +
`(${this.items.length}, Page ${this.pageNumber}/${this.maxPages})`,
description: this.header || undefined,
footer: this.footer ? { text: this.footer } : undefined,
fields: []
}, this.embedExtra, { color: config.embedColor });
embed.fields.push({
name: '*List Prompt*',
value: displayPage.join('\n')
});
return { embed };
} else {
const top = `${this.itemTitle} ` +
`(${this.items.length}, Page ${this.pageNumber}/${this.maxPages})`;
const lines = '─'.repeat(top.length);
return (this.header || '') + '```prolog\n' + `${top}\n` + `${lines}\n` +
displayPage.join('\n') + `${lines}\`\`\`` + (this.footer || '');
}
}
/**
* Starts the reaction collector and pagination
* @param {string} channelID The channel to post the new message to
* @param {string} userID The user's ID that started the process
* @param {number} timeout
*/
async start(channelID, userID, timeout) {
this.message = await this.client.createMessage(channelID, this.currentMessage);
return super.start(userID, timeout);
}
/**
* @private
*/
_change() {
this.updateMessage().catch(() => this.collector.end());
this.emit('change', this.pageNumber);
}
}
module.exports = GenericPager;