diff --git a/.eslintrc.json b/.eslintrc.json index 0e95594..f2aff2d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -142,7 +142,7 @@ "error" ], "no-underscore-dangle": [ - "error", + "warn", { "allowAfterThis": true, "allowFunctionParams": true diff --git a/src/autocomplete/references.js b/src/autocomplete/references.js index f5bd54c..300371e 100644 --- a/src/autocomplete/references.js +++ b/src/autocomplete/references.js @@ -1,7 +1,4 @@ const { Autocompleter } = require('@eartharoid/dbf'); -const emoji = require('node-emoji'); -const Cryptr = require('cryptr'); -const { decrypt } = new Cryptr(process.env.ENCRYPTION_KEY); module.exports = class ReferencesCompleter extends Autocompleter { constructor(client, options) { @@ -11,12 +8,6 @@ module.exports = class ReferencesCompleter extends Autocompleter { }); } - format(ticket) { - const date = new Date(ticket.createdAt).toLocaleString(ticket.guild.locale, { dateStyle: 'short' }); - const topic = ticket.topic ? '| ' + decrypt(ticket.topic).substring(0, 50) : ''; - const category = emoji.hasEmoji(ticket.category.emoji) ? emoji.get(ticket.category.emoji) + ' ' + ticket.category.name : ticket.category.name; - return `${category} #${ticket.number} - ${date} ${topic}`; - } /** * @param {string} value @@ -24,32 +15,12 @@ module.exports = class ReferencesCompleter extends Autocompleter { * @param {import("discord.js").AutocompleteInteraction} interaction */ async run(value, comamnd, interaction) { - /** @type {import("client")} */ - const client = this.client; - const tickets = await client.prisma.ticket.findMany({ - include: { - category: { - select: { - emoji: true, - name: true, - }, - }, - guild: true, - }, - where: { - createdById: interaction.user.id, + await interaction.respond( + await this.client.autocomplete.components.get('ticket').getOptions(value, { guildId: interaction.guild.id, open: false, - }, - }); - const options = value ? tickets.filter(t => this.format(t).match(new RegExp(value, 'i'))) : tickets; - await interaction.respond( - options - .slice(0, 25) - .map(t => ({ - name: this.format(t), - value: t.id, - })), + userId: interaction.user.id, + }), ); } }; \ No newline at end of file diff --git a/src/autocomplete/ticket.js b/src/autocomplete/ticket.js index fec52e6..e6ac012 100644 --- a/src/autocomplete/ticket.js +++ b/src/autocomplete/ticket.js @@ -1,7 +1,10 @@ +/* eslint-disable no-underscore-dangle */ const { Autocompleter } = require('@eartharoid/dbf'); const emoji = require('node-emoji'); const Cryptr = require('cryptr'); const { decrypt } = new Cryptr(process.env.ENCRYPTION_KEY); +const Keyv = require('keyv'); +const ms = require('ms'); module.exports = class TicketCompleter extends Autocompleter { constructor(client, options) { @@ -9,13 +12,55 @@ module.exports = class TicketCompleter extends Autocompleter { ...options, id: 'ticket', }); + + this.cache = new Keyv(); } - format(ticket) { - const date = new Date(ticket.createdAt).toLocaleString(ticket.guild.locale, { dateStyle: 'short' }); - const topic = ticket.topic ? '| ' + decrypt(ticket.topic).substring(0, 50) : ''; - const category = emoji.hasEmoji(ticket.category.emoji) ? emoji.get(ticket.category.emoji) + ' ' + ticket.category.name : ticket.category.name; - return `${category} #${ticket.number} - ${date} ${topic}`; + async getOptions(value, { + guildId, + open, + userId, + }) { + /** @type {import("client")} */ + const client = this.client; + const cacheKey = [guildId, userId, open].join('/'); + + let tickets = await this.cache.get(cacheKey); + + if (!tickets) { + tickets = await client.prisma.ticket.findMany({ + include: { + category: { + select: { + emoji: true, + name: true, + }, + }, + guild: true, + }, + where: { + createdById: userId, + guildId, + open, + }, + }); + tickets = tickets.map(ticket => { + const date = new Date(ticket.createdAt).toLocaleString([ticket.guild.locale, 'en-GB'], { dateStyle: 'short' }); + const topic = ticket.topic ? '- ' + decrypt(ticket.topic).substring(0, 50) : ''; + const category = emoji.hasEmoji(ticket.category.emoji) ? emoji.get(ticket.category.emoji) + ' ' + ticket.category.name : ticket.category.name; + ticket._name = `${category} #${ticket.number} (${date}) ${topic}`; + return ticket; + }); + this.cache.set(cacheKey, tickets, ms('1m')); + } + + const options = value ? tickets.filter(t => t._name.match(new RegExp(value, 'i'))) : tickets; + return options + .slice(0, 25) + .map(t => ({ + name: t._name, + value: t.id, + })); } /** @@ -24,32 +69,12 @@ module.exports = class TicketCompleter extends Autocompleter { * @param {import("discord.js").AutocompleteInteraction} interaction */ async run(value, command, interaction) { - /** @type {import("client")} */ - const client = this.client; - const tickets = await client.prisma.ticket.findMany({ - include: { - category: { - select: { - emoji: true, - name: true, - }, - }, - guild: true, - }, - where: { - createdById: interaction.user.id, - guildId: interaction.guild.id, - open: ['add', 'close', 'force-close', 'remove'].includes(command.name), // false for `new`, `transcript` etc - }, - }); - const options = value ? tickets.filter(t => this.format(t).match(new RegExp(value, 'i'))) : tickets; await interaction.respond( - options - .slice(0, 25) - .map(t => ({ - name: this.format(t), - value: t.id, - })), + await this.getOptions(value, { + guildId: interaction.guild.id, + open: ['add', 'close', 'force-close', 'remove'].includes(command.name), // false for `new`, `transcript` etc + userId: interaction.user.id, + }), ); } }; \ No newline at end of file