From 71e0d788c34ebfd74fc4d2ea3d7fed5b891196c2 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 21 Jan 2023 14:34:58 +0100 Subject: [PATCH 01/40] refactor: improve subcmd type --- src/commands/util/Reminder.ts | 4 +++- src/types/index.d.ts | 6 +++--- src/utils/misc.ts | 8 +++++++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/commands/util/Reminder.ts b/src/commands/util/Reminder.ts index af8fce6..037f0e6 100644 --- a/src/commands/util/Reminder.ts +++ b/src/commands/util/Reminder.ts @@ -170,11 +170,13 @@ export class Reminder extends Command } } + //#MARKER run + async run(int: CommandInteraction, opt: CommandInteractionOption<"cached">) { const { user, guild, channel } = int; - let action = ""; + let action = "run the reminder command"; try { const tooSoon = () => this.reply(int, embedify("Please enter an expiry that's at least five seconds from now.", settings.embedColors.error), true); diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 1573d8c..b96711c 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -92,11 +92,11 @@ export interface CommandMeta extends CmdMetaBase { /** Meta information of a Command instance that has multiple subcommands - see https://discordjs.guide/interactions/slash-commands.html#subcommands */ export interface SubcommandMeta extends CmdMetaBase { /** Array of subcommands */ - subcommands: Omit[]; + subcommands: Pick[]; } -/** Result of PUTing a guild command to the Discord API */ -export interface PutGuildCommandResult { +/** Result of PUTing an application guild command (slash or context) to the Discord API */ +export interface PutApplicationGuildCommandsResult { application_id: string; default_member_permissions: null | string; default_permission: boolean; diff --git a/src/utils/misc.ts b/src/utils/misc.ts index 3d204e7..fde251f 100644 --- a/src/utils/misc.ts +++ b/src/utils/misc.ts @@ -4,13 +4,19 @@ export function truncStr(str: string, length: number, endStr = "...") return str.length > length ? str.substring(0, length) + endStr : str; } +/** Truncates the value of an EmbedBuilder field to a max length of 1024 and inserts endStr */ export function truncField(content: string, endStr = "...") { return truncStr(content, 1024 - endStr.length, endStr); } /** - * Automatically appends an `s` to the passed `word`, if `num` is not equal to 1 + * Automatically appends an `"s"` to the passed `word`, if `num` (or length of num if it's an array) is not equal to 1 + * @example ```ts + * autoPlural("bunger", 1) // "bunger" + * autoPlural("bunger", 2) // "bungers" + * autoPlural("bunger", [1,2]) // "bungers" + * ``` * @param word A word in singular form, to auto-convert to plural * @param num If this is an array, the amount of items is used */ From 73bdb372ddf20bcc6d17e2fe561cac61e17894c1 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 21 Jan 2023 20:15:01 +0100 Subject: [PATCH 02/40] fix: replace randomUUID with nanoid 4 better perf --- package-lock.json | 17 +++++++++++++++++ package.json | 1 + src/utils/BtnMsg.ts | 4 ++-- src/utils/Modal.ts | 4 ++-- src/utils/PageEmbed.ts | 7 ++++--- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index ca1878a..a3d5b7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "fs-extra": "^10.1.0", "fuse.js": "^6.6.2", "kleur": "^4.1.4", + "nanoid": "^3.3.4", "prisma": "^4.3.1", "redis": "^4.2.0", "simple-statistics": "^7.7.5", @@ -2559,6 +2560,17 @@ "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5803,6 +5815,11 @@ "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", diff --git a/package.json b/package.json index 532b85a..662550b 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "fs-extra": "^10.1.0", "fuse.js": "^6.6.2", "kleur": "^4.1.4", + "nanoid": "^3.3.4", "prisma": "^4.3.1", "redis": "^4.2.0", "simple-statistics": "^7.7.5", diff --git a/src/utils/BtnMsg.ts b/src/utils/BtnMsg.ts index 6eeebba..b242063 100644 --- a/src/utils/BtnMsg.ts +++ b/src/utils/BtnMsg.ts @@ -1,5 +1,5 @@ -import { randomUUID } from "crypto"; import { ButtonInteraction, ActionRowBuilder, ButtonBuilder, EmbedBuilder, TextBasedChannel, APIButtonComponentWithCustomId, ButtonStyle } from "discord.js"; +import { nanoid } from "nanoid"; import { btnListener } from "@src/registry"; import { EmitterBase } from "@utils/EmitterBase"; @@ -48,7 +48,7 @@ export class BtnMsg extends EmitterBase { super(); - this.btnId = randomUUID(); + this.btnId = nanoid(); this.msg = message instanceof EmbedBuilder ? [message] : message; diff --git a/src/utils/Modal.ts b/src/utils/Modal.ts index 8a30d99..2da8e6f 100644 --- a/src/utils/Modal.ts +++ b/src/utils/Modal.ts @@ -1,5 +1,5 @@ import { ActionRowBuilder, TextInputBuilder, ModalBuilder as DjsModal, ModalSubmitInteraction, EmbedBuilder, ButtonBuilder, ModalActionRowComponentBuilder } from "discord.js"; -import { randomUUID } from "crypto"; +import { nanoid } from "nanoid"; import { registerModal } from "@src/registry"; import { Command } from "@src/Command"; import { EmitterBase } from "./EmitterBase"; @@ -26,7 +26,7 @@ export abstract class Modal extends EmitterBase { constructor(data: ModalConstructor) { super(); - this.id = randomUUID(); + this.id = nanoid(); this.internalModal = new DjsModal() .setCustomId(this.id) diff --git a/src/utils/PageEmbed.ts b/src/utils/PageEmbed.ts index e4490c6..4225e29 100644 --- a/src/utils/PageEmbed.ts +++ b/src/utils/PageEmbed.ts @@ -2,11 +2,12 @@ import { Message, EmbedBuilder, ButtonInteraction, TextBasedChannel, ButtonBuild import { time } from "@discordjs/builders"; import { clamp } from "svcorelib"; import { APIEmbed } from "discord-api-types/v10"; -import { randomUUID } from "crypto"; +import { nanoid } from "nanoid"; + import { EmitterBase } from "@utils/EmitterBase"; import { Command } from "@src/Command"; import { btnListener } from "@src/registry"; -import { useEmbedify } from "./embedify"; +import { useEmbedify } from "@src/utils"; import { settings } from "@src/settings"; import { AnyInteraction, DiscordAPIFile, Tuple } from "@src/types"; @@ -86,7 +87,7 @@ export class PageEmbed extends EmitterBase { super(); - this.btnId = randomUUID(); + this.btnId = nanoid(); this.pages = pages.map(p => p instanceof EmbedBuilder ? p.toJSON() : p); this.files = files?.length ? files : []; From 2205eb4e57a7642668306e31bfe8bc06efaba976 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 21 Jan 2023 20:15:14 +0100 Subject: [PATCH 03/40] fix: exec imports --- src/modals/exec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modals/exec.ts b/src/modals/exec.ts index f077a4a..c7ff67f 100644 --- a/src/modals/exec.ts +++ b/src/modals/exec.ts @@ -31,6 +31,7 @@ export class ExecModal extends Modal try { const { channel, user, guild, client } = int; + // only destructured to be made available to the eval() unused(channel, user, guild, client); const code = int.fields.getTextInputValue("code").trim(); @@ -41,7 +42,7 @@ export class ExecModal extends Modal try { const lines = [ - "import { EmbedBuilder, ButtonBuilder, Colors, CommandInteraction, ButtonInteraction, Collection, User, Member, Guild } from \"discord.js\";", + "import { EmbedBuilder, ButtonBuilder, ButtonStyle, Colors, CommandInteraction, ButtonInteraction, Collection, User, Member, Guild } from \"discord.js\";", "import { BtnMsg, PageEmbed, embedify, useEmbedify, toUnix10, truncStr, truncField } from \"../utils/\";", "(async () => {", code, From a00daff43100667e11c61d3777b5eff8a1bd14a1 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 21 Jan 2023 21:17:05 +0100 Subject: [PATCH 04/40] feat: unfinished reminder rescheduling --- src/commands/util/Reminder.ts | 119 ++++++++++++++++++++++++++++++++-- src/utils/BtnMsg.ts | 4 +- 2 files changed, 118 insertions(+), 5 deletions(-) diff --git a/src/commands/util/Reminder.ts b/src/commands/util/Reminder.ts index 037f0e6..7383890 100644 --- a/src/commands/util/Reminder.ts +++ b/src/commands/util/Reminder.ts @@ -1,12 +1,13 @@ -import { ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ChannelType, Client, CommandInteraction, CommandInteractionOption, EmbedBuilder, TextBasedChannel } from "discord.js"; +import { ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ChannelType, Client, CommandInteraction, CommandInteractionOption, Embed, EmbedBuilder, Message, TextBasedChannel } from "discord.js"; import k from "kleur"; import { Command } from "@src/Command"; import { settings } from "@src/settings"; import { time } from "@discordjs/builders"; import { createNewUser, deleteReminder, deleteReminders, getExpiredReminders, getReminder, getReminders, getUser, setReminder } from "@src/database/users"; import { Reminder as ReminderObj } from "@prisma/client"; -import { autoPlural, BtnMsg, embedify, PageEmbed, timeToMs, toUnix10, useEmbedify } from "@src/utils"; +import { autoPlural, BtnMsg, ButtonsTuple, embedify, PageEmbed, timeToMs, toUnix10, useEmbedify } from "@src/utils"; import { Tuple } from "@src/types"; +import { randomItem } from "svcorelib"; /** Max reminders per user (global) */ const reminderLimit = 10; @@ -475,6 +476,104 @@ export class Reminder extends Command // TODO: add logger const reminderError = (err: Error) => console.error(k.red("Error while checking expired reminders:\n"), err); + /** Edits `msg` to have the reschedule buttons and handles the listening and reminder rescheduling */ + const editReschedMsg = (msg: Message, rem: ReminderObj) => { + const min = 60_000; + const hr = min * 60; + const day = hr * 24; + + const reschedBtns = [ + { + label: "+ 5m", + val: 5 * min, + }, + { + label: "+ 15m", + val: 15 * min, + }, + { + label: "+ 1h", + val: hr, + }, + { + label: "+ 3h", + val: 3 * hr, + }, + { + label: "+ 8h", + val: 8 * hr, + }, + { + label: "+ 12h", + val: 12 * hr, + }, + { + label: "+ 1d", + val: day, + }, + { + label: "+ 3d", + val: 6 * hr, + }, + { + label: "+ 7d", + val: 6 * hr, + }, + ].map(({ label, val }) => ({ + val, + label, + btn: new ButtonBuilder().setStyle(ButtonStyle.Secondary).setLabel(label), + })); + + reschedBtns.push({ + val: 0, + label: "Submit", + btn: new ButtonBuilder().setStyle(ButtonStyle.Primary).setLabel("Submit"), + }); + reschedBtns.push({ + val: 0, + label: "Cancel", + btn: new ButtonBuilder().setStyle(ButtonStyle.Danger).setLabel("Cancel"), + }); + + const getEbd = (rem: ReminderObj) => new EmbedBuilder() + .setColor(settings.embedColors.default) + .setDescription(`Rescheduling the reminder.\nPress any of the buttons below to add time onto this reminder.\n\nCurrent expiry: `); + + const ebd = getEbd(rem); + + const slicedBtnsInput = reschedBtns.map(({ btn }) => btn); + const slicedBtns: ButtonBuilder[][] = []; + while(slicedBtnsInput.length > 0) + slicedBtns.push(slicedBtnsInput.splice(0, 5)); + + const editReschedBm = new BtnMsg(ebd, slicedBtns as ButtonsTuple); + + const newReminder = { ...rem }; + + /** Adds the `value` in milliseconds to the newReminder */ + const addValueToReminder = (value: number) => { + newReminder.dueTimestamp = new Date(newReminder.dueTimestamp.getTime() + value); + msg.edit({ ...editReschedBm.getMsgOpts(), embeds: [ getEbd(newReminder) ]}); + }; + + editReschedBm.on("press", (btn, int) => { + const reschedBt = reschedBtns.find(b => b.label === btn.data.label); + if(int.user.id === rem.userId && reschedBt) { + if(btn.data.label === "Submit") + console.log("TODO"); + else if(btn.data.label === "Cancel") + console.log("TODO"); + else + addValueToReminder(reschedBt.val); + } + }); + + msg.edit({ + ...editReschedBm.getMsgOpts(), + }); + }; + /** Sends the expiry reminder in the guild and channel it was created in, but only if it is not private */ const remindPublicly = async (rem: ReminderObj) => { try { @@ -486,8 +585,18 @@ export class Reminder extends Command if(chan && [ChannelType.GuildText, ChannelType.GuildPublicThread, ChannelType.GuildPrivateThread, ChannelType.GuildForum].includes(chan.type)) { - const c = chan as TextBasedChannel; - c.send({ content: `Reminder! <@${rem.userId}>`, embeds: [ getExpiredEbd(rem) ] }); + const reschedBm = new BtnMsg("", new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ")); + + const msg = (chan as TextBasedChannel).send({ + ...reschedBm.getMsgOpts(), + content: `🔔 Reminder! <@${rem.userId}>`, + embeds: [ getExpiredEbd(rem) ], + }); + + reschedBm.on("press", async (btn, btInt) => { + if(btInt.user.id === rem.userId && btn.data.label === "Reschedule") + editReschedMsg(msg instanceof Promise ? await msg : msg, rem); + }); } } catch(err) { @@ -526,6 +635,8 @@ export class Reminder extends Command const usr = client.users.cache.find(u => u.id === rem.userId); promises.push((async () => { + const reschedBtn = new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ"); + if(!usr) return remindPublicly(rem); diff --git a/src/utils/BtnMsg.ts b/src/utils/BtnMsg.ts index b242063..0334252 100644 --- a/src/utils/BtnMsg.ts +++ b/src/utils/BtnMsg.ts @@ -21,6 +21,8 @@ export interface BtnMsg { on(event: "error", listener: (err: Error) => void): this; } +export type ButtonsTuple = Tuple, 1|2|3|4|5>; + /** * Wrapper for discord.js' `ButtonBuilder` * Contains convenience methods for easier creation of messages with attached buttons @@ -44,7 +46,7 @@ export class BtnMsg extends EmitterBase * @param message The message or reply content * @param buttons Up to 5 rows of 5 ButtonBuilder instances - customIDs will be managed by this BtnMsg */ - constructor(message: string | EmbedBuilder | EmbedBuilder[], buttons: ButtonBuilder | Tuple, 1|2|3|4|5>, options?: Partial) + constructor(message: string | EmbedBuilder | EmbedBuilder[], buttons: ButtonBuilder | ButtonsTuple, options?: Partial) { super(); From 9009c064f302392edd8133d80fbf43780de4e782 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 21 Jan 2023 21:30:19 +0100 Subject: [PATCH 05/40] fix: wrong prop in /premium toggle --- src/commands/music/Premium.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/music/Premium.ts b/src/commands/music/Premium.ts index 5c0b4b7..cea90b1 100644 --- a/src/commands/music/Premium.ts +++ b/src/commands/music/Premium.ts @@ -2,6 +2,7 @@ import { CommandInteraction, CommandInteractionOption, PermissionFlagsBits } fro import { Command } from "@src/Command"; import { embedify } from "@utils/embedify"; import { getPremium, togglePremium } from "@src/database/music"; +import { settings } from "@src/settings"; export class Premium extends Command { constructor() { @@ -13,7 +14,6 @@ export class Premium extends Command { { name: "toggle", desc: "Give premium to current guild [DEV ONLY]", - devOnly: true, perms: [PermissionFlagsBits.Administrator], }, { @@ -30,7 +30,7 @@ export class Premium extends Command { if(!int.guild?.id) return this.followUpReply(int, embedify("This command cannot be used in DMs")); - if(opt.name == "toggle") { + if(opt.name == "toggle" && settings.devs.includes(int.user.id)) { const a = await togglePremium(int.guild.id); return this.followUpReply(int, embedify(`${int.guild.name} ${a ? "now has" : "no longer has"} premium`)); From b7a6f3c0ac62f6e6bd4753e0f2cff9f72b8225f1 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 21 Jan 2023 22:22:30 +0100 Subject: [PATCH 06/40] feat: isDestroyed() method on all emitting classes --- src/utils/EmitterBase.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/utils/EmitterBase.ts b/src/utils/EmitterBase.ts index 79d50c2..29044ed 100644 --- a/src/utils/EmitterBase.ts +++ b/src/utils/EmitterBase.ts @@ -4,19 +4,21 @@ export abstract class EmitterBase extends EventEmitter { protected destroyed = false; - constructor() - { + constructor() { super({ captureRejections: true }); } /** Destroys this instance, emits the "destroy" event, then removes all event listeners */ - public destroy() - { + public destroy() { this._destroy(); } - protected _destroy(emitDestroy = true) - { + /** Whether destroy() has been called or not */ + public isDestroyed() { + return this.destroyed; + } + + protected _destroy(emitDestroy = true) { if(this.destroyed) return; From a0ab1ae346e5cae8081f4acdd0f84d8dd0f9327e Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 21 Jan 2023 22:22:55 +0100 Subject: [PATCH 07/40] feat: unfinished reminder rescheduling --- src/commands/util/Reminder.ts | 392 +++++++++++++++++++--------------- 1 file changed, 223 insertions(+), 169 deletions(-) diff --git a/src/commands/util/Reminder.ts b/src/commands/util/Reminder.ts index 7383890..7cf8a16 100644 --- a/src/commands/util/Reminder.ts +++ b/src/commands/util/Reminder.ts @@ -1,4 +1,4 @@ -import { ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ChannelType, Client, CommandInteraction, CommandInteractionOption, Embed, EmbedBuilder, Message, TextBasedChannel } from "discord.js"; +import { ActionRowBuilder, ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ChannelType, Client, CommandInteraction, CommandInteractionOption, EmbedBuilder, Message, TextBasedChannel } from "discord.js"; import k from "kleur"; import { Command } from "@src/Command"; import { settings } from "@src/settings"; @@ -7,21 +7,21 @@ import { createNewUser, deleteReminder, deleteReminders, getExpiredReminders, ge import { Reminder as ReminderObj } from "@prisma/client"; import { autoPlural, BtnMsg, ButtonsTuple, embedify, PageEmbed, timeToMs, toUnix10, useEmbedify } from "@src/utils"; import { Tuple } from "@src/types"; -import { randomItem } from "svcorelib"; /** Max reminders per user (global) */ const reminderLimit = 10; const reminderCheckInterval = 2000; /** To not exceed the embed limits */ const maxNameLength = 250; +/** + * Contains all compound keys of reminders that are currently being checked. + * This is necessary because the check could take longer than `reminderCheckInterval` and check the same reminder twice. + * Format: `userId-reminderId` + */ +const reminderCheckBuffer = new Set(); export class Reminder extends Command { - /** - * Contains all compound keys of reminders that are currently being checked. - * Format: `userId-reminderId` - */ - private reminderCheckBuffer = new Set(); constructor(client: Client) { @@ -162,8 +162,8 @@ export class Reminder extends Command { try { // since the constructor is called exactly once at startup, this should work just fine - this.checkReminders(client); - setInterval(() => this.checkReminders(client), reminderCheckInterval); + checkReminders(client); + setInterval(() => checkReminders(client), reminderCheckInterval); } catch(err) { console.error(k.red("Error while checking reminders:"), err); @@ -456,212 +456,266 @@ export class Reminder extends Command int.reply(cont); } } +} - //#MARKER check reminders - async checkReminders(client: Client) - { - const expRems = await getExpiredReminders(); - - if(!expRems || expRems.length === 0) - return; +//#MARKER check reminders +async function checkReminders(client: Client) +{ + const expRems = await getExpiredReminders(); - const promises: Promise[] = []; + if(!expRems || expRems.length === 0) + return; - // TODO: add buttons to reinstate the reminder and add more time to it - // e.g.: [+5m] [+10m] [+1h] [+3h] [+12h] - const getExpiredEbd = ({ name }: ReminderObj) => new EmbedBuilder() - .setDescription(`Your reminder has expired:\n> ${name.replace(/\n/gm, "\n> ")}`) - .setColor(settings.embedColors.default); + const promises: Promise[] = []; - // TODO: add logger - const reminderError = (err: Error) => console.error(k.red("Error while checking expired reminders:\n"), err); + const getExpiredEbd = ({ name }: ReminderObj) => new EmbedBuilder() + .setDescription(`Your reminder has expired:\n> ${name.replace(/\n/gm, "\n> ")}`) + .setColor(settings.embedColors.default); - /** Edits `msg` to have the reschedule buttons and handles the listening and reminder rescheduling */ - const editReschedMsg = (msg: Message, rem: ReminderObj) => { - const min = 60_000; - const hr = min * 60; - const day = hr * 24; + // TODO: add logger + const reminderError = (err: Error) => console.error(k.red("Error while checking expired reminders:\n"), err); - const reschedBtns = [ - { - label: "+ 5m", - val: 5 * min, - }, - { - label: "+ 15m", - val: 15 * min, - }, - { - label: "+ 1h", - val: hr, - }, - { - label: "+ 3h", - val: 3 * hr, - }, - { - label: "+ 8h", - val: 8 * hr, - }, - { - label: "+ 12h", - val: 12 * hr, - }, - { - label: "+ 1d", - val: day, - }, - { - label: "+ 3d", - val: 6 * hr, - }, - { - label: "+ 7d", - val: 6 * hr, - }, - ].map(({ label, val }) => ({ - val, - label, - btn: new ButtonBuilder().setStyle(ButtonStyle.Secondary).setLabel(label), - })); + /** Edits `msg` to have the reschedule buttons and handles the listening and reminder rescheduling */ + const editReschedMsg = (msg: Message, rem: ReminderObj) => { + const min = 60_000; + const hr = min * 60; + const day = hr * 24; - reschedBtns.push({ + /** null is used to pad to a new component row */ + const reschedBtns = [ + { + label: "+ 5m", + val: 5 * min, + }, + { + label: "+ 15m", + val: 15 * min, + }, + { + label: "+ 1h", + val: hr, + }, + { + label: "+ 3h", + val: 3 * hr, + }, + { + label: "+ 8h", + val: 8 * hr, + }, + { + label: "+ 12h", + val: 12 * hr, + }, + { + label: "+ 1d", + val: day, + }, + { + label: "+ 3d", + val: 6 * hr, + }, + { + label: "+ 7d", + val: 6 * hr, + }, + null, + { val: 0, label: "Submit", btn: new ButtonBuilder().setStyle(ButtonStyle.Primary).setLabel("Submit"), - }); - reschedBtns.push({ + }, + { val: 0, label: "Cancel", btn: new ButtonBuilder().setStyle(ButtonStyle.Danger).setLabel("Cancel"), - }); + }, + { + val: 0, + label: "Reset", + btn: new ButtonBuilder().setStyle(ButtonStyle.Secondary).setLabel("Reset"), + }, + ].map((props) => (props ? { + ...props, + btn: new ButtonBuilder().setStyle(ButtonStyle.Secondary).setLabel(props.label), + } : null)); - const getEbd = (rem: ReminderObj) => new EmbedBuilder() - .setColor(settings.embedColors.default) - .setDescription(`Rescheduling the reminder.\nPress any of the buttons below to add time onto this reminder.\n\nCurrent expiry: `); + const getEbd = (rem: ReminderObj) => new EmbedBuilder() + .setColor(settings.embedColors.default) + .setDescription(`Rescheduling the reminder.\nPress any of the buttons below to add time onto this reminder.\n\nCurrent expiry: `); - const ebd = getEbd(rem); + const ebd = getEbd(rem); - const slicedBtnsInput = reschedBtns.map(({ btn }) => btn); - const slicedBtns: ButtonBuilder[][] = []; - while(slicedBtnsInput.length > 0) - slicedBtns.push(slicedBtnsInput.splice(0, 5)); + const slicedBtnsInput = reschedBtns.map((props) => props ? props.btn : null); + const slicedBtns: ButtonBuilder[][] = []; + while(slicedBtnsInput.length > 0) + slicedBtns.push(slicedBtnsInput.splice(0, 5).filter(b => b !== null) as ButtonBuilder[]); - const editReschedBm = new BtnMsg(ebd, slicedBtns as ButtonsTuple); + const editReschedBm = new BtnMsg(ebd, slicedBtns as ButtonsTuple); - const newReminder = { ...rem }; + const newReminder = { ...rem }; - /** Adds the `value` in milliseconds to the newReminder */ - const addValueToReminder = (value: number) => { - newReminder.dueTimestamp = new Date(newReminder.dueTimestamp.getTime() + value); - msg.edit({ ...editReschedBm.getMsgOpts(), embeds: [ getEbd(newReminder) ]}); - }; + /** Adds the `value` in milliseconds to the newReminder */ + const addValueToReminder = (value: number) => { + newReminder.dueTimestamp = new Date(newReminder.dueTimestamp.getTime() + value); + msg.edit({ ...editReschedBm.getMsgOpts(), embeds: [ getEbd(newReminder) ]}); + }; - editReschedBm.on("press", (btn, int) => { - const reschedBt = reschedBtns.find(b => b.label === btn.data.label); - if(int.user.id === rem.userId && reschedBt) { - if(btn.data.label === "Submit") - console.log("TODO"); - else if(btn.data.label === "Cancel") - console.log("TODO"); - else - addValueToReminder(reschedBt.val); - } - }); + /** Resets the rescheduled reminder time back to the original */ + const resetRescheduledReminder = () => { + newReminder.dueTimestamp = new Date(rem.dueTimestamp.getTime()); + msg.edit({ ...editReschedBm.getMsgOpts(), embeds: [ getEbd(newReminder) ]}); + }; + + /** Sets a new reminder */ + const setRescheduledReminder = async (rem: ReminderObj) => { + const reminders = await getReminders(rem.userId); + + const reminderId = reminders && reminders.length > 0 && reminders.at(-1) + ? reminders.at(-1)!.reminderId + 1 + : 1; + + if(!await getUser(rem.userId)) + await createNewUser(rem.userId); + + await setReminder(rem); + return await msg.edit(useEmbedify(`I've rescheduled your reminder:\n> ${rem.name}\n> Now due on ${time(toUnix10(rem.dueTimestamp), "f")}\n\nID: \`${reminderId}\` â€Ē To list your reminders use \`/reminder list\``, settings.embedColors.success)); + }; + + /** Cancels the reminder rescheduling */ + const cancelRescheduling = () => { + if(!editReschedBm.isDestroyed()) + editReschedBm.destroy(); msg.edit({ ...editReschedBm.getMsgOpts(), + embeds: [ getExpiredEbd(rem) ], + components: [ + new ActionRowBuilder().setComponents( + new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ") + ), + ] }); }; - /** Sends the expiry reminder in the guild and channel it was created in, but only if it is not private */ - const remindPublicly = async (rem: ReminderObj) => { - try { - if(rem.private) - throw new Error("Can't send message in guild as reminder is private."); + let submitted = false, cancelled = false; - const guild = client.guilds.cache.find(g => g.id === rem.guild); - const chan = guild?.channels.cache.find(c => c.id === rem.channel); + editReschedBm.on("press", (btn, int) => { + const reschedBt = reschedBtns.find(b => b && b.label === btn.data.label); + if(int.user.id === rem.userId && reschedBt) { + if(btn.data.label === "Submit") { + submitted = true; + editReschedBm.destroy(); + return setRescheduledReminder(newReminder); + } + else if(btn.data.label === "Cancel") { + cancelled = true; + return cancelRescheduling(); + } + else if(btn.data.label === "Reset") + return resetRescheduledReminder(); + else + return addValueToReminder(reschedBt.val); + } + }); - if(chan && [ChannelType.GuildText, ChannelType.GuildPublicThread, ChannelType.GuildPrivateThread, ChannelType.GuildForum].includes(chan.type)) - { - const reschedBm = new BtnMsg("", new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ")); + ["timeout", "destroy"].forEach(evt => + editReschedBm.on(evt as "timeout", () => !submitted && !cancelled && cancelRescheduling()) + ); - const msg = (chan as TextBasedChannel).send({ - ...reschedBm.getMsgOpts(), - content: `🔔 Reminder! <@${rem.userId}>`, - embeds: [ getExpiredEbd(rem) ], - }); + msg.edit({ + ...editReschedBm.getMsgOpts(), + }); + }; - reschedBm.on("press", async (btn, btInt) => { - if(btInt.user.id === rem.userId && btn.data.label === "Reschedule") - editReschedMsg(msg instanceof Promise ? await msg : msg, rem); - }); - } + /** Sends the expiry reminder in the guild and channel it was created in, but only if it is not private */ + const remindPublicly = async (rem: ReminderObj) => { + try { + if(rem.private) + throw new Error("Can't send message in guild as reminder is private."); + + const guild = client.guilds.cache.find(g => g.id === rem.guild); + const chan = guild?.channels.cache.find(c => c.id === rem.channel); + + if(chan && [ChannelType.GuildText, ChannelType.GuildPublicThread, ChannelType.GuildPrivateThread, ChannelType.GuildForum].includes(chan.type)) + { + const reschedBm = new BtnMsg("", new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ")); + + const msg = (chan as TextBasedChannel).send({ + ...reschedBm.getMsgOpts(), + content: `🔔 Reminder! <@${rem.userId}>`, + embeds: [ getExpiredEbd(rem) ], + }); + + reschedBm.on("press", async (btn, btInt) => { + if(btInt.user.id === rem.userId && btn.data.label === "Reschedule") + editReschedMsg(msg instanceof Promise ? await msg : msg, rem); + }); + } + } + catch(err) { + // TODO: track reminder "loss rate" + // + // I │ I I + // ─────┾───── + // I I │ I ⌐® + + err instanceof Error && reminderError(err); + + void err; + } + finally { + try { + await deleteReminder(rem.reminderId, rem.userId); } catch(err) { - // TODO: track reminder "loss rate" - // - // I │ I I - // ─────┾───── - // I I │ I ⌐® + // TODO: see above err instanceof Error && reminderError(err); - - void err; } finally { - try { - await deleteReminder(rem.reminderId, rem.userId); - } - catch(err) { - // TODO: see above - - err instanceof Error && reminderError(err); - } - finally { - this.reminderCheckBuffer.delete(`${rem.userId}-${rem.reminderId}`); - } + reminderCheckBuffer.delete(`${rem.userId}-${rem.reminderId}`); } - }; - - for(const rem of expRems) - { - if(this.reminderCheckBuffer.has(`${rem.userId}-${rem.reminderId}`)) - continue; + } + }; - this.reminderCheckBuffer.add(`${rem.userId}-${rem.reminderId}`); + for(const rem of expRems) + { + if(reminderCheckBuffer.has(`${rem.userId}-${rem.reminderId}`)) + continue; - const usr = client.users.cache.find(u => u.id === rem.userId); + reminderCheckBuffer.add(`${rem.userId}-${rem.reminderId}`); - promises.push((async () => { - const reschedBtn = new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ"); + const usr = client.users.cache.find(u => u.id === rem.userId); - if(!usr) - return remindPublicly(rem); + promises.push((async () => { + const reschedBtn = new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ"); + // TODO - try - { - if(rem.private) { - const dm = await usr.createDM(); + if(!usr) + return remindPublicly(rem); - const msg = await dm.send({ embeds: [ getExpiredEbd(rem) ]}); + try + { + if(rem.private) { + const dm = await usr.createDM(); - if(!dm || !msg) - return remindPublicly(rem); - } - else remindPublicly(rem); + const msg = await dm.send({ embeds: [ getExpiredEbd(rem) ]}); - await deleteReminder(rem.reminderId, rem.userId); - this.reminderCheckBuffer.delete(`${rem.userId}-${rem.reminderId}`); - } - catch(err) - { - return remindPublicly(rem); + if(!dm || !msg) + return remindPublicly(rem); } - })()); - } + else remindPublicly(rem); - await Promise.allSettled(promises); + await deleteReminder(rem.reminderId, rem.userId); + reminderCheckBuffer.delete(`${rem.userId}-${rem.reminderId}`); + } + catch(err) + { + return remindPublicly(rem); + } + })()); } + + await Promise.allSettled(promises); } From 12cbb51c961b13e4747a9f684e6c12792faf8b63 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 21 Jan 2023 22:38:11 +0100 Subject: [PATCH 08/40] m --- src/Command.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Command.ts b/src/Command.ts index 9138237..6681485 100644 --- a/src/Command.ts +++ b/src/Command.ts @@ -40,7 +40,7 @@ export abstract class Command if(cmdMeta.desc.length > 100) throw new Error(`${k.yellow(`/${cmdMeta.name}`)}: Description can't be longer than 100 chars, got ${cmdMeta.desc.length}`); - if(Command.isCommandMeta(cmdMeta)) + if(!Command.isSubcommandMeta(cmdMeta)) { // top level command this.meta = { ...fallbackMeta, ...cmdMeta }; From cf610c24f02139c008f2e03050b50b41c950936c Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 21 Jan 2023 23:12:34 +0100 Subject: [PATCH 09/40] fix: joining guilds didn't register cmds (yikes) --- src/events/GuildJoined.ts | 2 +- src/registry.ts | 35 ++++++++++++++++++++++------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/events/GuildJoined.ts b/src/events/GuildJoined.ts index 6996617..129aa25 100644 --- a/src/events/GuildJoined.ts +++ b/src/events/GuildJoined.ts @@ -12,7 +12,7 @@ export class GuildJoined extends Event async run(guild: Guild) { - await registerGuildCommands(guild.id); + await registerGuildCommands(guild.id, true); // TODO: add logger lib here } diff --git a/src/registry.ts b/src/registry.ts index 3591cc9..47bde44 100644 --- a/src/registry.ts +++ b/src/registry.ts @@ -54,11 +54,17 @@ export function getCtxMenus() return ctxMenus; } -/** Registers all slash commands and context menus for multiple guilds */ -export async function registerGuildCommands(guildID: string[]): Promise -/** Registers all slash commands and context menus for one guild */ -export async function registerGuildCommands(guildID: string): Promise -export async function registerGuildCommands(...guildIDs: (string|string[])[]): Promise +/** + * (Re-)registers all slash commands and context menus for multiple guilds. + * Set `forceUpdate` to true to (re-)register commands even if their meta hash hasn't changed. + */ +export async function registerGuildCommands(guildID: string[], forceUpdate?: boolean): Promise +/** + * (Re-)registers all slash commands and context menus for one guild. + * Set `forceUpdate` to true to (re-)register commands even if their meta hash hasn't changed. + */ +export async function registerGuildCommands(guildID: string, forceUpdate?: boolean): Promise +export async function registerGuildCommands(guildIDs: (string|string[]), forceUpdate = false): Promise { if(!client) throw new Error("Registry isn't initialized yet!"); @@ -114,9 +120,9 @@ export async function registerGuildCommands(...guildIDs: (string|string[])[]): P // // console.log(`â€Ē Registered ${k.green(slashCmds.length)} global slash command${slashCmds.length != 1 ? "s" : ""}`); - if(commandsChanged) { + if(commandsChanged || forceUpdate) { const r = k.bold(k.bgYellow(k.black("â†ŧ "))); - console.log(`${r} ${k.underline("Command meta has changed, updating commands")} ${r}\n`); + !forceUpdate && console.log(`${r} ${k.underline("Command meta has changed, updating commands")} ${r}\n`); // register guild commands for await(const guild of guilds) { @@ -145,15 +151,18 @@ const cmdHashPath = ".command_hash"; /** Sets a new command hash by providing the JSON data */ async function updateCommandHash(cmds: RESTPostAPIApplicationCommandsJSONBody[]) { const curHash = await pathExists(cmdHashPath) - ? (await readFile(cmdHashPath)).toString() - : ""; - const newHash = createHash("SHA512") - .update(JSON.stringify(cmds)) - .digest("binary"); + ? await readFile(cmdHashPath) + : Buffer.alloc(0); + const newHash = Buffer.from( + createHash("SHA512") + .update(JSON.stringify(cmds)) + .digest("binary"), + "binary" + ); let commandsChanged = false; - if(newHash !== curHash) { + if(curHash.compare(newHash) !== 0) { await writeFile(cmdHashPath, newHash); commandsChanged = true; From 07ffff368311266082418a78fca97adb3d91a2db Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 21 Jan 2023 23:12:43 +0100 Subject: [PATCH 10/40] chore: update readme uwu --- README.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9763d48..f29b202 100644 --- a/README.md +++ b/README.md @@ -51,19 +51,26 @@ In order for a command or event to be initialized on startup, add it to the arra At the moment, `src/bot.ts` only sets guild-specific commands as these update pretty quickly (global commands take up to an hour to propagate). The regular Discord client doesn't update the locally saved slash commands when the bot restarts, so it's sometimes necessary to reload the Discord app with `Ctrl+R` If that still didn't work, or when you just want to remove a command or change its arguments, it's sometimes also necessary to delete them from Discord servers entirely. -The bot inserts a fresh copy of all commands at next startup. To clear all global commands and guild commands, use `npm run clearCommands` +To clear all global commands and guild commands, use `npm run clearCommands` + +All slash and context commands' meta objects are hashed to create a checksum at each startup that's saved to `.command_hash` in the project root. +Only if this hash changes will the commands be re-sent to the Discord API. This is to reduce startup time and prevent us from getting rate limited. +If you want to force your commands to be updated for whatever reason, delete or edit the `.command_hash` file and restart the bot (Note: it's invisible in VSC and Win Explorer by default).
### Context menu commands: There are two types of context menus; message and user. This dictates where they will be situated in the Discord client and what properties are passed. -Use `int.isUserContextMenu()` and `int.isMessageContextMenu()` to tell TS what type of context menu it's dealing with, then you will be able to access the `int.targetMessage` or `int.targetUser` and `int.targetMember` props. +Use an if-condition with `int.isUserContextMenu()` and `int.isMessageContextMenu()` to tell TS what type of context menu it's dealing with, then you will be able to access the `int.targetMessage` or `int.targetUser` and `int.targetMember` props. Other than how the commands are sent and that a user can't pass any arguments, context commands are pretty much the same as slash commands. To create a new context menu, use the Template.ts in `src/context/` to create a sub-class of `src/CtxMenu.ts` Make sure the file and class name are changed, and the meta object in the constructor is filled out. To specify who can use the context command, use the `memberPerms` meta prop. -Lastly, as with slash commands, add the class to the array in `src/context/index.ts` +Lastly, as with slash commands, add the class to the array in `src/context/index.ts` + +Just like the slash commands, the context commands will only be re-sent to the API, if their meta object changes. +For more info, read the [slash command section.](#slash-commands)
@@ -166,7 +173,7 @@ All messages can have:
-Interaction replies and MessageEmbeds (title, fields & description) can have: +Interaction replies and EmbedBuilders (title, fields & description) can have: - Hyperlinks (`[text](url)`)
@@ -220,7 +227,7 @@ Markdown that isn't allowed anywhere:
> ### PageEmbed -> This class is a wrapper for MessageEmbed that handles scrolling through multiple of them via MessageButtons. +> This class is a wrapper for EmbedBuilder that handles scrolling through multiple of them via MessageButtons. > It offers lots of configurability and dynamically changeable pages. > > #### Methods: From d4e9086516125631ce2259d9ed4ad453504f1b5d Mon Sep 17 00:00:00 2001 From: Sv443 Date: Mon, 30 Jan 2023 15:07:02 +0100 Subject: [PATCH 11/40] feat: delete below & including ctx command --- src/bot.ts | 2 +- src/context/DeleteBelow.ts | 100 +++++++++++++++++++++++++++++++++++ src/context/DeleteMessage.ts | 33 ------------ src/context/index.ts | 8 ++- src/types/index.d.ts | 5 +- 5 files changed, 109 insertions(+), 39 deletions(-) create mode 100644 src/context/DeleteBelow.ts delete mode 100644 src/context/DeleteMessage.ts diff --git a/src/bot.ts b/src/bot.ts index ffa68de..90be5d6 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -141,7 +141,7 @@ async function registerCommands(client: Client) throw new Error("No commands found to listen to"); console.log(`â€Ē Registered ${k.green(slashCmds.length)} slash ${autoPlural("command", slashCmds)}`); - printDbgItmList(cmds.map(c => c.meta.name)); + printDbgItmList(cmds.map(c => c.getFullCmdName(c.meta.name))); console.log(`â€Ē Registered ${k.green(ctxMenus.length)} context ${autoPlural("menu", ctxMenus)}`); printDbgItmList(ctxMenus.map(c => c.meta.name)); diff --git a/src/context/DeleteBelow.ts b/src/context/DeleteBelow.ts new file mode 100644 index 0000000..3527713 --- /dev/null +++ b/src/context/DeleteBelow.ts @@ -0,0 +1,100 @@ +import { CtxMenu } from "@src/CtxMenu"; +import { settings } from "@src/settings"; +import { BtnMsg, embedify, useEmbedify } from "@src/utils"; +import { ApplicationCommandType, PermissionFlagsBits } from "discord-api-types/v10"; +import { ButtonBuilder, ButtonStyle, Collection, ContextMenuCommandInteraction, GuildTextBasedChannel, Message } from "discord.js"; + + +export class DeleteBelow extends CtxMenu +{ + constructor() { + super({ + name: "Delete below and including", + type: ApplicationCommandType.Message, + memberPerms: [ PermissionFlagsBits.ManageMessages ], + }); + } + + async run(int: ContextMenuCommandInteraction) { + const err = (msg?: string) => int.reply({ + ...useEmbedify(`Couldn't delete the messages${msg ? `:\n${msg}` : " due to an error."}`, settings.embedColors.error), + ephemeral: true, + }); + + // this condition will never be true, it's just for TS to shut up + if(!int.isMessageContextMenuCommand()) + return; + + const msg = int.targetMessage; + + if(!msg.member || !msg.guild) + return err("This command can only be used in a server."); + + if(!msg.member.permissionsIn(msg.channel.id).has(PermissionFlagsBits.ManageMessages)) + return err("You don't have the permission to delete messages in this channel."); + + const { channel } = msg; + + let msgCount = 0; + + await int.deferReply({ ephemeral: true }); + + try { + const msgs = (await channel.messages.fetch({ after: msg.id })) + .reduce((acc, cur) => { + cur.deletable && acc.set(cur.id, cur); + return acc; + }, new Collection>()); + msgs.set(msg.id, msg); + + msgCount = msgs.size; + + const deleteMsgs = async () => await (channel as GuildTextBasedChannel).bulkDelete(msgs, true); + + if(msgCount < 5) { + deleteMsgs(); + return int.editReply(useEmbedify(`Successfully deleted ${msgCount > 1 ? `all ${msgCount} messages` : "the message"}`, settings.embedColors.success)); + } + + const sortedMsgs = msgs.sort((a, b) => a.createdTimestamp === b.createdTimestamp ? 0 : (a.createdTimestamp < b.createdTimestamp ? -1 : 1)); + + const firstMsgLink = sortedMsgs.at(0)!.url, + lastMsgLink = sortedMsgs.at(-1)!.url; + + const bm = new BtnMsg( + embedify(`Are you sure you want to delete ${msgCount} messages from [here](${firstMsgLink}) to [here](${lastMsgLink})?`), + [[ + new ButtonBuilder().setLabel("Delete").setStyle(ButtonStyle.Danger), + new ButtonBuilder().setLabel("Cancel").setStyle(ButtonStyle.Secondary), + ]], + { timeout: 60_000 }, + ); + + let replied = false; + + bm.on("press", async (btn, btnInt) => { + await btnInt.deferUpdate(); + if(btn.data.label === "Delete") { + deleteMsgs(); + replied = true; + bm.destroy(); + int.editReply({ ...bm.getReplyOpts(), ...useEmbedify(`Successfully deleted ${msgCount > 1 ? `all ${msgCount} messages` : "the message"}`, settings.embedColors.success) }); + } + else if(btn.data.label === "Cancel") { + replied = true; + bm.destroy(); + int.editReply({ ...bm.getReplyOpts(), ...useEmbedify("Canceled message deletion.", settings.embedColors.warning) }); + } + }); + + bm.on("destroy", () => !replied && int.editReply(bm.getReplyOpts())); + int.editReply(bm.getReplyOpts()); + } + catch(e) { + return err(); + } + + if(msgCount < 1) + return int.editReply(useEmbedify("No messages were deleted.", settings.embedColors.warning)); + } +} diff --git a/src/context/DeleteMessage.ts b/src/context/DeleteMessage.ts deleted file mode 100644 index 07bfd49..0000000 --- a/src/context/DeleteMessage.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { CtxMenu } from "@src/CtxMenu"; -import { settings } from "@src/settings"; -import { useEmbedify } from "@src/utils"; -import { ApplicationCommandType, PermissionFlagsBits } from "discord-api-types/v10"; -import { ContextMenuCommandInteraction, Message } from "discord.js"; - - -export class DeleteMessage extends CtxMenu -{ - constructor() - { - super({ - name: "Delete Message", - type: ApplicationCommandType.Message, - memberPerms: [ PermissionFlagsBits.ManageMessages ], - }); - } - - async run(int: ContextMenuCommandInteraction) - { - const err = () => int.reply({ ...useEmbedify("Can't delete this message", settings.embedColors.error), ephemeral: true }); - - if(!int.isMessageContextMenuCommand()) - return err(); - - if(int.targetMessage instanceof Message) - await int.targetMessage.delete(); - else - return err(); - - return int.reply({ ...useEmbedify("Deleted the message"), ephemeral: true }); - } -} diff --git a/src/context/index.ts b/src/context/index.ts index 6f6eb74..0ec1b8a 100644 --- a/src/context/index.ts +++ b/src/context/index.ts @@ -1,10 +1,14 @@ -// import { DeleteMessage } from "./DeleteMessage"; +import { DeleteBelow } from "./DeleteBelow"; +import { Emoji } from "./Emoji"; + import { ResetNickname } from "./ResetNickname"; + /** Every context menu in here will get registered when the bot starts up */ export const contextMenus = [ // message - // DeleteMessage, + DeleteBelow, + Emoji, // user ResetNickname, diff --git a/src/types/index.d.ts b/src/types/index.d.ts index b96711c..c5c618f 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -1,6 +1,5 @@ import { ClientEvents, ApplicationCommandOptionType, BufferResolvable, JSONEncodable, APIAttachment, Attachment, AttachmentBuilder, AttachmentPayload, CommandInteraction, ButtonInteraction, ModalSubmitInteraction, ContextMenuCommandInteraction } from "discord.js"; import { PermissionFlagsBits } from "discord-api-types/v10"; -import { ContextMenuCommandType } from "@discordjs/builders"; import { Stream } from "node:stream"; //#MARKER commands @@ -139,8 +138,8 @@ export type EventName = keyof ClientEvents; export interface CtxMeta { name: string; - /** Accepts `User` or `Message` of `ApplicationCommandType` enum from `discord-api-types/v10` */ - type: ContextMenuCommandType; + /** Whether this context menu is attached to a user profile (or mention) or a message */ + type: ApplicationCommandType.User | ApplicationCommandType.Message; /** Default member permissions needed to use this context menu */ memberPerms?: PermissionFlagsBits[]; } From a729b6090f23c3b8a1a56b25895966300074a8b2 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Mon, 30 Jan 2023 15:10:25 +0100 Subject: [PATCH 12/40] fix: delete below stuff --- src/context/DeleteBelow.ts | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/context/DeleteBelow.ts b/src/context/DeleteBelow.ts index 3527713..addf1e4 100644 --- a/src/context/DeleteBelow.ts +++ b/src/context/DeleteBelow.ts @@ -1,6 +1,6 @@ import { CtxMenu } from "@src/CtxMenu"; import { settings } from "@src/settings"; -import { BtnMsg, embedify, useEmbedify } from "@src/utils"; +import { autoPlural, BtnMsg, embedify, useEmbedify } from "@src/utils"; import { ApplicationCommandType, PermissionFlagsBits } from "discord-api-types/v10"; import { ButtonBuilder, ButtonStyle, Collection, ContextMenuCommandInteraction, GuildTextBasedChannel, Message } from "discord.js"; @@ -49,20 +49,13 @@ export class DeleteBelow extends CtxMenu msgCount = msgs.size; - const deleteMsgs = async () => await (channel as GuildTextBasedChannel).bulkDelete(msgs, true); - - if(msgCount < 5) { - deleteMsgs(); - return int.editReply(useEmbedify(`Successfully deleted ${msgCount > 1 ? `all ${msgCount} messages` : "the message"}`, settings.embedColors.success)); - } - const sortedMsgs = msgs.sort((a, b) => a.createdTimestamp === b.createdTimestamp ? 0 : (a.createdTimestamp < b.createdTimestamp ? -1 : 1)); const firstMsgLink = sortedMsgs.at(0)!.url, lastMsgLink = sortedMsgs.at(-1)!.url; const bm = new BtnMsg( - embedify(`Are you sure you want to delete ${msgCount} messages from [here](${firstMsgLink}) to [here](${lastMsgLink})?`), + embedify(`Are you sure you want to delete ${msgCount} ${autoPlural("message", msgCount)} from [here](${firstMsgLink}) to [here](${lastMsgLink})?`), [[ new ButtonBuilder().setLabel("Delete").setStyle(ButtonStyle.Danger), new ButtonBuilder().setLabel("Cancel").setStyle(ButtonStyle.Secondary), @@ -75,7 +68,7 @@ export class DeleteBelow extends CtxMenu bm.on("press", async (btn, btnInt) => { await btnInt.deferUpdate(); if(btn.data.label === "Delete") { - deleteMsgs(); + await (channel as GuildTextBasedChannel).bulkDelete(msgs, true); replied = true; bm.destroy(); int.editReply({ ...bm.getReplyOpts(), ...useEmbedify(`Successfully deleted ${msgCount > 1 ? `all ${msgCount} messages` : "the message"}`, settings.embedColors.success) }); From 8770a8834ced5190aa7a1b4fe41da52f8fdba4d8 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Mon, 30 Jan 2023 15:21:32 +0100 Subject: [PATCH 13/40] fix: delete below: diff text for 1 and n case --- src/context/DeleteBelow.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/context/DeleteBelow.ts b/src/context/DeleteBelow.ts index addf1e4..00e256f 100644 --- a/src/context/DeleteBelow.ts +++ b/src/context/DeleteBelow.ts @@ -1,6 +1,6 @@ import { CtxMenu } from "@src/CtxMenu"; import { settings } from "@src/settings"; -import { autoPlural, BtnMsg, embedify, useEmbedify } from "@src/utils"; +import { BtnMsg, embedify, useEmbedify } from "@src/utils"; import { ApplicationCommandType, PermissionFlagsBits } from "discord-api-types/v10"; import { ButtonBuilder, ButtonStyle, Collection, ContextMenuCommandInteraction, GuildTextBasedChannel, Message } from "discord.js"; @@ -55,7 +55,10 @@ export class DeleteBelow extends CtxMenu lastMsgLink = sortedMsgs.at(-1)!.url; const bm = new BtnMsg( - embedify(`Are you sure you want to delete ${msgCount} ${autoPlural("message", msgCount)} from [here](${firstMsgLink}) to [here](${lastMsgLink})?`), + embedify(msgCount > 1 + ? `Are you sure you want to delete ${msgCount} messages from [here](${firstMsgLink}) to [here](${lastMsgLink})?` + : `Are you sure you want to delete [this message](${firstMsgLink})?` + ), [[ new ButtonBuilder().setLabel("Delete").setStyle(ButtonStyle.Danger), new ButtonBuilder().setLabel("Cancel").setStyle(ButtonStyle.Secondary), From e2c130942fe912e1a0e6fbe80038d3246642d4a1 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Mon, 30 Jan 2023 15:23:58 +0100 Subject: [PATCH 14/40] feat: emoji ctx menu --- src/commands/util/Emoji.ts | 1 + src/context/Emoji.ts | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/context/Emoji.ts diff --git a/src/commands/util/Emoji.ts b/src/commands/util/Emoji.ts index 58e1b10..6d8cd9d 100644 --- a/src/commands/util/Emoji.ts +++ b/src/commands/util/Emoji.ts @@ -30,6 +30,7 @@ export class Emoji extends Command const emoji = int.options.get("emoji", true).value as string; // TODO: make this URL auto download the image somehow + // solution: if the response header `Content-Type` is set to `application/octet-stream` all browsers instantly download the image const getEmUrl = (id: string, fmt: string) => `https://cdn.discordapp.com/emojis/${id}.${fmt}?size=4096&quality=lossless`; const trimmed = (str: string) => str.length > 24 ? str.substring(0, 24) + "+" : str; diff --git a/src/context/Emoji.ts b/src/context/Emoji.ts new file mode 100644 index 0000000..6f026c7 --- /dev/null +++ b/src/context/Emoji.ts @@ -0,0 +1,20 @@ +import { CtxMenu } from "@src/CtxMenu"; +import { ApplicationCommandType } from "discord-api-types/v10"; +import { ContextMenuCommandInteraction } from "discord.js"; + +export class Emoji extends CtxMenu { + constructor() { + super({ + name: "template", + type: ApplicationCommandType.User, + }); + } + + async run(int: ContextMenuCommandInteraction) { + // this condition will never be true, it's just for TS to shut up + if(!int.isMessageContextMenuCommand()) + return; + + + } +} From 408153cf2055a125391db8d605fbb175e0b4ee1f Mon Sep 17 00:00:00 2001 From: Sv443 Date: Mon, 30 Jan 2023 15:38:08 +0100 Subject: [PATCH 15/40] fix: deletebelow interaction already replied --- src/context/DeleteBelow.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/context/DeleteBelow.ts b/src/context/DeleteBelow.ts index 00e256f..73b5cb7 100644 --- a/src/context/DeleteBelow.ts +++ b/src/context/DeleteBelow.ts @@ -16,10 +16,13 @@ export class DeleteBelow extends CtxMenu } async run(int: ContextMenuCommandInteraction) { - const err = (msg?: string) => int.reply({ - ...useEmbedify(`Couldn't delete the messages${msg ? `:\n${msg}` : " due to an error."}`, settings.embedColors.error), - ephemeral: true, - }); + const err = (msg?: string) => { + const ebdOpts = useEmbedify(`Couldn't delete the messages${msg ? `:\n${msg}` : " due to an error."}`, settings.embedColors.error); + if(int.deferred || int.replied) + int.editReply(ebdOpts); + else + int.reply({ ...ebdOpts, ephemeral: true }); + }; // this condition will never be true, it's just for TS to shut up if(!int.isMessageContextMenuCommand()) From cc01ff3e332cc9c49c606ec6d82343d6bf79bb42 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Mon, 30 Jan 2023 22:56:11 +0100 Subject: [PATCH 16/40] chore: add new readme, move old one --- README.md | 338 ++++++++++++++---------------------------------------- 1 file changed, 89 insertions(+), 249 deletions(-) diff --git a/README.md b/README.md index f29b202..c6120f7 100644 --- a/README.md +++ b/README.md @@ -1,266 +1,106 @@ -# Brew Bot -![Node CI](https://github.com/codedrunks/BrewBot/workflows/Node%20CI/badge.svg) - -## Table of contents -- [Installation](#installation) -- [Development](#development) - - [Project structure](#project-structure) - - [Slash commands](#slash-commands) - - [Context menu commands](#context-menu-commands) - - [Other](#other) -- [CLI](#cli) - - [General](#general) - - [Prisma](#prisma) -- [Debugging](#debugging) -- [Redis](#redis) -- [Discord API quirks](#discord-api-quirks) - - [Markdown reference](#markdown-reference) - - [Length limits](#length-limits) -- [Classes](#classes) - - [BtnMsg](#btnmsg) - - [PageEmbed](#pageembed) - - [Modal](#modal) - -

- -### Invite URL -https://discord.com/oauth2/authorize?client_id=962824817038471178&permissions=8&scope=bot%20applications.commands - -
- -## Installation: -1. Install Node.js (v16.9+), npm (v8+) and Postgres -2. Install GTK2 and libjpeg-turbo by following [this guide](https://github.com/Automattic/node-canvas/wiki/Installation:-Windows#2-installing-gtk-2) -3. [Install Redis](#redis) -4. Set up a psql user and DB schema for the bot -5. Run `npm i` to install dependencies -6. Run `npx prisma migrate reset` to initialize the DB schema -7. Copy `.env.template` to `.env` and enter all values -8. See [CLI](#cli) for further commands - -
- -## Development: -### Project structure: -Commands, events and context menus have template files in their respective folders called `Template.ts`, use these to create new commands and events. -In order for a command or event to be initialized on startup, add it to the array of the `index.ts` file in the respective folder. - -
- -### Slash commands: -At the moment, `src/bot.ts` only sets guild-specific commands as these update pretty quickly (global commands take up to an hour to propagate). -The regular Discord client doesn't update the locally saved slash commands when the bot restarts, so it's sometimes necessary to reload the Discord app with `Ctrl+R` -If that still didn't work, or when you just want to remove a command or change its arguments, it's sometimes also necessary to delete them from Discord servers entirely. -To clear all global commands and guild commands, use `npm run clearCommands` - -All slash and context commands' meta objects are hashed to create a checksum at each startup that's saved to `.command_hash` in the project root. -Only if this hash changes will the commands be re-sent to the Discord API. This is to reduce startup time and prevent us from getting rate limited. -If you want to force your commands to be updated for whatever reason, delete or edit the `.command_hash` file and restart the bot (Note: it's invisible in VSC and Win Explorer by default). - -
- -### Context menu commands: -There are two types of context menus; message and user. This dictates where they will be situated in the Discord client and what properties are passed. -Use an if-condition with `int.isUserContextMenu()` and `int.isMessageContextMenu()` to tell TS what type of context menu it's dealing with, then you will be able to access the `int.targetMessage` or `int.targetUser` and `int.targetMember` props. -Other than how the commands are sent and that a user can't pass any arguments, context commands are pretty much the same as slash commands. - -To create a new context menu, use the Template.ts in `src/context/` to create a sub-class of `src/CtxMenu.ts` -Make sure the file and class name are changed, and the meta object in the constructor is filled out. -To specify who can use the context command, use the `memberPerms` meta prop. -Lastly, as with slash commands, add the class to the array in `src/context/index.ts` - -Just like the slash commands, the context commands will only be re-sent to the API, if their meta object changes. -For more info, read the [slash command section.](#slash-commands) - -
- -### Other: -Install these VS Code extensions for code auto-fix on save and special text highlighting: -- `dbaeumer.vscode-eslint` -- `fabiospampinato.vscode-highlight` - -
- -### Data persistence: -A mixture of Prisma with a Postgres database, and Redis is used. -All database utils can be found in `/src/database`, the functions are organized in files based on what part of the database they are associated with, i.e. all user related functions such as creating a new user or deleting a user are in `/src/database/users.ts`. When creating new utils, please follow this standard accordingly. - -See prisma docs [here](https://www.prisma.io/docs/) and a reference to the node client library [here.](https://www.prisma.io/docs/reference) - -### Redis: -Redis is an in-memory cache to keep highly accessed values in a place that is fast to access and update. -Setting up redis is easy for your distro of linux and if you are developing on Windows, can be installed through WSL, see docs for installation [here.](https://redis.io/docs/getting-started/installation/) - -Launching redis is as simple as running `redis-server`. - -When launching to production, you want redis to be daemonized, this can be done with systemd[^1] by default on most linux distributions using `sudo systemctl start redis` and `sudo systemctl enable redis` to enable launch on reboot, or you can do that with something like [pm2](https://pm2.keymetrics.io/) or [screen](https://linuxize.com/post/how-to-use-linux-screen/) or Windows Task Scheduler (see below), but can also be done manually with some configuration, see details [here.](https://redis.io/docs/getting-started/) +# BrewBot +The only Discord bot you'll ever need. +BrewBot is your essential server companion with extensive moderation tools, fun games, an art contest system and various utility commands. -[^1]: If you are using systemd, create a `redis.conf` in `/etc/redis/redis.conf` and make sure to add the line `supervised systemd`. - -In our specific application, your redis-server must be running on `127.0.0.1:6379` which is the default for redis-server, and if you are on windows, make sure to add the line `localhostForwarding=true` to your .wslconfig located in `%UserProfile%\.wslconfig`, if this file does not exist, please create one and be sure to add the header `[wsl2]` or `[wsl1]`. Also if you are on windows, be aware that WSL does not keep applications alive without a bash terminal running, so do not close the WSL window while developing. - -Another thing is to have a config for your instance of Redis, in testing/development you can do something like this to have an instance that does not save to disk. On WSL, you must do this because redis will not have write permissions to save to disk. -```sh -cd ~ -mkdir redis -cd redis -touch redis.conf -redis-server redis.conf # run this in a separate window -redis-cli config set save "" -redis-cli config rewrite -``` - -After it was installed on the default WSL shell, if you want Redis to automatically launch on Windows startup, you can use Task Scheduler. -Create a new task (not basic task) in Task Scheduler that runs `src/tools/redis.bat` whenever your user logs on, [see guide.](https://winaero.com/run-app-or-script-at-logon-with-task-scheduler-in-windows-10/#How_to_Run_App_or_Script_at_Logon_with_Task_Scheduler_in_Windows_10) -Then, right-click the finished task and click "Run" to test it. - -
- -## CLI -Run `npm link` to globally register the `brewbot` command, which you can use for some special commands. -See `brewbot -h` for help. - -
- -### General -| Command | Description | -| --- | --- | -| `npm start` | start the bot regularly | -| `npm run watch` | start the bot and watch for file changes to recompile automatically | -| `npm run lint` | lints the code with eslint | -| `npm test` | runs the script at `src/test.ts` | -| `npm run clearCommands` | clears all global and guild commands (takes a few minutes) | -| `npm run deploy` | runs prisma deployment scripts and launches the bot without watching | -| `npm run predeploy` | only runs prisma deployment scripts without launching the bot | -| `npm run win-redis` | use this command on Windows devices to launch redis-server in a WSL window | - -
- -### Prisma -| Command | Description | -| --- | --- | -| `npx prisma db push` | this will update your local db to reflect any changes in your schema.prisma file, use this while making changes that you want to see | -| `npx prisma migrate dev --name "describe_change_short"` | creates a database migration and updates the local database if there is one, use this once your changes to the schema.prisma file are done, do not use constantly for little changes, use the above command instead | -| `npx prisma migrate deploy` | this will deploy any changes to the local database, this is how you deploy migrations in production | -| `npx prisma migrate reset` | this will reset the localdatabase and re-apply any migrations, use this in testing if you make breaking changes or need a reset | -| `npx prisma migrate dev --create-only` | not usually needed, this will create a migration without applying it incase you need to manually change the SQL in the migration file | -| `npx prisma format` | this formats the schema.prisma file and can also auto-complete foreign key association | -| `npx prisma db seed` | this command seeds the database according to `prisma/seed.ts` | - -
+This bot is still WIP. Please check back in a while :) -## Debugging -Debugging through VS Code works just fine, including breakpoints. -Select "Launch" in the debugger pane, then press F5 to launch the debugger. -Select the "test.ts" profile to debug the script at `src/test.ts` +
-## Discord API quirks -- (Sub)Command names and command option names need to be lowercase only with no spaces (underscores are fine). -- If you get **ANY** discord api related error then any changes that have been made to commands won't be registered until the error is fixed. +## Invite link: +Coming soon
-### Markdown reference -Discord has multiple subsets of markdown, depending on the type of message. -They can be combined, but monospace and code blocks need to be on the innermost "layer". - -All messages can have: -- Bold (`**text**`), italic (`*text*`), underline (`__text__`), strikethrough (`~~text~~`) -- Monospace (\`text\`), code blocks (\`\`\`text\`\`\`) -- Quotes (`> text`), multiline quotes (`>>> text`) - -
- -Interaction replies and EmbedBuilders (title, fields & description) can have: -- Hyperlinks (`[text](url)`) +## Feature overview: +- [contests with user submissions & voting](#contests) +- [singleplayer & multiplayer games](#games) + - chess + - sudoku + - 2048 + - tic tac toe +- [economy](#economy) + - jobs +- [moderation tools](#moderation-tools) + - warning system + - reaction roles + - message logs +- [various utilities](#various-utilities) + - set reminders + - translate text + - get a word's definition + - let the bot tell you a joke + - get detailed info about a steam profile
-Markdown that isn't allowed anywhere: -- Tables -- HTML mixins (`
` etc) - -

- -### Length limits -| What | Limit | -| --- | --- | -| username | 1-80 chars | -| message content | 2000 chars | -| files per message | 10 files | -| embeds per message | 10 embeds | -| embed title | 256 chars | -| embed description | 2048 chars | -| embed author name | 256 chars | -| embed fields | 25 fields | -| embed field name | 256 chars | -| embed field value | 1024 chars | -| embed footer text | 2048 chars | -| sum of all chars in embed | 6000 chars | -| slash command description | 100 chars | -| slash command arg description | 100 chars | - +## Features (detailed): -

- -## Classes - -> ### BtnMsg -> To use the new message buttons, this class handles the communication between the `bot.ts` event listener and the slash command's scope. -> -> For the `buttons` constructor param, **don't set a `customId`** as the registry assigns own IDs automatically. -> -> #### Methods: -> - `destroy()` emits the `destroy` event, removes all event listeners and tells the registry to deregister this BtnMsg -> - `getReplyOpts()` returns properties that can be spread onto an interaction reply like `int.reply({ ...btmsg.getReplyOpts(), foo: "bar" })` -> - `getMsgOpts()` same as `getReplyOpts()` but for sending a message with `channel.send()` -> - `sendIn()` sends this BtnMsg in the provided channel -> -> #### Events: -> Use `BtnMsg.on("name", (args) => {})` to subscribe to them -> - `press` is emitted whenever the button is pressed by a user and gets passed the MessageButton and ButtonInteraction instances -> - `timeout` is emitted when the timeout of the BtnMsg, set in the settings object, is reached. After the timeout, the `.destroy()` method is automatically called -> - `destroy` is emitted whenever the `.destroy()` method is called and it prompts the registry to deregister this BtnMsg instance. It gets passed an array of `MessageButton.customId`'s. After this event is emitted, all previously registered event listeners will be removed and will never receive evetns again. +### Contests: +> After configuring and starting a contest with `/contest start`, users can submit any file to it with `/contest submit` +> As soon as the defined submission period ends, users can vote for submissions with `/contest vote` +> After the voting period ends, the winner will be announced in the channel set with `/contest set_channel` +> Run `/contest set_role` to set a role that will be pinged with contest updates. +> Use `/contest current` or `/contest list` to view the currently active or all contests for the current server.
-> ### PageEmbed -> This class is a wrapper for EmbedBuilder that handles scrolling through multiple of them via MessageButtons. -> It offers lots of configurability and dynamically changeable pages. -> -> #### Methods: -> - `sendIn()` sends this PageEmbed in the provided channel. If you want a custom message implementation, use `setMsg()` and `getMsg()` -> - `useInt()` instead replies to or edits a Command-/ButtonInteraction -> - `getMsgOpts()` returns properties that can be passed to a `channel.send()` or `(msg | int).reply()` method -> - `setPages()` is for dynamically changing the pages of the instance. If the current page index is out of range after the pages have changed, it gets lowered automatically. -> - `first()`, `prev()`, `next()` and `last()` can be used just like the users use the MessageButtons to navigate the PageEmbed. -> - `destroy()` edits the message to remove the buttons, emits the `destroy` event, removes all event listeners and deregisters the buttons -> - `updateMsg()` can be called to update the message on the Discord API with what's currently stored in the PageEmbed. -> - `setAllowAllUsers()` allows setting whether users other than the author can interact with the buttons -> - `askGoToPage()` opens a prompt in a channel to type the new page number to navigate to. -> -> #### Events: -> Use `PageEmbed.on("name", (args) => {})` to subscribe to them -> - `press` is emitted whenever a button is pressed by a user and gets passed the ButtonInteraction instance and a string telling you which button was pressed. -> - `timeout` is emitted when the timeout of the PageEmbed, set in the settings object, is reached. After the timeout, the `.destroy()` method is automatically called. -> - `destroy` is emitted whenever the `.destroy()` method is called. -> - `update` is emitted after the associated message or interaction on the Discord API has been edited. - -
- -> ### Modal -> The modal is a configurable form dialog that gets shown to a user. -> Modals only work in the desktop client, not the mobile app. -> -> This is an abstract class, so you need to create a sub-class extending `Modal` +### Games: +> BrewBot has a few singleplayer and multiplayer games you can play in the chat. +> Singleplayer games: +> - 2048 - `/2048 start` +> - Higher Lower - `/higherlower` +> - Slots (one-armed bandit) - `/slots` +> - Sudoku puzzle - `/sudoku start` > -> #### Methods: -> - `submit()` is executed when the user submitted the modal - this method needs to be overridden in a sub-class -> - `getInternalModal()` returns the modal object that needs to be passed to an interaction's `showModal()` method +> Multiplayer games: +> - Chess - `/chess start` > -> #### Events: -> - `destroy` gets emitted when `.destroy()` is called to trigger the registry to delete this instance - -
+> Multiplayer / AI Opponent games: +> - Tic Tac Toe - `/tictactoe start` + +
+ +### Economy: +> You can sign up for a job with `/job` and work once every 4 hours with `/work` to earn coins. +> Every 24 hours you can also run `/daily` for a daily bonus. +> If you work enough times, you will be promoted to a job that offers better salary. +> Once you have enough coins, you can bet them on the slots game with `/slots bet:` +> Coins and job timers are unique per server and cannot be transferred between accounts or servers. + +
+ +### Moderation tools: +> - Warning system: +> A moderator with the "manage members" permission can warn a member with the `/warning add` command. +> After a set threshold of warnings has passed, a message will be sent in a mod channel to suggest banning the account. +> Both of these can be configured in the [dashboard.](#TODO) +> - Reaction roles: +> TODO +> - Message logs: +> You can use `/log` to log the last n messages in the current channel to another channel. +> This is for keeping an evidence log and to capture the messages as they currently are, no matter if any are edited. + +
+ +### Various utilities: +> - Set reminders +> There are multiple ways of creating a reminder: +> - Start a timer from now by entering the delay with `/reminder set_timer` +> - Set the reminder by providing a date and time in UTC with `/reminder set_date` +> - Start a reminder that expires today by providing just the time in UTC with `/reminder set_time` +> List your reminders with `/reminder list` and delete them with `/reminder delete` +> - Translate text +> Translate any text to any language with the `/translate` command. +> The argument `input_language` will help if the text is too short and the language auto-detection fails. +> - Get a word's definition +> The `/define` command can tell you the definition of a term from multiple sources using the `engine` argument. +> The available sources are: Wikipedia, Urban Dictionary and a regular dictionary. +> - Let the bot tell you a joke +> Run `/joke` to let the bot tell you one or more jokes. +> - Get detailed info about a Steam profile +> With `/steam info` you can look up the summary of a user's profile. +> `/steam games` shows a sortable list of games that a user owns and their playtime. +> Note that the `username` argument takes in the user's vanity URL which may be different from their current username or even nonexistent. +> They also might have a private profile in which case either none or limited information is shown. From 8e42285e733c676061ba007d0cbca3595d54d4d4 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Mon, 30 Jan 2023 22:56:24 +0100 Subject: [PATCH 17/40] why u not commit --- src/README.md | 266 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 src/README.md diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..9aae74f --- /dev/null +++ b/src/README.md @@ -0,0 +1,266 @@ +# BrewBot Documentation +![Node CI](https://github.com/codedrunks/BrewBot/workflows/Node%20CI/badge.svg) + +## Table of contents +- [Installation](#installation) +- [Development](#development) + - [Project structure](#project-structure) + - [Slash commands](#slash-commands) + - [Context menu commands](#context-menu-commands) + - [Other](#other) +- [CLI](#cli) + - [General](#general) + - [Prisma](#prisma) +- [Debugging](#debugging) +- [Redis](#redis) +- [Discord API quirks](#discord-api-quirks) + - [Markdown reference](#markdown-reference) + - [Length limits](#length-limits) +- [Classes](#classes) + - [BtnMsg](#btnmsg) + - [PageEmbed](#pageembed) + - [Modal](#modal) + +

+ +### Invite URL +https://discord.com/oauth2/authorize?client_id=962824817038471178&permissions=8&scope=bot%20applications.commands + +
+ +## Installation: +1. Install Node.js (v16.9+), npm (v8+) and Postgres +2. Install GTK2 and libjpeg-turbo by following [this guide](https://github.com/Automattic/node-canvas/wiki/Installation:-Windows#2-installing-gtk-2) +3. [Install Redis](#redis) +4. Set up a psql user and DB schema for the bot +5. Run `npm i` to install dependencies +6. Run `npx prisma migrate reset` to initialize the DB schema +7. Copy `.env.template` to `.env` and enter all values +8. See [CLI](#cli) for further commands + +
+ +## Development: +### Project structure: +Commands, events and context menus have template files in their respective folders called `Template.ts`, use these to create new commands and events. +In order for a command or event to be initialized on startup, add it to the array of the `index.ts` file in the respective folder. + +
+ +### Slash commands: +At the moment, `src/bot.ts` only sets guild-specific commands as these update pretty quickly (global commands take up to an hour to propagate). +The regular Discord client doesn't update the locally saved slash commands when the bot restarts, so it's sometimes necessary to reload the Discord app with `Ctrl+R` +If that still didn't work, or when you just want to remove a command or change its arguments, it's sometimes also necessary to delete them from Discord servers entirely. +To clear all global commands and guild commands, use `npm run clearCommands` + +All slash and context commands' meta objects are hashed to create a checksum at each startup that's saved to `.command_hash` in the project root. +Only if this hash changes will the commands be re-sent to the Discord API. This is to reduce startup time and prevent us from getting rate limited. +If you want to force your commands to be updated for whatever reason, delete or edit the `.command_hash` file and restart the bot (Note: it's invisible in VSC and Win Explorer by default). + +
+ +### Context menu commands: +There are two types of context menus; message and user. This dictates where they will be situated in the Discord client and what properties are passed. +Use an if-condition with `int.isUserContextMenu()` and `int.isMessageContextMenu()` to tell TS what type of context menu it's dealing with, then you will be able to access the `int.targetMessage` or `int.targetUser` and `int.targetMember` props. +Other than how the commands are sent and that a user can't pass any arguments, context commands are pretty much the same as slash commands. + +To create a new context menu, use the Template.ts in `src/context/` to create a sub-class of `src/CtxMenu.ts` +Make sure the file and class name are changed, and the meta object in the constructor is filled out. +To specify who can use the context command, use the `memberPerms` meta prop. +Lastly, as with slash commands, add the class to the array in `src/context/index.ts` + +Just like the slash commands, the context commands will only be re-sent to the API, if their meta object changes. +For more info, read the [slash command section.](#slash-commands) + +
+ +### Other: +Install these VS Code extensions for code auto-fix on save and special text highlighting: +- `dbaeumer.vscode-eslint` +- `fabiospampinato.vscode-highlight` + +
+ +### Data persistence: +A mixture of Prisma with a Postgres database, and Redis is used. +All database utils can be found in `/src/database`, the functions are organized in files based on what part of the database they are associated with, i.e. all user related functions such as creating a new user or deleting a user are in `/src/database/users.ts`. When creating new utils, please follow this standard accordingly. + +See prisma docs [here](https://www.prisma.io/docs/) and a reference to the node client library [here.](https://www.prisma.io/docs/reference) + +### Redis: +Redis is an in-memory cache to keep highly accessed values in a place that is fast to access and update. +Setting up redis is easy for your distro of linux and if you are developing on Windows, can be installed through WSL, see docs for installation [here.](https://redis.io/docs/getting-started/installation/) + +Launching redis is as simple as running `redis-server`. + +When launching to production, you want redis to be daemonized, this can be done with systemd[^1] by default on most linux distributions using `sudo systemctl start redis` and `sudo systemctl enable redis` to enable launch on reboot, or you can do that with something like [pm2](https://pm2.keymetrics.io/) or [screen](https://linuxize.com/post/how-to-use-linux-screen/) or Windows Task Scheduler (see below), but can also be done manually with some configuration, see details [here.](https://redis.io/docs/getting-started/) + +[^1]: If you are using systemd, create a `redis.conf` in `/etc/redis/redis.conf` and make sure to add the line `supervised systemd`. + +In our specific application, your redis-server must be running on `127.0.0.1:6379` which is the default for redis-server, and if you are on windows, make sure to add the line `localhostForwarding=true` to your .wslconfig located in `%UserProfile%\.wslconfig`, if this file does not exist, please create one and be sure to add the header `[wsl2]` or `[wsl1]`. Also if you are on windows, be aware that WSL does not keep applications alive without a bash terminal running, so do not close the WSL window while developing. + +Another thing is to have a config for your instance of Redis, in testing/development you can do something like this to have an instance that does not save to disk. On WSL, you must do this because redis will not have write permissions to save to disk. +```sh +cd ~ +mkdir redis +cd redis +touch redis.conf +redis-server redis.conf # run this in a separate window +redis-cli config set save "" +redis-cli config rewrite +``` + +After it was installed on the default WSL shell, if you want Redis to automatically launch on Windows startup, you can use Task Scheduler. +Create a new task (not basic task) in Task Scheduler that runs `src/tools/redis.bat` whenever your user logs on, [see guide.](https://winaero.com/run-app-or-script-at-logon-with-task-scheduler-in-windows-10/#How_to_Run_App_or_Script_at_Logon_with_Task_Scheduler_in_Windows_10) +Then, right-click the finished task and click "Run" to test it. + +
+ +## CLI +Run `npm link` to globally register the `brewbot` command, which you can use for some special commands. +See `brewbot -h` for help. + +
+ +### General +| Command | Description | +| --- | --- | +| `npm start` | start the bot regularly | +| `npm run watch` | start the bot and watch for file changes to recompile automatically | +| `npm run lint` | lints the code with eslint | +| `npm test` | runs the script at `src/test.ts` | +| `npm run clearCommands` | clears all global and guild commands (takes a few minutes) | +| `npm run deploy` | runs prisma deployment scripts and launches the bot without watching | +| `npm run predeploy` | only runs prisma deployment scripts without launching the bot | +| `npm run win-redis` | use this command on Windows devices to launch redis-server in a WSL window | + +
+ +### Prisma +| Command | Description | +| --- | --- | +| `npx prisma db push` | this will update your local db to reflect any changes in your schema.prisma file, use this while making changes that you want to see | +| `npx prisma migrate dev --name "describe_change_short"` | creates a database migration and updates the local database if there is one, use this once your changes to the schema.prisma file are done, do not use constantly for little changes, use the above command instead | +| `npx prisma migrate deploy` | this will deploy any changes to the local database, this is how you deploy migrations in production | +| `npx prisma migrate reset` | this will reset the localdatabase and re-apply any migrations, use this in testing if you make breaking changes or need a reset | +| `npx prisma migrate dev --create-only` | not usually needed, this will create a migration without applying it incase you need to manually change the SQL in the migration file | +| `npx prisma format` | this formats the schema.prisma file and can also auto-complete foreign key association | +| `npx prisma db seed` | this command seeds the database according to `prisma/seed.ts` | + +
+ +## Debugging +Debugging through VS Code works just fine, including breakpoints. +Select "Launch" in the debugger pane, then press F5 to launch the debugger. +Select the "test.ts" profile to debug the script at `src/test.ts` + +
+ +## Discord API quirks +- (Sub)Command names and command option names need to be lowercase only with no spaces (underscores are fine). +- If you get **ANY** discord api related error then any changes that have been made to commands won't be registered until the error is fixed. + +
+ +### Markdown reference +Discord has multiple subsets of markdown, depending on the type of message. +They can be combined, but monospace and code blocks need to be on the innermost "layer". + +All messages can have: +- Bold (`**text**`), italic (`*text*`), underline (`__text__`), strikethrough (`~~text~~`) +- Monospace (\`text\`), code blocks (\`\`\`text\`\`\`) +- Quotes (`> text`), multiline quotes (`>>> text`) + +
+ +Interaction replies and EmbedBuilders (title, fields & description) can have: +- Hyperlinks (`[text](url)`) + +
+ +Markdown that isn't allowed anywhere: +- Tables +- HTML mixins (`
` etc) + +

+ +### Length limits +| What | Limit | +| --- | --- | +| username | 1-80 chars | +| message content | 2000 chars | +| files per message | 10 files | +| embeds per message | 10 embeds | +| embed title | 256 chars | +| embed description | 2048 chars | +| embed author name | 256 chars | +| embed fields | 25 fields | +| embed field name | 256 chars | +| embed field value | 1024 chars | +| embed footer text | 2048 chars | +| sum of all chars in embed | 6000 chars | +| slash command description | 100 chars | +| slash command arg description | 100 chars | + + +

+ +## Classes + +> ### BtnMsg +> To use the new message buttons, this class handles the communication between the `bot.ts` event listener and the slash command's scope. +> +> For the `buttons` constructor param, **don't set a `customId`** as the registry assigns own IDs automatically. +> +> #### Methods: +> - `destroy()` emits the `destroy` event, removes all event listeners and tells the registry to deregister this BtnMsg +> - `getReplyOpts()` returns properties that can be spread onto an interaction reply like `int.reply({ ...btmsg.getReplyOpts(), foo: "bar" })` +> - `getMsgOpts()` same as `getReplyOpts()` but for sending a message with `channel.send()` +> - `sendIn()` sends this BtnMsg in the provided channel +> +> #### Events: +> Use `BtnMsg.on("name", (args) => {})` to subscribe to them +> - `press` is emitted whenever the button is pressed by a user and gets passed the MessageButton and ButtonInteraction instances +> - `timeout` is emitted when the timeout of the BtnMsg, set in the settings object, is reached. After the timeout, the `.destroy()` method is automatically called +> - `destroy` is emitted whenever the `.destroy()` method is called and it prompts the registry to deregister this BtnMsg instance. It gets passed an array of `MessageButton.customId`'s. After this event is emitted, all previously registered event listeners will be removed and will never receive evetns again. + +
+ +> ### PageEmbed +> This class is a wrapper for EmbedBuilder that handles scrolling through multiple of them via MessageButtons. +> It offers lots of configurability and dynamically changeable pages. +> +> #### Methods: +> - `sendIn()` sends this PageEmbed in the provided channel. If you want a custom message implementation, use `setMsg()` and `getMsg()` +> - `useInt()` instead replies to or edits a Command-/ButtonInteraction +> - `getMsgOpts()` returns properties that can be passed to a `channel.send()` or `(msg | int).reply()` method +> - `setPages()` is for dynamically changing the pages of the instance. If the current page index is out of range after the pages have changed, it gets lowered automatically. +> - `first()`, `prev()`, `next()` and `last()` can be used just like the users use the MessageButtons to navigate the PageEmbed. +> - `destroy()` edits the message to remove the buttons, emits the `destroy` event, removes all event listeners and deregisters the buttons +> - `updateMsg()` can be called to update the message on the Discord API with what's currently stored in the PageEmbed. +> - `setAllowAllUsers()` allows setting whether users other than the author can interact with the buttons +> - `askGoToPage()` opens a prompt in a channel to type the new page number to navigate to. +> +> #### Events: +> Use `PageEmbed.on("name", (args) => {})` to subscribe to them +> - `press` is emitted whenever a button is pressed by a user and gets passed the ButtonInteraction instance and a string telling you which button was pressed. +> - `timeout` is emitted when the timeout of the PageEmbed, set in the settings object, is reached. After the timeout, the `.destroy()` method is automatically called. +> - `destroy` is emitted whenever the `.destroy()` method is called. +> - `update` is emitted after the associated message or interaction on the Discord API has been edited. + +
+ +> ### Modal +> The modal is a configurable form dialog that gets shown to a user. +> Modals only work in the desktop client, not the mobile app. +> +> This is an abstract class, so you need to create a sub-class extending `Modal` +> +> #### Methods: +> - `submit()` is executed when the user submitted the modal - this method needs to be overridden in a sub-class +> - `getInternalModal()` returns the modal object that needs to be passed to an interaction's `showModal()` method +> +> #### Events: +> - `destroy` gets emitted when `.destroy()` is called to trigger the registry to delete this instance + +
From 9743c33aa34dca9fbf99ab9f1198022fab8b4310 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 18 Mar 2023 21:15:27 +0100 Subject: [PATCH 18/40] chore: update deps --- package-lock.json | 3541 +++++++++++++++++---------------------------- package.json | 16 +- 2 files changed, 1336 insertions(+), 2221 deletions(-) diff --git a/package-lock.json b/package-lock.json index a3d5b7c..26b739c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,17 +9,17 @@ "version": "0.2.0", "license": "AGPL-3.0", "dependencies": { - "@discordjs/rest": "^0.5.0", + "@discordjs/rest": "^1.6.0", "@prisma/client": "^4.3.1", - "axios": "^0.27.2", + "axios": "^1.3.4", "better-erela.js-spotify": "^1.3.8", "canvas": "^2.9.3", "discord-api-types": "^0.37.3", - "discord.js": "^14.2.0", + "discord.js": "^14.8.0", "dotenv": "^16.0.0", "erela.js": "^2.3.3", "fast-memoize": "^2.5.2", - "fs-extra": "^10.1.0", + "fs-extra": "^11.1.0", "fuse.js": "^6.6.2", "kleur": "^4.1.4", "nanoid": "^3.3.4", @@ -34,8 +34,8 @@ "brewbot": "src/tools/cli/cli" }, "devDependencies": { - "@types/fs-extra": "^9.0.13", - "@types/node": "^17.0.23", + "@types/fs-extra": "^11.0.1", + "@types/node": "^18.15.3", "@types/prompts": "^2.0.14", "@types/steamapi": "^2.2.2", "@types/yargs": "^17.0.12", @@ -46,7 +46,7 @@ "prompts": "^2.4.2", "ts-node": "^10.7.0", "tsc-alias": "^1.6.11", - "typescript": "^4.6.3" + "typescript": "^5.0.2" }, "engines": { "node": ">=16.9", @@ -66,88 +66,150 @@ } }, "node_modules/@discordjs/builders": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.1.0.tgz", - "integrity": "sha512-EO8TSltiIc9Z1wE854wAFvv5AccqEtvjFmao9PPoxQhRaJ0hEb7FwWRTCA1jGg4ZWI3hcp4m+RET5ufZQz3rOg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.5.0.tgz", + "integrity": "sha512-7XxT78mnNBPigHn2y6KAXkicxIBFtZREGWaRZ249EC1l6gBUEP8IyVY5JTciIjJArxkF+tg675aZvsTNTKBpmA==", "dependencies": { - "@sapphire/shapeshift": "^3.5.1", - "discord-api-types": "^0.36.3", + "@discordjs/formatters": "^0.2.0", + "@discordjs/util": "^0.2.0", + "@sapphire/shapeshift": "^3.8.1", + "discord-api-types": "^0.37.35", "fast-deep-equal": "^3.1.3", - "ts-mixer": "^6.0.1", - "tslib": "^2.4.0" + "ts-mixer": "^6.0.3", + "tslib": "^2.5.0" }, "engines": { "node": ">=16.9.0" } }, - "node_modules/@discordjs/builders/node_modules/discord-api-types": { - "version": "0.36.3", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.36.3.tgz", - "integrity": "sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg==" - }, "node_modules/@discordjs/collection": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.7.0.tgz", - "integrity": "sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.4.0.tgz", + "integrity": "sha512-hiOJyk2CPFf1+FL3a4VKCuu1f448LlROVuu8nLz1+jCOAPokUcdFAV+l4pd3B3h6uJlJQSASoZzrdyNdjdtfzQ==", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/@discordjs/formatters": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.2.0.tgz", + "integrity": "sha512-vn4oMSXuMZUm8ITqVOtvE7/fMMISj4cI5oLsR09PEQXHKeKDAMLltG/DWeeIs7Idfy6V8Fk3rn1e69h7NfzuNA==", + "dependencies": { + "discord-api-types": "^0.37.35" + }, "engines": { "node": ">=16.9.0" } }, "node_modules/@discordjs/rest": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-0.5.0.tgz", - "integrity": "sha512-S4E1YNz1UxgUfMPpMeqzPPkCfXE877zOsvKM5WEmwIhcpz1PQV7lzqlEOuz194UuwOJLLjQFBgQELnQfCX9UfA==", - "dependencies": { - "@discordjs/collection": "^0.7.0", - "@sapphire/async-queue": "^1.3.1", - "@sapphire/snowflake": "^3.2.2", - "discord-api-types": "^0.33.3", - "tslib": "^2.4.0", - "undici": "^5.4.0" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.6.0.tgz", + "integrity": "sha512-HGvqNCZ5Z5j0tQHjmT1lFvE5ETO4hvomJ1r0cbnpC1zM23XhCpZ9wgTCiEmaxKz05cyf2CI9p39+9LL+6Yz1bA==", + "dependencies": { + "@discordjs/collection": "^1.4.0", + "@discordjs/util": "^0.2.0", + "@sapphire/async-queue": "^1.5.0", + "@sapphire/snowflake": "^3.4.0", + "discord-api-types": "^0.37.35", + "file-type": "^18.2.1", + "tslib": "^2.5.0", + "undici": "^5.20.0" }, "engines": { "node": ">=16.9.0" } }, - "node_modules/@discordjs/rest/node_modules/discord-api-types": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.5.tgz", - "integrity": "sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg==" + "node_modules/@discordjs/util": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.2.0.tgz", + "integrity": "sha512-/8qNbebFzLWKOOg+UV+RB8itp4SmU5jw0tBUD3ifElW6rYNOj1Ku5JaSW7lLl/WgjjxF01l/1uQPCzkwr110vg==", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", + "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", + "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", + "espree": "^9.5.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", @@ -155,9 +217,9 @@ "dev": true }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", - "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, "engines": { "node": ">=6.0.0" @@ -180,9 +242,9 @@ } }, "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", - "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -198,20 +260,6 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, - "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -248,12 +296,12 @@ } }, "node_modules/@prisma/client": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.3.1.tgz", - "integrity": "sha512-FA0/d1VMJNWqzU7WVWTNWJ+lGOLR9JUBnF73GdIPAEVo/6dWk4gHx0EmgeU+SMv4MZoxgOeTBJF2azhg7x0hMw==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.11.0.tgz", + "integrity": "sha512-0INHYkQIqgAjrt7NzhYpeDQi8x3Nvylc2uDngKyFDDj1tTRQ4uV1HnVmd1sQEraeVAN63SOK0dgCKQHlvjL0KA==", "hasInstallScript": true, "dependencies": { - "@prisma/engines-version": "4.3.0-32.c875e43600dfe042452e0b868f7a48b817b9640b" + "@prisma/engines-version": "4.11.0-57.8fde8fef4033376662cad983758335009d522acb" }, "engines": { "node": ">=14.17" @@ -268,31 +316,31 @@ } }, "node_modules/@prisma/engines": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.3.1.tgz", - "integrity": "sha512-4JF/uMaEDAPdcdZNOrnzE3BvrbGpjgV0FcPT3EVoi6I86fWkloqqxBt+KcK/+fIRR0Pxj66uGR9wVH8U1Y13JA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.11.0.tgz", + "integrity": "sha512-0AEBi2HXGV02cf6ASsBPhfsVIbVSDC9nbQed4iiY5eHttW9ZtMxHThuKZE1pnESbr8HRdgmFSa/Kn4OSNYuibg==", "hasInstallScript": true }, "node_modules/@prisma/engines-version": { - "version": "4.3.0-32.c875e43600dfe042452e0b868f7a48b817b9640b", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.3.0-32.c875e43600dfe042452e0b868f7a48b817b9640b.tgz", - "integrity": "sha512-8yWpXkQRmiSfsi2Wb/ZS5D3RFbeu/btL9Pm/gdF4phB0Lo5KGsDFMxFMgaD64mwED2nHc8ZaEJg/+4Jymb9Znw==" + "version": "4.11.0-57.8fde8fef4033376662cad983758335009d522acb", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.11.0-57.8fde8fef4033376662cad983758335009d522acb.tgz", + "integrity": "sha512-3Vd8Qq06d5xD8Ch5WauWcUUrsVPdMC6Ge8ILji8RFfyhUpqon6qSyGM0apvr1O8n8qH8cKkEFqRPsYjuz5r83g==" }, "node_modules/@redis/bloom": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.0.2.tgz", - "integrity": "sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", + "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/client": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.2.0.tgz", - "integrity": "sha512-a8Nlw5fv2EIAFJxTDSSDVUT7yfBGpZO96ybZXzQpgkyLg/dxtQ1uiwTc0EGfzg1mrPjZokeBSEGTbGXekqTNOg==", + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.6.tgz", + "integrity": "sha512-dFD1S6je+A47Lj22jN/upVU2fj4huR7S9APd7/ziUXsIXDL+11GPYti4Suv5y8FuXaN+0ZG4JF+y1houEJ7ToA==", "dependencies": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", + "cluster-key-slot": "1.1.2", + "generic-pool": "3.9.0", "yallist": "4.0.0" }, "engines": { @@ -300,33 +348,33 @@ } }, "node_modules/@redis/graph": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.0.1.tgz", - "integrity": "sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", + "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/json": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.3.tgz", - "integrity": "sha512-4X0Qv0BzD9Zlb0edkUoau5c1bInWSICqXAGrpwEltkncUwcxJIGEcVryZhLgb0p/3PkKaLIWkjhHRtLe9yiA7Q==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", + "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/search": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.0.6.tgz", - "integrity": "sha512-pP+ZQRis5P21SD6fjyCeLcQdps+LuTzp2wdUbzxEmNhleighDDTD5ck8+cYof+WLec4csZX7ks+BuoMw0RaZrA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.2.tgz", + "integrity": "sha512-/cMfstG/fOh/SsE+4/BQGeuH/JJloeWuH+qJzM8dbxuWvdWibWAOAHHCZTMPhV3xIlH4/cUEIA8OV5QnYpaVoA==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/time-series": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.3.tgz", - "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", + "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", "peerDependencies": { "@redis/client": "^1.0.0" } @@ -341,12 +389,12 @@ } }, "node_modules/@sapphire/shapeshift": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.5.1.tgz", - "integrity": "sha512-7JFsW5IglyOIUQI1eE0g6h06D/Far6HqpcowRScgCiLSqTf3hhkPWCWotVTtVycnDCMYIwPeaw6IEPBomKC8pA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.8.1.tgz", + "integrity": "sha512-xG1oXXBhCjPKbxrRTlox9ddaZTvVpOhYLmKmApD/vIWOV1xEYXnpoFs68zHIZBGbqztq6FrUPNPerIrO1Hqeaw==", "dependencies": { "fast-deep-equal": "^3.1.3", - "lodash.uniqwith": "^4.5.0" + "lodash": "^4.17.21" }, "engines": { "node": ">=v14.0.0", @@ -354,26 +402,14 @@ } }, "node_modules/@sapphire/snowflake": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.2.2.tgz", - "integrity": "sha512-ula2O0kpSZtX9rKXNeQMrHwNd7E4jPDJYUXmEGTFdMRfyfMw+FPyh04oKMjAiDuOi64bYgVkOV3MjK+loImFhQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.4.0.tgz", + "integrity": "sha512-zZxymtVO6zeXVMPds+6d7gv/OfnCc25M1Z+7ZLB0oPmeMTPeRWVPQSS16oDJy5ZsyCOLj7M6mbZml5gWXcVRNw==", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" } }, - "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@tokenizer/token": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", @@ -404,11 +440,12 @@ "dev": true }, "node_modules/@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.1.tgz", + "integrity": "sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA==", "dev": true, "dependencies": { + "@types/jsonfile": "*", "@types/node": "*" } }, @@ -418,20 +455,45 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, + "node_modules/@types/jsonfile": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.1.tgz", + "integrity": "sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==" }, "node_modules/@types/prompts": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.0.14.tgz", - "integrity": "sha512-HZBd99fKxRWpYCErtm2/yxUZv6/PBI9J7N4TNFffl5JbrYMHBwF25DjQGTW3b3jmXq+9P6/8fCIb2ee57BFfYA==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.4.3.tgz", + "integrity": "sha512-qpzXlxoPv67TCtTCS+SwYmz1M+G5ARTrE5YVlrZPy/xBD36dzLqiJLDzOzsMXkcJYq6+6UkWqFwtLAOjsfec5Q==", "dev": true, "dependencies": { - "@types/node": "*" + "@types/node": "*", + "kleur": "^3.0.3" + } + }, + "node_modules/@types/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" } }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, "node_modules/@types/steamapi": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/@types/steamapi/-/steamapi-2.2.2.tgz", @@ -439,17 +501,17 @@ "dev": true }, "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", + "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/yargs": { - "version": "17.0.12", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.12.tgz", - "integrity": "sha512-Nz4MPhecOFArtm81gFQvQqdV7XYCrWKx5uUt6GNHredFHn1i2mtWqXTON7EPXMtNi1qjtjEM/VCHDhcHsAMLXQ==", + "version": "17.0.22", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.22.tgz", + "integrity": "sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -462,18 +524,19 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.0.tgz", - "integrity": "sha512-lvhRJ2pGe2V9MEU46ELTdiHgiAFZPKtLhiU5wlnaYpMc2+c1R8fh8i80ZAa665drvjHKUJyRRGg3gEm1If54ow==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz", + "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.30.0", - "@typescript-eslint/type-utils": "5.30.0", - "@typescript-eslint/utils": "5.30.0", + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/type-utils": "5.55.0", + "@typescript-eslint/utils": "5.55.0", "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", - "regexpp": "^3.2.0", + "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", "tsutils": "^3.21.0" }, @@ -495,14 +558,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.0.tgz", - "integrity": "sha512-2oYYUws5o2liX6SrFQ5RB88+PuRymaM2EU02/9Ppoyu70vllPnHVO7ioxDdq/ypXHA277R04SVjxvwI8HmZpzA==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", + "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.30.0", - "@typescript-eslint/types": "5.30.0", - "@typescript-eslint/typescript-estree": "5.30.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", "debug": "^4.3.4" }, "engines": { @@ -522,13 +585,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.0.tgz", - "integrity": "sha512-3TZxvlQcK5fhTBw5solQucWSJvonXf5yua5nx8OqK94hxdrT7/6W3/CS42MLd/f1BmlmmbGEgQcTHHCktUX5bQ==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", + "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.30.0", - "@typescript-eslint/visitor-keys": "5.30.0" + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -539,12 +602,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.0.tgz", - "integrity": "sha512-GF8JZbZqSS+azehzlv/lmQQ3EU3VfWYzCczdZjJRxSEeXDQkqFhCBgFhallLDbPwQOEQ4MHpiPfkjKk7zlmeNg==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz", + "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.30.0", + "@typescript-eslint/typescript-estree": "5.55.0", + "@typescript-eslint/utils": "5.55.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -565,9 +629,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.0.tgz", - "integrity": "sha512-vfqcBrsRNWw/LBXyncMF/KrUTYYzzygCSsVqlZ1qGu1QtGs6vMkt3US0VNSQ05grXi5Yadp3qv5XZdYLjpp8ag==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", + "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -578,13 +642,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.0.tgz", - "integrity": "sha512-hDEawogreZB4n1zoqcrrtg/wPyyiCxmhPLpZ6kmWfKF5M5G0clRLaEexpuWr31fZ42F96SlD/5xCt1bT5Qm4Nw==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", + "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.30.0", - "@typescript-eslint/visitor-keys": "5.30.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -605,17 +669,19 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.0.tgz", - "integrity": "sha512-0bIgOgZflLKIcZsWvfklsaQTM3ZUbmtH0rJ1hKyV3raoUYyeZwcjQ8ZUJTzS7KnhNcsVT1Rxs7zeeMHEhGlltw==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz", + "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==", "dev": true, "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.30.0", - "@typescript-eslint/types": "5.30.0", - "@typescript-eslint/typescript-estree": "5.30.0", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "semver": "^7.3.7" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -629,12 +695,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.0.tgz", - "integrity": "sha512-6WcIeRk2DQ3pHKxU1Ni0qMXJkjO/zLjBymlYBy/53qxe7yjEFSvzKLDToJjURUhSl2Fzhkl4SMXQoETauF74cw==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", + "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.30.0", + "@typescript-eslint/types": "5.55.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -651,9 +717,9 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -707,15 +773,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "dependencies": { - "string-width": "^4.1.0" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -739,9 +796,9 @@ } }, "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", @@ -768,19 +825,6 @@ "node": ">=10" } }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -808,12 +852,13 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/balanced-match": { @@ -822,12 +867,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/better-erela.js-spotify": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/better-erela.js-spotify/-/better-erela.js-spotify-1.3.8.tgz", - "integrity": "sha512-4s8igXJTvriusSRzHofBoYUZj6gi8Ik2lZTaEDJunQh32Uh/ICt4riEYIGgVi7OKMGsRdlOU/EXVoCxqkpU+0w==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/better-erela.js-spotify/-/better-erela.js-spotify-1.3.11.tgz", + "integrity": "sha512-5Y6u3hYnOxRQxr1dRZJWQ9X2TaAZdhHQmhDkLV+/hB0IoSNlzRwYMH3+xXPmCJSczukjm8CqEyedovf3++f3eQ==", "dependencies": { - "erela.js": "^2.3.3", - "undici": "^5.6.0" + "undici": "^5.10.0" } }, "node_modules/bignumber.js": { @@ -848,28 +892,6 @@ "node": ">=8" } }, - "node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "dev": true, - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -891,46 +913,15 @@ "node": ">=8" } }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" + "streamsearch": "^1.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, "engines": { - "node": ">=8" + "node": ">=10.16.0" } }, "node_modules/callsites": { @@ -942,26 +933,14 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/canvas": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.3.tgz", - "integrity": "sha512-WOUM7ghii5TV2rbhaZkh1youv/vW1/Canev6Yx6BG2W+1S07w8jKZqKkPnbiPpQEDsnJdN8ouDd7OvQEGXDcUw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.0.tgz", + "integrity": "sha512-bdTjFexjKJEwtIo0oRx8eD4G2yWoUOXP9lj279jmQ2zMnTQhT8C3512OKz3s+ZOaQlLbE7TuVvRDYDB3Llyy5g==", "hasInstallScript": true, "dependencies": { "@mapbox/node-pre-gyp": "^1.0.0", - "nan": "^2.15.0", + "nan": "^2.17.0", "simple-get": "^3.0.3" }, "engines": { @@ -1031,47 +1010,23 @@ "node": ">=10" } }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" - } - }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/cluster-key-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", - "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", "engines": { "node": ">=0.10.0" } @@ -1112,9 +1067,9 @@ } }, "node_modules/commander": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz", - "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true, "engines": { "node": "^12.20.0 || >=14" @@ -1125,23 +1080,6 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, - "node_modules/configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "dependencies": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -1173,15 +1111,6 @@ "node": ">= 8" } }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1199,15 +1128,14 @@ } }, "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "dev": true, + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", "dependencies": { - "mimic-response": "^1.0.0" + "mimic-response": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/deep-diff": { @@ -1215,27 +1143,12 @@ "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.2.tgz", "integrity": "sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==" }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1279,61 +1192,33 @@ } }, "node_modules/discord-api-types": { - "version": "0.37.3", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.3.tgz", - "integrity": "sha512-LWcx1jDL8zanQJOPwNmHdFQTr/PFflDw1VYoRmTjme7LEKLr2Qqa2uz04gjN0eNEYskM2TYkOvNn3H5rblFM6g==" + "version": "0.37.36", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.36.tgz", + "integrity": "sha512-Nlxmp10UpVr/utgZ9uODQvG2Or+5w7LFrvFMswyeKC9l/+UaqGT6H0OVgEFhu9GEO4U6K7NNO5W8Carv7irnCA==" }, "node_modules/discord.js": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.2.0.tgz", - "integrity": "sha512-kIGhEeOB1d9k7whL9HCCuRuzK2GL7i/hTesYINOZ2szWm4TOsBVwRU+i9O/zDb2M+Gvff4SJ4EpAtCVV0okgVw==", - "dependencies": { - "@discordjs/builders": "^1.1.0", - "@discordjs/collection": "^1.0.1", - "@discordjs/rest": "^1.0.1", - "@sapphire/snowflake": "^3.2.2", - "@types/ws": "^8.5.3", - "discord-api-types": "^0.36.3", + "version": "14.8.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.8.0.tgz", + "integrity": "sha512-UOxYtc/YnV7jAJ2gISluJyYeBw4e+j8gWn+IoqG8unaHAVuvZ13DdYN0M1f9fbUgUvSarV798inIrYFtDNDjwQ==", + "dependencies": { + "@discordjs/builders": "^1.5.0", + "@discordjs/collection": "^1.4.0", + "@discordjs/formatters": "^0.2.0", + "@discordjs/rest": "^1.6.0", + "@discordjs/util": "^0.2.0", + "@sapphire/snowflake": "^3.4.0", + "@types/ws": "^8.5.4", + "discord-api-types": "^0.37.35", "fast-deep-equal": "^3.1.3", "lodash.snakecase": "^4.1.1", - "tslib": "^2.4.0", - "undici": "^5.8.2", - "ws": "^8.8.1" - }, - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/discord.js/node_modules/@discordjs/collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.0.1.tgz", - "integrity": "sha512-5V/wswzR3r2RVYXLxxg4TvrAnBhVCNgHTXhC+OUtLoriJ072rPMHo+Iw1SS1vrCckp8Es40XM411+WkNRPaXFw==", - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/discord.js/node_modules/@discordjs/rest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.0.1.tgz", - "integrity": "sha512-w08CTKVzzYYvKxEjXKOs9AdS7KQ1J502TrPfF8eCZ2lF6AfKuMP/32YgDakiwIyYTDjEQS/v0nKLSFcncHRMtg==", - "dependencies": { - "@discordjs/collection": "^1.0.1", - "@sapphire/async-queue": "^1.3.2", - "@sapphire/snowflake": "^3.2.2", - "discord-api-types": "^0.36.3", - "file-type": "^17.1.4", - "tslib": "^2.4.0", - "undici": "^5.8.0" + "tslib": "^2.5.0", + "undici": "^5.20.0", + "ws": "^8.12.1" }, "engines": { "node": ">=16.9.0" } }, - "node_modules/discord.js/node_modules/discord-api-types": { - "version": "0.36.3", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.36.3.tgz", - "integrity": "sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg==" - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1346,99 +1231,41 @@ "node": ">=6.0.0" } }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/dotenv": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", - "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", "engines": { "node": ">=12" } }, - "node_modules/duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==", - "dev": true - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/erela.js": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/erela.js/-/erela.js-2.3.3.tgz", - "integrity": "sha512-tzowGHLSodZr2j311csFSqm9lwE6plqeULTAwPwuRX9PQbXg4Ohdy/3MTMWrltiFAMSIG/5r9GQtTUt9Mqzhhw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/erela.js/-/erela.js-2.4.0.tgz", + "integrity": "sha512-wLfPvfzbDZTDV0zwJYXGkjO9Q6mkXi3PNf984apdv58Ktt0cv1Zp8og3hmp7Ose4C4iwAKitHxV/yiP+pt3FRQ==", "dependencies": { - "@discordjs/collection": "^0.1.6", - "petitio": "^1.1.0", - "ws": "^7.3.1" + "@discordjs/collection": "^1.1.0", + "tslib": "^2.4.0", + "undici": "^5.10.0", + "ws": "^8.8.1" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/erela.js/node_modules/@discordjs/collection": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", - "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==", - "deprecated": "no longer supported" - }, - "node_modules/erela.js/node_modules/ws": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz", - "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "engines": { "node": ">=6" } }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1452,13 +1279,18 @@ } }, "node_modules/eslint": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.18.0.tgz", - "integrity": "sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.9.2", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -1466,20 +1298,22 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", + "espree": "^9.5.0", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -1487,11 +1321,9 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -1516,33 +1348,6 @@ "node": ">=8.0.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-visitor-keys": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", @@ -1575,23 +1380,26 @@ } }, "node_modules/espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", "dev": true, "dependencies": { - "acorn": "^8.7.1", + "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -1654,9 +1462,9 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -1699,9 +1507,9 @@ "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -1720,16 +1528,16 @@ } }, "node_modules/file-type": { - "version": "17.1.6", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-17.1.6.tgz", - "integrity": "sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==", + "version": "18.2.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", + "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", "dependencies": { "readable-web-to-node-stream": "^3.0.2", - "strtok3": "^7.0.0-alpha.9", - "token-types": "^5.0.0-alpha.2" + "strtok3": "^7.0.0", + "token-types": "^5.0.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sindresorhus/file-type?sponsor=1" @@ -1747,6 +1555,22 @@ "node": ">=8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -1761,15 +1585,15 @@ } }, "node_modules/flatted": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", - "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", - "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "funding": [ { "type": "individual", @@ -1799,16 +1623,16 @@ } }, "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", + "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=14.14" } }, "node_modules/fs-minipass": { @@ -1822,16 +1646,35 @@ "node": ">= 8" } }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, "node_modules/fuse.js": { "version": "6.6.2", @@ -1861,9 +1704,9 @@ } }, "node_modules/generic-pool": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", - "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", "engines": { "node": ">= 4" } @@ -1876,18 +1719,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -1919,25 +1750,10 @@ "node": ">=10.13.0" } }, - "node_modules/global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dev": true, - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/globals": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", - "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -1969,41 +1785,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/got/node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true }, "node_modules/has-flag": { "version": "4.0.0", @@ -2019,21 +1810,6 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, - "node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -2066,9 +1842,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, "engines": { "node": ">= 4" @@ -2096,15 +1872,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -2128,15 +1895,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2149,18 +1907,6 @@ "node": ">=8" } }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2190,34 +1936,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2227,15 +1945,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -2245,18 +1954,6 @@ "node": ">=8" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -2269,6 +1966,16 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2281,12 +1988,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", - "dev": true - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2315,15 +2016,6 @@ "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.2.1.tgz", "integrity": "sha512-HjorDJFNhnM4SicvaUXac0X77NiskggxJdesG72+O5zBKpSqKFCrqmndKVqpu3pFqkla0St6uGk8Ju0sCurrmg==" }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.0" - } - }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -2332,18 +2024,6 @@ "node": ">=6" } }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "dependencies": { - "package-json": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2357,6 +2037,26 @@ "node": ">= 0.8.0" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -2368,20 +2068,6 @@ "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" }, - "node_modules/lodash.uniqwith": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniqwith/-/lodash.uniqwith-4.5.0.tgz", - "integrity": "sha512-7lYL8bLopMoy4CTICbxygAUq6CdRJ36vFc80DucPueUee+d5NBRxz3FdT9Pes/HEx5mPoT9jwnsEJWz1N7uq7Q==" - }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2463,12 +2149,14 @@ } }, "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimatch": { @@ -2482,19 +2170,10 @@ "node": "*" } }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, "node_modules/minipass": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", - "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", + "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", "engines": { "node": ">=8" } @@ -2511,6 +2190,17 @@ "node": ">= 8" } }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -2528,9 +2218,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/mylas": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.11.tgz", - "integrity": "sha512-krnPUl3n9/k52FGCltWMYcqp9SttxjRJEy0sWLk+g7mIa7wnZrmNSZ40Acx7ghzRSOsxt2rEqMbaq4jWlnTDKg==", + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", + "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", "dev": true, "engines": { "node": ">=12.0.0" @@ -2555,10 +2245,40 @@ "node": ">= 0.6" } }, + "node_modules/mysql/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "optional": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/mysql/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "optional": true + }, + "node_modules/mysql/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "optional": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/nan": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", - "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" }, "node_modules/nanoid": { "version": "3.3.4", @@ -2577,10 +2297,16 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -2597,22 +2323,21 @@ } }, "node_modules/nodemon": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.18.tgz", - "integrity": "sha512-uAvrKipi2zAz8E7nkSz4qW4F4zd5fs2wNGsTx+xXlP8KXqd9ucE0vY9wankOsPboeDyuUGN9vsXGV1pLn80l/A==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.21.tgz", + "integrity": "sha512-djN/n2549DUtY33S7o1djRCd7dEm0kBnj9c7S9XVXqRUbuggN1MZH/Nqa+5RFQr63Fbefq37nFXAE9VU86yL1A==", "dev": true, - "hasInstallScript": true, "dependencies": { "chokidar": "^3.5.2", "debug": "^3.2.7", "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "pstree.remy": "^1.1.8", "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", "supports-color": "^5.5.0", "touch": "^3.1.0", - "undefsafe": "^2.0.5", - "update-notifier": "^5.1.0" + "undefsafe": "^2.0.5" }, "bin": { "nodemon": "bin/nodemon.js" @@ -2665,10 +2390,9 @@ } }, "node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "dependencies": { "abbrev": "1" }, @@ -2676,7 +2400,7 @@ "nopt": "bin/nopt.js" }, "engines": { - "node": "*" + "node": ">=6" } }, "node_modules/normalize-path": { @@ -2688,15 +2412,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -2741,37 +2456,34 @@ "node": ">= 0.8.0" } }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=8" - } - }, - "node_modules/package-json/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/parent-module": { @@ -2786,6 +2498,15 @@ "node": ">=6" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -2824,14 +2545,6 @@ "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/petitio": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/petitio/-/petitio-1.4.0.tgz", - "integrity": "sha512-9LaVd/5BLmbNU8Q4Ax8NezihiPt2ISNqi2vKilEchSSf+YSOXxfsLUb0SUmDskm1WkBOVTsqdyuyYI0RYKqr0Q==", - "engines": { - "node": ">=12.3.0" - } - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2845,12 +2558,12 @@ } }, "node_modules/plimit-lit": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.2.7.tgz", - "integrity": "sha512-ce/kfCHFJ2sIK1IuSnXfVBxoMaIwuAF9J5NjFwxng1j+r8XguGxXMK87dBSODQfY+se2Raj/grpx5EAK9kapEA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.5.0.tgz", + "integrity": "sha512-Eb/MqCb1Iv/ok4m1FqIXqvUKPISufcjZ605hl3KM/n8GaX8zfhtgdLwZU3vKjuHGh2O9Rjog/bHTq8ofIShdng==", "dev": true, "dependencies": { - "queue-lit": "^1.2.8" + "queue-lit": "^1.5.0" } }, "node_modules/prelude-ls": { @@ -2862,22 +2575,13 @@ "node": ">= 0.8.0" } }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/prisma": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.3.1.tgz", - "integrity": "sha512-90xo06wtqil76Xsi3mNpc4Js3SdDRR5g4qb9h+4VWY4Y8iImJY6xc3PX+C9xxTSt1lr0Q89A0MLkJjd8ax6KiQ==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.11.0.tgz", + "integrity": "sha512-4zZmBXssPUEiX+GeL0MUq/Yyie4ltiKmGu7jCJFnYMamNrrulTBc+D+QwAQSJ01tyzeGHlD13kOnqPwRipnlNw==", "hasInstallScript": true, "dependencies": { - "@prisma/engines": "4.3.1" + "@prisma/engines": "4.11.0" }, "bin": { "prisma": "build/index.js", @@ -2915,47 +2619,30 @@ "node": ">=6" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, "engines": { "node": ">=6" } }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, - "dependencies": { - "escape-goat": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/queue-lit": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.2.8.tgz", - "integrity": "sha512-CR0/8Xb0oRk4rZrteSZcjrrPhWfXGBAWa/ATxYCqpdM4fnZu8M3zob5ajLxLUCXmpOzhHZ1+zgscrlzQtEOM0A==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.0.tgz", + "integrity": "sha512-IslToJ4eiCEE9xwMzq3viOO5nH8sUWUCwoElrhNMozzr9IIt2qqvB4I+uHu/zJTQVqc9R5DFwok4ijNK1pU3fA==", "dev": true }, "node_modules/queue-microtask": { @@ -2978,49 +2665,17 @@ } ] }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "node": ">= 6" } }, "node_modules/readable-web-to-node-stream": { @@ -3038,19 +2693,6 @@ "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3064,52 +2706,16 @@ } }, "node_modules/redis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.2.0.tgz", - "integrity": "sha512-bCR0gKVhIXFg8zCQjXEANzgI01DDixtPZgIUZHBCmwqixnu+MK3Tb2yqGjh+HCLASQVVgApiwhNkv+FoedZOGQ==", + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.5.tgz", + "integrity": "sha512-O0OWA36gDQbswOdUuAhRL6mTZpHFN525HlgZgDaVNgCJIAZR3ya06NTESb0R+TUZ+BFaDpz6NnnVvoMx9meUFg==", "dependencies": { - "@redis/bloom": "1.0.2", - "@redis/client": "1.2.0", - "@redis/graph": "1.0.1", - "@redis/json": "1.0.3", - "@redis/search": "1.0.6", - "@redis/time-series": "1.0.3" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/registry-auth-token": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", - "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", - "dev": true, - "dependencies": { - "rc": "1.2.8" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=8" + "@redis/bloom": "1.2.0", + "@redis/client": "1.5.6", + "@redis/graph": "1.1.0", + "@redis/json": "1.0.4", + "@redis/search": "1.1.2", + "@redis/time-series": "1.0.4" } }, "node_modules/require-directory": { @@ -3129,15 +2735,6 @@ "node": ">=4" } }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", - "dev": true, - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3186,14 +2783,28 @@ } }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3204,27 +2815,6 @@ "node": ">=10" } }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "dependencies": { - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -3285,34 +2875,33 @@ "simple-concat": "^1.0.0" } }, - "node_modules/simple-get/node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dependencies": { - "mimic-response": "^2.0.0" - }, + "node_modules/simple-statistics": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/simple-statistics/-/simple-statistics-7.8.3.tgz", + "integrity": "sha512-JFvMY00t6SBGtwMuJ+nqgsx9ylkMiJ5JlK9bkj8AdvniIe5615wWQYkKHXe84XtSuc40G/tlrPu0A5/NlJvv8A==", "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/simple-get/node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "engines": { - "node": ">=8" + "node_modules/simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dev": true, + "dependencies": { + "semver": "~7.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8.10.0" } }, - "node_modules/simple-statistics": { - "version": "7.7.5", - "resolved": "https://registry.npmjs.org/simple-statistics/-/simple-statistics-7.7.5.tgz", - "integrity": "sha512-CYq683Yg2mb7M4mklQ6FtxEdsYeziGa2giaLvqXobfK1qVqZDKd7BIqLnngnKQSw9GsfNinbiScbfjc3IRWdQA==", - "engines": { - "node": "*" + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, "node_modules/sisteransi": { @@ -3355,12 +2944,20 @@ "node": ">=12.0.0" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dependencies": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } }, "node_modules/string-width": { @@ -3428,14 +3025,17 @@ } }, "node_modules/svcorelib": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/svcorelib/-/svcorelib-1.18.1.tgz", - "integrity": "sha512-OJBg7OAX75v3aPKzOwSlj9KSvdorXm65SSsSxlTSf1ZLE6Mn6LjXLDfPd09pEZrFlm8bMBsiDmAE1P0woA6J0A==", + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/svcorelib/-/svcorelib-1.18.2.tgz", + "integrity": "sha512-EW8kUpRXfwwfH31Yu6fygIz8XsXeI9OIVU9fG8LFuwjreVCYLT6TJhxzeJEMvVRlF/pyTWi9FKkuCIF5C3H2FQ==", "dependencies": { "deep-diff": "^1.0.2", - "fs-extra": "^10.1.0", + "fs-extra": "^11.1.0", "keypress": "^0.2.1", - "minimatch": "^5.1.0" + "minimatch": "^7.0.0" + }, + "engines": { + "node": ">=14" }, "optionalDependencies": { "mysql": "^2.18.1" @@ -3450,30 +3050,33 @@ } }, "node_modules/svcorelib/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", + "integrity": "sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", + "minipass": "^4.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" }, "engines": { - "node": ">= 10" + "node": ">=10" } }, "node_modules/text-table": { @@ -3482,15 +3085,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3531,20 +3125,35 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/touch/node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/ts-mixer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz", - "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==" + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", + "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" }, "node_modules/ts-node": { - "version": "10.8.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.1.tgz", - "integrity": "sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -3585,9 +3194,9 @@ } }, "node_modules/tsc-alias": { - "version": "1.6.11", - "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.6.11.tgz", - "integrity": "sha512-mXEM21WriTJMQyo07B4Kc2nNFFk/1qOjU+jZ0ymXOyLz/A8J+dIBkimqZrh3s/x1qLGoJ1cNZQxa8GGoWOGX1Q==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.3.tgz", + "integrity": "sha512-/9JARcmXBrEqSuLjdSOqxY7/xI/AnvmBi4CU9/Ba2oX6Oq8vnd0OGSQTk+PIwqWJ5ZxskV0X/x15yzxCNTHU+g==", "dev": true, "dependencies": { "chokidar": "^3.5.3", @@ -3602,9 +3211,9 @@ } }, "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -3651,26 +3260,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", + "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=12.20" } }, "node_modules/undefsafe": { @@ -3680,23 +3280,14 @@ "dev": true }, "node_modules/undici": { - "version": "5.9.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.9.1.tgz", - "integrity": "sha512-6fB3a+SNnWEm4CJbgo0/CWR8RGcOCQP68SF4X0mxtYTq2VNN8T88NYrWVBAeSX+zb7bny2dx2iYhP3XHi00omg==", - "engines": { - "node": ">=12.18" - } - }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.21.0.tgz", + "integrity": "sha512-HOjK8l6a57b2ZGXOcUsI5NLfoTrfmbOl90ixJDl0AEFG4wgHNDQxtZy15/ZQp7HhjkpaGlp/eneMgtsu1dIlUA==", "dependencies": { - "crypto-random-string": "^2.0.0" + "busboy": "^1.6.0" }, "engines": { - "node": ">=8" + "node": ">=12.18" } }, "node_modules/universalify": { @@ -3707,34 +3298,6 @@ "node": ">= 10.0.0" } }, - "node_modules/update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", - "dev": true, - "dependencies": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3744,29 +3307,11 @@ "punycode": "^2.1.0" } }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", - "dev": true, - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -3807,19 +3352,7 @@ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" + "string-width": "^1.0.2 || 2 || 3 || 4" } }, "node_modules/word-wrap": { @@ -3852,28 +3385,16 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, "node_modules/ws": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", - "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -3884,15 +3405,6 @@ } } }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -3907,17 +3419,17 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" @@ -3939,6 +3451,18 @@ "engines": { "node": ">=6" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } }, "dependencies": { @@ -3952,59 +3476,77 @@ } }, "@discordjs/builders": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.1.0.tgz", - "integrity": "sha512-EO8TSltiIc9Z1wE854wAFvv5AccqEtvjFmao9PPoxQhRaJ0hEb7FwWRTCA1jGg4ZWI3hcp4m+RET5ufZQz3rOg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.5.0.tgz", + "integrity": "sha512-7XxT78mnNBPigHn2y6KAXkicxIBFtZREGWaRZ249EC1l6gBUEP8IyVY5JTciIjJArxkF+tg675aZvsTNTKBpmA==", "requires": { - "@sapphire/shapeshift": "^3.5.1", - "discord-api-types": "^0.36.3", + "@discordjs/formatters": "^0.2.0", + "@discordjs/util": "^0.2.0", + "@sapphire/shapeshift": "^3.8.1", + "discord-api-types": "^0.37.35", "fast-deep-equal": "^3.1.3", - "ts-mixer": "^6.0.1", - "tslib": "^2.4.0" - }, - "dependencies": { - "discord-api-types": { - "version": "0.36.3", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.36.3.tgz", - "integrity": "sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg==" - } + "ts-mixer": "^6.0.3", + "tslib": "^2.5.0" } }, "@discordjs/collection": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.7.0.tgz", - "integrity": "sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.4.0.tgz", + "integrity": "sha512-hiOJyk2CPFf1+FL3a4VKCuu1f448LlROVuu8nLz1+jCOAPokUcdFAV+l4pd3B3h6uJlJQSASoZzrdyNdjdtfzQ==" + }, + "@discordjs/formatters": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.2.0.tgz", + "integrity": "sha512-vn4oMSXuMZUm8ITqVOtvE7/fMMISj4cI5oLsR09PEQXHKeKDAMLltG/DWeeIs7Idfy6V8Fk3rn1e69h7NfzuNA==", + "requires": { + "discord-api-types": "^0.37.35" + } }, "@discordjs/rest": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-0.5.0.tgz", - "integrity": "sha512-S4E1YNz1UxgUfMPpMeqzPPkCfXE877zOsvKM5WEmwIhcpz1PQV7lzqlEOuz194UuwOJLLjQFBgQELnQfCX9UfA==", - "requires": { - "@discordjs/collection": "^0.7.0", - "@sapphire/async-queue": "^1.3.1", - "@sapphire/snowflake": "^3.2.2", - "discord-api-types": "^0.33.3", - "tslib": "^2.4.0", - "undici": "^5.4.0" - }, - "dependencies": { - "discord-api-types": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.5.tgz", - "integrity": "sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg==" - } + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.6.0.tgz", + "integrity": "sha512-HGvqNCZ5Z5j0tQHjmT1lFvE5ETO4hvomJ1r0cbnpC1zM23XhCpZ9wgTCiEmaxKz05cyf2CI9p39+9LL+6Yz1bA==", + "requires": { + "@discordjs/collection": "^1.4.0", + "@discordjs/util": "^0.2.0", + "@sapphire/async-queue": "^1.5.0", + "@sapphire/snowflake": "^3.4.0", + "discord-api-types": "^0.37.35", + "file-type": "^18.2.1", + "tslib": "^2.5.0", + "undici": "^5.20.0" + } + }, + "@discordjs/util": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.2.0.tgz", + "integrity": "sha512-/8qNbebFzLWKOOg+UV+RB8itp4SmU5jw0tBUD3ifElW6rYNOj1Ku5JaSW7lLl/WgjjxF01l/1uQPCzkwr110vg==" + }, + "@eslint-community/eslint-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", + "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" } }, + "@eslint-community/regexpp": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", + "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "dev": true + }, "@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", + "espree": "^9.5.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -4012,17 +3554,29 @@ "strip-json-comments": "^3.1.1" } }, + "@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "dev": true + }, "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" } }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, "@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", @@ -4030,9 +3584,9 @@ "dev": true }, "@jridgewell/resolve-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", - "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true }, "@jridgewell/sourcemap-codec": { @@ -4052,9 +3606,9 @@ } }, "@mapbox/node-pre-gyp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", - "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", "requires": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -4065,16 +3619,6 @@ "rimraf": "^3.0.2", "semver": "^7.3.5", "tar": "^6.1.11" - }, - "dependencies": { - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "requires": { - "abbrev": "1" - } - } } }, "@nodelib/fs.scandir": { @@ -4104,61 +3648,61 @@ } }, "@prisma/client": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.3.1.tgz", - "integrity": "sha512-FA0/d1VMJNWqzU7WVWTNWJ+lGOLR9JUBnF73GdIPAEVo/6dWk4gHx0EmgeU+SMv4MZoxgOeTBJF2azhg7x0hMw==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.11.0.tgz", + "integrity": "sha512-0INHYkQIqgAjrt7NzhYpeDQi8x3Nvylc2uDngKyFDDj1tTRQ4uV1HnVmd1sQEraeVAN63SOK0dgCKQHlvjL0KA==", "requires": { - "@prisma/engines-version": "4.3.0-32.c875e43600dfe042452e0b868f7a48b817b9640b" + "@prisma/engines-version": "4.11.0-57.8fde8fef4033376662cad983758335009d522acb" } }, "@prisma/engines": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.3.1.tgz", - "integrity": "sha512-4JF/uMaEDAPdcdZNOrnzE3BvrbGpjgV0FcPT3EVoi6I86fWkloqqxBt+KcK/+fIRR0Pxj66uGR9wVH8U1Y13JA==" + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.11.0.tgz", + "integrity": "sha512-0AEBi2HXGV02cf6ASsBPhfsVIbVSDC9nbQed4iiY5eHttW9ZtMxHThuKZE1pnESbr8HRdgmFSa/Kn4OSNYuibg==" }, "@prisma/engines-version": { - "version": "4.3.0-32.c875e43600dfe042452e0b868f7a48b817b9640b", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.3.0-32.c875e43600dfe042452e0b868f7a48b817b9640b.tgz", - "integrity": "sha512-8yWpXkQRmiSfsi2Wb/ZS5D3RFbeu/btL9Pm/gdF4phB0Lo5KGsDFMxFMgaD64mwED2nHc8ZaEJg/+4Jymb9Znw==" + "version": "4.11.0-57.8fde8fef4033376662cad983758335009d522acb", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.11.0-57.8fde8fef4033376662cad983758335009d522acb.tgz", + "integrity": "sha512-3Vd8Qq06d5xD8Ch5WauWcUUrsVPdMC6Ge8ILji8RFfyhUpqon6qSyGM0apvr1O8n8qH8cKkEFqRPsYjuz5r83g==" }, "@redis/bloom": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.0.2.tgz", - "integrity": "sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", + "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", "requires": {} }, "@redis/client": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.2.0.tgz", - "integrity": "sha512-a8Nlw5fv2EIAFJxTDSSDVUT7yfBGpZO96ybZXzQpgkyLg/dxtQ1uiwTc0EGfzg1mrPjZokeBSEGTbGXekqTNOg==", + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.6.tgz", + "integrity": "sha512-dFD1S6je+A47Lj22jN/upVU2fj4huR7S9APd7/ziUXsIXDL+11GPYti4Suv5y8FuXaN+0ZG4JF+y1houEJ7ToA==", "requires": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", + "cluster-key-slot": "1.1.2", + "generic-pool": "3.9.0", "yallist": "4.0.0" } }, "@redis/graph": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.0.1.tgz", - "integrity": "sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", + "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", "requires": {} }, "@redis/json": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.3.tgz", - "integrity": "sha512-4X0Qv0BzD9Zlb0edkUoau5c1bInWSICqXAGrpwEltkncUwcxJIGEcVryZhLgb0p/3PkKaLIWkjhHRtLe9yiA7Q==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", + "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", "requires": {} }, "@redis/search": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.0.6.tgz", - "integrity": "sha512-pP+ZQRis5P21SD6fjyCeLcQdps+LuTzp2wdUbzxEmNhleighDDTD5ck8+cYof+WLec4csZX7ks+BuoMw0RaZrA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.2.tgz", + "integrity": "sha512-/cMfstG/fOh/SsE+4/BQGeuH/JJloeWuH+qJzM8dbxuWvdWibWAOAHHCZTMPhV3xIlH4/cUEIA8OV5QnYpaVoA==", "requires": {} }, "@redis/time-series": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.3.tgz", - "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", + "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", "requires": {} }, "@sapphire/async-queue": { @@ -4167,27 +3711,18 @@ "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==" }, "@sapphire/shapeshift": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.5.1.tgz", - "integrity": "sha512-7JFsW5IglyOIUQI1eE0g6h06D/Far6HqpcowRScgCiLSqTf3hhkPWCWotVTtVycnDCMYIwPeaw6IEPBomKC8pA==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.8.1.tgz", + "integrity": "sha512-xG1oXXBhCjPKbxrRTlox9ddaZTvVpOhYLmKmApD/vIWOV1xEYXnpoFs68zHIZBGbqztq6FrUPNPerIrO1Hqeaw==", "requires": { "fast-deep-equal": "^3.1.3", - "lodash.uniqwith": "^4.5.0" + "lodash": "^4.17.21" } }, "@sapphire/snowflake": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.2.2.tgz", - "integrity": "sha512-ula2O0kpSZtX9rKXNeQMrHwNd7E4jPDJYUXmEGTFdMRfyfMw+FPyh04oKMjAiDuOi64bYgVkOV3MjK+loImFhQ==" - }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "requires": { - "defer-to-connect": "^1.0.1" - } + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.4.0.tgz", + "integrity": "sha512-zZxymtVO6zeXVMPds+6d7gv/OfnCc25M1Z+7ZLB0oPmeMTPeRWVPQSS16oDJy5ZsyCOLj7M6mbZml5gWXcVRNw==" }, "@tokenizer/token": { "version": "0.3.0", @@ -4219,11 +3754,12 @@ "dev": true }, "@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.1.tgz", + "integrity": "sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA==", "dev": true, "requires": { + "@types/jsonfile": "*", "@types/node": "*" } }, @@ -4233,20 +3769,44 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, + "@types/jsonfile": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.1.tgz", + "integrity": "sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==" }, "@types/prompts": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.0.14.tgz", - "integrity": "sha512-HZBd99fKxRWpYCErtm2/yxUZv6/PBI9J7N4TNFffl5JbrYMHBwF25DjQGTW3b3jmXq+9P6/8fCIb2ee57BFfYA==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.4.3.tgz", + "integrity": "sha512-qpzXlxoPv67TCtTCS+SwYmz1M+G5ARTrE5YVlrZPy/xBD36dzLqiJLDzOzsMXkcJYq6+6UkWqFwtLAOjsfec5Q==", "dev": true, "requires": { - "@types/node": "*" + "@types/node": "*", + "kleur": "^3.0.3" + }, + "dependencies": { + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + } } }, + "@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, "@types/steamapi": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/@types/steamapi/-/steamapi-2.2.2.tgz", @@ -4254,17 +3814,17 @@ "dev": true }, "@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", + "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", "requires": { "@types/node": "*" } }, "@types/yargs": { - "version": "17.0.12", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.12.tgz", - "integrity": "sha512-Nz4MPhecOFArtm81gFQvQqdV7XYCrWKx5uUt6GNHredFHn1i2mtWqXTON7EPXMtNi1qjtjEM/VCHDhcHsAMLXQ==", + "version": "17.0.22", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.22.tgz", + "integrity": "sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -4277,69 +3837,71 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.0.tgz", - "integrity": "sha512-lvhRJ2pGe2V9MEU46ELTdiHgiAFZPKtLhiU5wlnaYpMc2+c1R8fh8i80ZAa665drvjHKUJyRRGg3gEm1If54ow==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz", + "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.30.0", - "@typescript-eslint/type-utils": "5.30.0", - "@typescript-eslint/utils": "5.30.0", + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/type-utils": "5.55.0", + "@typescript-eslint/utils": "5.55.0", "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", - "regexpp": "^3.2.0", + "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", "tsutils": "^3.21.0" } }, "@typescript-eslint/parser": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.0.tgz", - "integrity": "sha512-2oYYUws5o2liX6SrFQ5RB88+PuRymaM2EU02/9Ppoyu70vllPnHVO7ioxDdq/ypXHA277R04SVjxvwI8HmZpzA==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", + "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.30.0", - "@typescript-eslint/types": "5.30.0", - "@typescript-eslint/typescript-estree": "5.30.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.0.tgz", - "integrity": "sha512-3TZxvlQcK5fhTBw5solQucWSJvonXf5yua5nx8OqK94hxdrT7/6W3/CS42MLd/f1BmlmmbGEgQcTHHCktUX5bQ==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", + "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.30.0", - "@typescript-eslint/visitor-keys": "5.30.0" + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0" } }, "@typescript-eslint/type-utils": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.0.tgz", - "integrity": "sha512-GF8JZbZqSS+azehzlv/lmQQ3EU3VfWYzCczdZjJRxSEeXDQkqFhCBgFhallLDbPwQOEQ4MHpiPfkjKk7zlmeNg==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz", + "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==", "dev": true, "requires": { - "@typescript-eslint/utils": "5.30.0", + "@typescript-eslint/typescript-estree": "5.55.0", + "@typescript-eslint/utils": "5.55.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.0.tgz", - "integrity": "sha512-vfqcBrsRNWw/LBXyncMF/KrUTYYzzygCSsVqlZ1qGu1QtGs6vMkt3US0VNSQ05grXi5Yadp3qv5XZdYLjpp8ag==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", + "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.0.tgz", - "integrity": "sha512-hDEawogreZB4n1zoqcrrtg/wPyyiCxmhPLpZ6kmWfKF5M5G0clRLaEexpuWr31fZ42F96SlD/5xCt1bT5Qm4Nw==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", + "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.30.0", - "@typescript-eslint/visitor-keys": "5.30.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -4348,26 +3910,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.0.tgz", - "integrity": "sha512-0bIgOgZflLKIcZsWvfklsaQTM3ZUbmtH0rJ1hKyV3raoUYyeZwcjQ8ZUJTzS7KnhNcsVT1Rxs7zeeMHEhGlltw==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz", + "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==", "dev": true, "requires": { + "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.30.0", - "@typescript-eslint/types": "5.30.0", - "@typescript-eslint/typescript-estree": "5.30.0", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.0.tgz", - "integrity": "sha512-6WcIeRk2DQ3pHKxU1Ni0qMXJkjO/zLjBymlYBy/53qxe7yjEFSvzKLDToJjURUhSl2Fzhkl4SMXQoETauF74cw==", + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", + "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.30.0", + "@typescript-eslint/types": "5.55.0", "eslint-visitor-keys": "^3.3.0" } }, @@ -4377,9 +3941,9 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true }, "acorn-jsx": { @@ -4415,15 +3979,6 @@ "uri-js": "^4.2.2" } }, - "ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "requires": { - "string-width": "^4.1.0" - } - }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -4438,9 +3993,9 @@ } }, "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -4459,18 +4014,6 @@ "requires": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } } }, "arg": { @@ -4497,12 +4040,13 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", "requires": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "balanced-match": { @@ -4511,12 +4055,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "better-erela.js-spotify": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/better-erela.js-spotify/-/better-erela.js-spotify-1.3.8.tgz", - "integrity": "sha512-4s8igXJTvriusSRzHofBoYUZj6gi8Ik2lZTaEDJunQh32Uh/ICt4riEYIGgVi7OKMGsRdlOU/EXVoCxqkpU+0w==", + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/better-erela.js-spotify/-/better-erela.js-spotify-1.3.11.tgz", + "integrity": "sha512-5Y6u3hYnOxRQxr1dRZJWQ9X2TaAZdhHQmhDkLV+/hB0IoSNlzRwYMH3+xXPmCJSczukjm8CqEyedovf3++f3eQ==", "requires": { - "erela.js": "^2.3.3", - "undici": "^5.6.0" + "undici": "^5.10.0" } }, "bignumber.js": { @@ -4531,22 +4074,6 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, - "boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "dev": true, - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4565,36 +4092,12 @@ "fill-range": "^7.0.1" } }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } + "streamsearch": "^1.1.0" } }, "callsites": { @@ -4603,19 +4106,13 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, "canvas": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.3.tgz", - "integrity": "sha512-WOUM7ghii5TV2rbhaZkh1youv/vW1/Canev6Yx6BG2W+1S07w8jKZqKkPnbiPpQEDsnJdN8ouDd7OvQEGXDcUw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.0.tgz", + "integrity": "sha512-bdTjFexjKJEwtIo0oRx8eD4G2yWoUOXP9lj279jmQ2zMnTQhT8C3512OKz3s+ZOaQlLbE7TuVvRDYDB3Llyy5g==", "requires": { "@mapbox/node-pre-gyp": "^1.0.0", - "nan": "^2.15.0", + "nan": "^2.17.0", "simple-get": "^3.0.3" } }, @@ -4661,41 +4158,20 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true - }, "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "requires": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, "cluster-key-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", - "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" }, "color-convert": { "version": "2.0.1", @@ -4724,9 +4200,9 @@ } }, "commander": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz", - "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true }, "concat-map": { @@ -4734,20 +4210,6 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - } - }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -4776,12 +4238,6 @@ "which": "^2.0.1" } }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true - }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -4791,12 +4247,11 @@ } }, "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "dev": true, + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "^2.0.0" } }, "deep-diff": { @@ -4804,24 +4259,12 @@ "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.2.tgz", "integrity": "sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==" }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -4853,52 +4296,28 @@ } }, "discord-api-types": { - "version": "0.37.3", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.3.tgz", - "integrity": "sha512-LWcx1jDL8zanQJOPwNmHdFQTr/PFflDw1VYoRmTjme7LEKLr2Qqa2uz04gjN0eNEYskM2TYkOvNn3H5rblFM6g==" + "version": "0.37.36", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.36.tgz", + "integrity": "sha512-Nlxmp10UpVr/utgZ9uODQvG2Or+5w7LFrvFMswyeKC9l/+UaqGT6H0OVgEFhu9GEO4U6K7NNO5W8Carv7irnCA==" }, "discord.js": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.2.0.tgz", - "integrity": "sha512-kIGhEeOB1d9k7whL9HCCuRuzK2GL7i/hTesYINOZ2szWm4TOsBVwRU+i9O/zDb2M+Gvff4SJ4EpAtCVV0okgVw==", - "requires": { - "@discordjs/builders": "^1.1.0", - "@discordjs/collection": "^1.0.1", - "@discordjs/rest": "^1.0.1", - "@sapphire/snowflake": "^3.2.2", - "@types/ws": "^8.5.3", - "discord-api-types": "^0.36.3", + "version": "14.8.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.8.0.tgz", + "integrity": "sha512-UOxYtc/YnV7jAJ2gISluJyYeBw4e+j8gWn+IoqG8unaHAVuvZ13DdYN0M1f9fbUgUvSarV798inIrYFtDNDjwQ==", + "requires": { + "@discordjs/builders": "^1.5.0", + "@discordjs/collection": "^1.4.0", + "@discordjs/formatters": "^0.2.0", + "@discordjs/rest": "^1.6.0", + "@discordjs/util": "^0.2.0", + "@sapphire/snowflake": "^3.4.0", + "@types/ws": "^8.5.4", + "discord-api-types": "^0.37.35", "fast-deep-equal": "^3.1.3", "lodash.snakecase": "^4.1.1", - "tslib": "^2.4.0", - "undici": "^5.8.2", - "ws": "^8.8.1" - }, - "dependencies": { - "@discordjs/collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.0.1.tgz", - "integrity": "sha512-5V/wswzR3r2RVYXLxxg4TvrAnBhVCNgHTXhC+OUtLoriJ072rPMHo+Iw1SS1vrCckp8Es40XM411+WkNRPaXFw==" - }, - "@discordjs/rest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.0.1.tgz", - "integrity": "sha512-w08CTKVzzYYvKxEjXKOs9AdS7KQ1J502TrPfF8eCZ2lF6AfKuMP/32YgDakiwIyYTDjEQS/v0nKLSFcncHRMtg==", - "requires": { - "@discordjs/collection": "^1.0.1", - "@sapphire/async-queue": "^1.3.2", - "@sapphire/snowflake": "^3.2.2", - "discord-api-types": "^0.36.3", - "file-type": "^17.1.4", - "tslib": "^2.4.0", - "undici": "^5.8.0" - } - }, - "discord-api-types": { - "version": "0.36.3", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.36.3.tgz", - "integrity": "sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg==" - } + "tslib": "^2.5.0", + "undici": "^5.20.0", + "ws": "^8.12.1" } }, "doctrine": { @@ -4910,61 +4329,25 @@ "esutils": "^2.0.2" } }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, "dotenv": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", - "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==" - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==", - "dev": true + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, "erela.js": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/erela.js/-/erela.js-2.3.3.tgz", - "integrity": "sha512-tzowGHLSodZr2j311csFSqm9lwE6plqeULTAwPwuRX9PQbXg4Ohdy/3MTMWrltiFAMSIG/5r9GQtTUt9Mqzhhw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/erela.js/-/erela.js-2.4.0.tgz", + "integrity": "sha512-wLfPvfzbDZTDV0zwJYXGkjO9Q6mkXi3PNf984apdv58Ktt0cv1Zp8og3hmp7Ose4C4iwAKitHxV/yiP+pt3FRQ==", "requires": { - "@discordjs/collection": "^0.1.6", - "petitio": "^1.1.0", - "ws": "^7.3.1" - }, - "dependencies": { - "@discordjs/collection": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", - "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" - }, - "ws": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz", - "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==", - "requires": {} - } + "@discordjs/collection": "^1.1.0", + "tslib": "^2.4.0", + "undici": "^5.10.0", + "ws": "^8.8.1" } }, "escalade": { @@ -4972,12 +4355,6 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, - "escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -4985,13 +4362,18 @@ "dev": true }, "eslint": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.18.0.tgz", - "integrity": "sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.9.2", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -4999,20 +4381,22 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", + "espree": "^9.5.0", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -5020,11 +4404,9 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "dependencies": { "eslint-scope": { @@ -5055,23 +4437,6 @@ "estraverse": "^4.1.1" } }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, "eslint-visitor-keys": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", @@ -5079,20 +4444,20 @@ "dev": true }, "espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", "dev": true, "requires": { - "acorn": "^8.7.1", + "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.3.0" } }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -5141,9 +4506,9 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -5182,9 +4547,9 @@ "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -5200,13 +4565,13 @@ } }, "file-type": { - "version": "17.1.6", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-17.1.6.tgz", - "integrity": "sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==", + "version": "18.2.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", + "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", "requires": { "readable-web-to-node-stream": "^3.0.2", - "strtok3": "^7.0.0-alpha.9", - "token-types": "^5.0.0-alpha.2" + "strtok3": "^7.0.0", + "token-types": "^5.0.1" } }, "fill-range": { @@ -5218,6 +4583,16 @@ "to-regex-range": "^5.0.1" } }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -5229,15 +4604,15 @@ } }, "flatted": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", - "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, "follow-redirects": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", - "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" }, "form-data": { "version": "4.0.0", @@ -5250,9 +4625,9 @@ } }, "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", + "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -5265,6 +4640,16 @@ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "requires": { "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } } }, "fs.realpath": { @@ -5272,11 +4657,12 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true }, "fuse.js": { "version": "6.6.2", @@ -5300,24 +4686,15 @@ } }, "generic-pool": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", - "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==" + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==" }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -5340,19 +4717,10 @@ "is-glob": "^4.0.3" } }, - "global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dev": true, - "requires": { - "ini": "2.0.0" - } - }, "globals": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", - "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -5372,37 +4740,16 @@ "slash": "^3.0.0" } }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "dependencies": { - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true - } - } - }, "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true }, "has-flag": { "version": "4.0.0", @@ -5415,18 +4762,6 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, - "has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -5442,9 +4777,9 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, "ignore-by-default": { @@ -5463,12 +4798,6 @@ "resolve-from": "^4.0.0" } }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", - "dev": true - }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -5486,14 +4815,8 @@ }, "inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "is-binary-path": { "version": "2.1.0", @@ -5504,15 +4827,6 @@ "binary-extensions": "^2.0.0" } }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -5533,52 +4847,18 @@ "is-extglob": "^2.1.1" } }, - "is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "requires": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - } - }, - "is-npm": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", - "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", - "dev": true - }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, "is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -5591,6 +4871,12 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true + }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -5600,12 +4886,6 @@ "argparse": "^2.0.1" } }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", - "dev": true - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -5632,29 +4912,11 @@ "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.2.1.tgz", "integrity": "sha512-HjorDJFNhnM4SicvaUXac0X77NiskggxJdesG72+O5zBKpSqKFCrqmndKVqpu3pFqkla0St6uGk8Ju0sCurrmg==" }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } - }, "kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==" }, - "latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "requires": { - "package-json": "^6.3.0" - } - }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5665,6 +4927,20 @@ "type-check": "~0.4.0" } }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -5676,17 +4952,6 @@ "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" }, - "lodash.uniqwith": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniqwith/-/lodash.uniqwith-4.5.0.tgz", - "integrity": "sha512-7lYL8bLopMoy4CTICbxygAUq6CdRJ36vFc80DucPueUee+d5NBRxz3FdT9Pes/HEx5mPoT9jwnsEJWz1N7uq7Q==" - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -5746,10 +5011,9 @@ } }, "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" }, "minimatch": { "version": "3.1.2", @@ -5759,19 +5023,10 @@ "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, "minipass": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", - "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", - "requires": { - "yallist": "^4.0.0" - } + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", + "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==" }, "minizlib": { "version": "2.1.2", @@ -5780,6 +5035,16 @@ "requires": { "minipass": "^3.0.0", "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } } }, "mkdirp": { @@ -5793,9 +5058,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "mylas": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.11.tgz", - "integrity": "sha512-krnPUl3n9/k52FGCltWMYcqp9SttxjRJEy0sWLk+g7mIa7wnZrmNSZ40Acx7ghzRSOsxt2rEqMbaq4jWlnTDKg==", + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", + "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", "dev": true }, "mysql": { @@ -5808,12 +5073,44 @@ "readable-stream": "2.3.7", "safe-buffer": "5.1.2", "sqlstring": "2.3.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "optional": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "nan": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", - "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" }, "nanoid": { "version": "3.3.4", @@ -5826,30 +5123,36 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", "requires": { "whatwg-url": "^5.0.0" } }, "nodemon": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.18.tgz", - "integrity": "sha512-uAvrKipi2zAz8E7nkSz4qW4F4zd5fs2wNGsTx+xXlP8KXqd9ucE0vY9wankOsPboeDyuUGN9vsXGV1pLn80l/A==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.21.tgz", + "integrity": "sha512-djN/n2549DUtY33S7o1djRCd7dEm0kBnj9c7S9XVXqRUbuggN1MZH/Nqa+5RFQr63Fbefq37nFXAE9VU86yL1A==", "dev": true, "requires": { "chokidar": "^3.5.2", "debug": "^3.2.7", "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "pstree.remy": "^1.1.8", "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", "supports-color": "^5.5.0", "touch": "^3.1.0", - "undefsafe": "^2.0.5", - "update-notifier": "^5.1.0" + "undefsafe": "^2.0.5" }, "dependencies": { "debug": { @@ -5885,10 +5188,9 @@ } }, "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "requires": { "abbrev": "1" } @@ -5899,12 +5201,6 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true - }, "npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -5943,30 +5239,22 @@ "word-wrap": "^1.2.3" } }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } }, - "package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "p-limit": "^3.0.2" } }, "parent-module": { @@ -5978,6 +5266,12 @@ "callsites": "^3.0.0" } }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -6000,11 +5294,6 @@ "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==" }, - "petitio": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/petitio/-/petitio-1.4.0.tgz", - "integrity": "sha512-9LaVd/5BLmbNU8Q4Ax8NezihiPt2ISNqi2vKilEchSSf+YSOXxfsLUb0SUmDskm1WkBOVTsqdyuyYI0RYKqr0Q==" - }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -6012,12 +5301,12 @@ "dev": true }, "plimit-lit": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.2.7.tgz", - "integrity": "sha512-ce/kfCHFJ2sIK1IuSnXfVBxoMaIwuAF9J5NjFwxng1j+r8XguGxXMK87dBSODQfY+se2Raj/grpx5EAK9kapEA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.5.0.tgz", + "integrity": "sha512-Eb/MqCb1Iv/ok4m1FqIXqvUKPISufcjZ605hl3KM/n8GaX8zfhtgdLwZU3vKjuHGh2O9Rjog/bHTq8ofIShdng==", "dev": true, "requires": { - "queue-lit": "^1.2.8" + "queue-lit": "^1.5.0" } }, "prelude-ls": { @@ -6026,18 +5315,12 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", - "dev": true - }, "prisma": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.3.1.tgz", - "integrity": "sha512-90xo06wtqil76Xsi3mNpc4Js3SdDRR5g4qb9h+4VWY4Y8iImJY6xc3PX+C9xxTSt1lr0Q89A0MLkJjd8ax6KiQ==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.11.0.tgz", + "integrity": "sha512-4zZmBXssPUEiX+GeL0MUq/Yyie4ltiKmGu7jCJFnYMamNrrulTBc+D+QwAQSJ01tyzeGHlD13kOnqPwRipnlNw==", "requires": { - "@prisma/engines": "4.3.1" + "@prisma/engines": "4.11.0" } }, "process-nextick-args": { @@ -6064,41 +5347,27 @@ } } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true }, - "pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, - "requires": { - "escape-goat": "^2.0.0" - } - }, "queue-lit": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.2.8.tgz", - "integrity": "sha512-CR0/8Xb0oRk4rZrteSZcjrrPhWfXGBAWa/ATxYCqpdM4fnZu8M3zob5ajLxLUCXmpOzhHZ1+zgscrlzQtEOM0A==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.0.tgz", + "integrity": "sha512-IslToJ4eiCEE9xwMzq3viOO5nH8sUWUCwoElrhNMozzr9IIt2qqvB4I+uHu/zJTQVqc9R5DFwok4ijNK1pU3fA==", "dev": true }, "queue-microtask": { @@ -6107,45 +5376,14 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true - } - } - }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, "readable-web-to-node-stream": { @@ -6154,18 +5392,6 @@ "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", "requires": { "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } } }, "readdirp": { @@ -6178,40 +5404,16 @@ } }, "redis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.2.0.tgz", - "integrity": "sha512-bCR0gKVhIXFg8zCQjXEANzgI01DDixtPZgIUZHBCmwqixnu+MK3Tb2yqGjh+HCLASQVVgApiwhNkv+FoedZOGQ==", - "requires": { - "@redis/bloom": "1.0.2", - "@redis/client": "1.2.0", - "@redis/graph": "1.0.1", - "@redis/json": "1.0.3", - "@redis/search": "1.0.6", - "@redis/time-series": "1.0.3" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "registry-auth-token": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", - "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", - "dev": true, - "requires": { - "rc": "1.2.8" - } - }, - "registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.5.tgz", + "integrity": "sha512-O0OWA36gDQbswOdUuAhRL6mTZpHFN525HlgZgDaVNgCJIAZR3ya06NTESb0R+TUZ+BFaDpz6NnnVvoMx9meUFg==", "requires": { - "rc": "^1.2.8" + "@redis/bloom": "1.2.0", + "@redis/client": "1.5.6", + "@redis/graph": "1.1.0", + "@redis/json": "1.0.4", + "@redis/search": "1.1.2", + "@redis/time-series": "1.0.4" } }, "require-directory": { @@ -6225,15 +5427,6 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } - }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -6258,35 +5451,18 @@ } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "requires": { "lru-cache": "^6.0.0" } }, - "semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -6325,28 +5501,30 @@ "decompress-response": "^4.2.0", "once": "^1.3.1", "simple-concat": "^1.0.0" + } + }, + "simple-statistics": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/simple-statistics/-/simple-statistics-7.8.3.tgz", + "integrity": "sha512-JFvMY00t6SBGtwMuJ+nqgsx9ylkMiJ5JlK9bkj8AdvniIe5615wWQYkKHXe84XtSuc40G/tlrPu0A5/NlJvv8A==" + }, + "simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dev": true, + "requires": { + "semver": "~7.0.0" }, "dependencies": { - "decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "requires": { - "mimic-response": "^2.0.0" - } - }, - "mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true } } }, - "simple-statistics": { - "version": "7.7.5", - "resolved": "https://registry.npmjs.org/simple-statistics/-/simple-statistics-7.7.5.tgz", - "integrity": "sha512-CYq683Yg2mb7M4mklQ6FtxEdsYeziGa2giaLvqXobfK1qVqZDKd7BIqLnngnKQSw9GsfNinbiScbfjc3IRWdQA==" - }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -6378,12 +5556,17 @@ "resolved": "https://registry.npmjs.org/steamid/-/steamid-2.0.0.tgz", "integrity": "sha512-+BFJMbo+IxzyfovLR37E7APkaNfmrL3S+88T7wTMRHnQ6LBhzEawPnjfWNKM9eUL/dH45j+7vhSX4WaGXoa4/Q==" }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } }, "string-width": { @@ -6429,14 +5612,14 @@ } }, "svcorelib": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/svcorelib/-/svcorelib-1.18.1.tgz", - "integrity": "sha512-OJBg7OAX75v3aPKzOwSlj9KSvdorXm65SSsSxlTSf1ZLE6Mn6LjXLDfPd09pEZrFlm8bMBsiDmAE1P0woA6J0A==", + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/svcorelib/-/svcorelib-1.18.2.tgz", + "integrity": "sha512-EW8kUpRXfwwfH31Yu6fygIz8XsXeI9OIVU9fG8LFuwjreVCYLT6TJhxzeJEMvVRlF/pyTWi9FKkuCIF5C3H2FQ==", "requires": { "deep-diff": "^1.0.2", - "fs-extra": "^10.1.0", + "fs-extra": "^11.1.0", "keypress": "^0.2.1", - "minimatch": "^5.1.0", + "minimatch": "^7.0.0", "mysql": "^2.18.1" }, "dependencies": { @@ -6449,9 +5632,9 @@ } }, "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", + "integrity": "sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==", "requires": { "brace-expansion": "^2.0.1" } @@ -6459,13 +5642,13 @@ } }, "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", + "minipass": "^4.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" @@ -6477,12 +5660,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6508,6 +5685,17 @@ "dev": true, "requires": { "nopt": "~1.0.10" + }, + "dependencies": { + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "requires": { + "abbrev": "1" + } + } } }, "tr46": { @@ -6516,14 +5704,14 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "ts-mixer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz", - "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==" + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", + "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" }, "ts-node": { - "version": "10.8.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.1.tgz", - "integrity": "sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, "requires": { "@cspotcode/source-map-support": "^0.8.0", @@ -6542,9 +5730,9 @@ } }, "tsc-alias": { - "version": "1.6.11", - "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.6.11.tgz", - "integrity": "sha512-mXEM21WriTJMQyo07B4Kc2nNFFk/1qOjU+jZ0ymXOyLz/A8J+dIBkimqZrh3s/x1qLGoJ1cNZQxa8GGoWOGX1Q==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.3.tgz", + "integrity": "sha512-/9JARcmXBrEqSuLjdSOqxY7/xI/AnvmBi4CU9/Ba2oX6Oq8vnd0OGSQTk+PIwqWJ5ZxskV0X/x15yzxCNTHU+g==", "dev": true, "requires": { "chokidar": "^3.5.3", @@ -6556,9 +5744,9 @@ } }, "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "tsutils": { "version": "3.21.0", @@ -6592,19 +5780,10 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", + "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", "dev": true }, "undefsafe": { @@ -6614,17 +5793,11 @@ "dev": true }, "undici": { - "version": "5.9.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.9.1.tgz", - "integrity": "sha512-6fB3a+SNnWEm4CJbgo0/CWR8RGcOCQP68SF4X0mxtYTq2VNN8T88NYrWVBAeSX+zb7bny2dx2iYhP3XHi00omg==" - }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.21.0.tgz", + "integrity": "sha512-HOjK8l6a57b2ZGXOcUsI5NLfoTrfmbOl90ixJDl0AEFG4wgHNDQxtZy15/ZQp7HhjkpaGlp/eneMgtsu1dIlUA==", "requires": { - "crypto-random-string": "^2.0.0" + "busboy": "^1.6.0" } }, "universalify": { @@ -6632,28 +5805,6 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, - "update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", - "dev": true, - "requires": { - "boxen": "^5.0.0", - "chalk": "^4.1.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.4.0", - "is-npm": "^5.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.1.0", - "pupa": "^2.1.1", - "semver": "^7.3.4", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - } - }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -6663,26 +5814,11 @@ "punycode": "^2.1.0" } }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", - "dev": true, - "requires": { - "prepend-http": "^2.0.0" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -6720,15 +5856,6 @@ "string-width": "^1.0.2 || 2 || 3 || 4" } }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "requires": { - "string-width": "^4.0.0" - } - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -6750,30 +5877,12 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, "ws": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", - "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "requires": {} }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true - }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -6785,17 +5894,17 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "requires": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" } }, "yargs-parser": { @@ -6808,6 +5917,12 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index 662550b..7e7dec2 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,8 @@ }, "homepage": "https://github.com/codedrunks/BrewBot#readme", "devDependencies": { - "@types/fs-extra": "^9.0.13", - "@types/node": "^17.0.23", + "@types/fs-extra": "^11.0.1", + "@types/node": "^18.15.3", "@types/prompts": "^2.0.14", "@types/steamapi": "^2.2.2", "@types/yargs": "^17.0.12", @@ -38,20 +38,20 @@ "prompts": "^2.4.2", "ts-node": "^10.7.0", "tsc-alias": "^1.6.11", - "typescript": "^4.6.3" + "typescript": "^5.0.2" }, "dependencies": { - "@discordjs/rest": "^0.5.0", + "@discordjs/rest": "^1.6.0", "@prisma/client": "^4.3.1", - "axios": "^0.27.2", + "axios": "^1.3.4", "better-erela.js-spotify": "^1.3.8", "canvas": "^2.9.3", "discord-api-types": "^0.37.3", - "discord.js": "^14.2.0", + "discord.js": "^14.8.0", "dotenv": "^16.0.0", "erela.js": "^2.3.3", "fast-memoize": "^2.5.2", - "fs-extra": "^10.1.0", + "fs-extra": "^11.1.0", "fuse.js": "^6.6.2", "kleur": "^4.1.4", "nanoid": "^3.3.4", @@ -80,4 +80,4 @@ "prisma": { "seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts" } -} +} \ No newline at end of file From b0862734cf4cde7789279af6d13e476dfc890c4a Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 18 Mar 2023 21:21:15 +0100 Subject: [PATCH 19/40] fix: random errors --- src/commands/mod/Log.ts | 7 ++++--- src/commands/util/Avatar.ts | 4 ++-- src/database/economy.ts | 4 ++-- src/settings.ts | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/commands/mod/Log.ts b/src/commands/mod/Log.ts index 74b5077..4247d3b 100644 --- a/src/commands/mod/Log.ts +++ b/src/commands/mod/Log.ts @@ -1,4 +1,4 @@ -import { CommandInteraction, TextChannel, EmbedBuilder, ColorResolvable, ApplicationCommandOptionType, ChannelType } from "discord.js"; +import { CommandInteraction, TextChannel, EmbedBuilder, ColorResolvable, ApplicationCommandOptionType, ChannelType, TextBasedChannel } from "discord.js"; import k from "kleur"; import { Command } from "@src/Command"; import { settings } from "@src/settings"; @@ -38,7 +38,9 @@ export class Log extends Command { } async run(int: CommandInteraction): Promise { - const { guild, channel } = int; + const { guild } = int; + + const channel = int.channel as TextBasedChannel; if(!guild || !channel) return this.reply(int, embedify("This command can only be used in a server.", settings.embedColors.error), true); @@ -82,7 +84,6 @@ export class Log extends Command { channel.messages.fetch({ limit: amount, before: startMessageID }) .then(async (messages) => { - messages.set(startMessageID!, await channel.messages.fetch(startMessageID!)); const lastMessage = messages?.first(); diff --git a/src/commands/util/Avatar.ts b/src/commands/util/Avatar.ts index 3d00397..3fa3f43 100644 --- a/src/commands/util/Avatar.ts +++ b/src/commands/util/Avatar.ts @@ -53,7 +53,7 @@ export class Avatar extends Command } catch(err) { - status = err instanceof AxiosError ? parseInt(err.status ?? "415") : 415; + status = err instanceof AxiosError ? Number(err.status ?? 415) : 415; } const avatarUrl = (status >= 400 ? usr.avatarURL({ extension: "png", size: 4096 }) : requestedAvUrl); @@ -64,7 +64,7 @@ export class Avatar extends Command .setTitle(`Avatar of ${usr.username}:`) .setColor(settings.embedColors.default) .setImage(avatarUrl); - format && ebd.setFooter({ text: `[${format.toUpperCase()}]` }); + format && ebd.setFooter({ text: `[${format?.toUpperCase()}]` }); return await this.editReply(int, ebd); } diff --git a/src/database/economy.ts b/src/database/economy.ts index 7da6ad3..76d1450 100644 --- a/src/database/economy.ts +++ b/src/database/economy.ts @@ -1,7 +1,7 @@ import { prisma } from "@database/client"; -import { PrismaPromise } from "@prisma/client"; import { getRedis } from "@src/redis"; import { nowInSeconds } from "@utils/time"; +import { Prisma } from "@prisma/client"; const redis = getRedis(); @@ -204,7 +204,7 @@ export async function incrementTotalWorks(userId: string, guildId: string, by?: export async function addOrSubCoinsToMultipleUsers(users: string[], guildId: string, coins: number): Promise { - const txQueue: PrismaPromise[] = []; // eslint-disable-line + const txQueue: Prisma.PrismaPromise[] = []; // eslint-disable-line for(let i = 0; i < users.length; i++) { txQueue.push( diff --git a/src/settings.ts b/src/settings.ts index 5685c2c..8b3ff73 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -79,7 +79,7 @@ export function getEnvVar(varName: string, asType: "stringArray"): undefined | s /** Grabs an environment variable's value, and casts it to a `number[]` */ export function getEnvVar(varName: string, asType: "numberArray"): undefined | number[] /** Grabs an environment variable's value, and casts it to a specific type (default string) */ -export function getEnvVar(varName: string, asType: T = "string" as T): undefined | (string | number | string[] | number[]) +export function getEnvVar(varName: string, asType: T = "string" as T): undefined | (string | number | string[] | number[]) { const val = process.env[varName]; From 4f6bd1ebfe4cce51ed92353bf62163ae7499c56e Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 18 Mar 2023 22:16:51 +0100 Subject: [PATCH 20/40] fix: another error --- src/commands/mod/Log.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/mod/Log.ts b/src/commands/mod/Log.ts index 4247d3b..3400308 100644 --- a/src/commands/mod/Log.ts +++ b/src/commands/mod/Log.ts @@ -1,4 +1,4 @@ -import { CommandInteraction, TextChannel, EmbedBuilder, ColorResolvable, ApplicationCommandOptionType, ChannelType, TextBasedChannel } from "discord.js"; +import { CommandInteraction, TextChannel, EmbedBuilder, ColorResolvable, ApplicationCommandOptionType, ChannelType, TextBasedChannel, Message, Collection } from "discord.js"; import k from "kleur"; import { Command } from "@src/Command"; import { settings } from "@src/settings"; @@ -83,7 +83,7 @@ export class Log extends Command { let newEmbedColor: ColorResolvable = embedColors[0]; channel.messages.fetch({ limit: amount, before: startMessageID }) - .then(async (messages) => { + .then(async (messages: Collection) => { messages.set(startMessageID!, await channel.messages.fetch(startMessageID!)); const lastMessage = messages?.first(); From 6c8757d6cc06c249003bc6361e91c3fc5d8dd984 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sat, 18 Mar 2023 22:34:06 +0100 Subject: [PATCH 21/40] remove emoji ctx command for now --- src/context/Emoji.ts | 20 -------------------- src/context/index.ts | 2 -- 2 files changed, 22 deletions(-) delete mode 100644 src/context/Emoji.ts diff --git a/src/context/Emoji.ts b/src/context/Emoji.ts deleted file mode 100644 index 6f026c7..0000000 --- a/src/context/Emoji.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { CtxMenu } from "@src/CtxMenu"; -import { ApplicationCommandType } from "discord-api-types/v10"; -import { ContextMenuCommandInteraction } from "discord.js"; - -export class Emoji extends CtxMenu { - constructor() { - super({ - name: "template", - type: ApplicationCommandType.User, - }); - } - - async run(int: ContextMenuCommandInteraction) { - // this condition will never be true, it's just for TS to shut up - if(!int.isMessageContextMenuCommand()) - return; - - - } -} diff --git a/src/context/index.ts b/src/context/index.ts index 0ec1b8a..4bac29c 100644 --- a/src/context/index.ts +++ b/src/context/index.ts @@ -1,5 +1,4 @@ import { DeleteBelow } from "./DeleteBelow"; -import { Emoji } from "./Emoji"; import { ResetNickname } from "./ResetNickname"; @@ -8,7 +7,6 @@ import { ResetNickname } from "./ResetNickname"; export const contextMenus = [ // message DeleteBelow, - Emoji, // user ResetNickname, From a0797f7430e75efe9d927d730fd19839b0305a22 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sun, 19 Mar 2023 00:01:45 +0100 Subject: [PATCH 22/40] refactor: deprecate replyOpts, consolidate BM & PE --- src/utils/BtnMsg.ts | 9 +++++---- src/utils/PageEmbed.ts | 14 +++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/utils/BtnMsg.ts b/src/utils/BtnMsg.ts index 0334252..3051675 100644 --- a/src/utils/BtnMsg.ts +++ b/src/utils/BtnMsg.ts @@ -30,7 +30,7 @@ export type ButtonsTuple = Tuple, 1|2|3|4|5>; export class BtnMsg extends EmitterBase { readonly btns: ButtonBuilder[][]; - readonly msg: string | EmbedBuilder[]; + readonly msg: string | EmbedBuilder[] | null; readonly opts: BtnMsgOpts; @@ -43,10 +43,10 @@ export class BtnMsg extends EmitterBase * Wrapper for discord.js' `ButtonBuilder` * Contains convenience methods for easier creation of messages with attached buttons * Use `.on("press")` to listen for button presses - * @param message The message or reply content + * @param message The message or reply content - set to null if you don't need a content * @param buttons Up to 5 rows of 5 ButtonBuilder instances - customIDs will be managed by this BtnMsg */ - constructor(message: string | EmbedBuilder | EmbedBuilder[], buttons: ButtonBuilder | ButtonsTuple, options?: Partial) + constructor(message: string | EmbedBuilder | EmbedBuilder[] | null, buttons: ButtonBuilder | ButtonsTuple, options?: Partial) { super(); @@ -120,6 +120,7 @@ export class BtnMsg extends EmitterBase * @example ```ts * await int.reply(new BtnMsg().getReplyOpts()) * ``` + * @deprecated Should be replaced with `getMsgOpts()` */ public getReplyOpts() { @@ -142,7 +143,7 @@ export class BtnMsg extends EmitterBase embeds: this.msg, ...btns, } : { - content: this.msg, + content: this.msg ?? undefined, ...btns, }; } diff --git a/src/utils/PageEmbed.ts b/src/utils/PageEmbed.ts index 4225e29..7e7d837 100644 --- a/src/utils/PageEmbed.ts +++ b/src/utils/PageEmbed.ts @@ -413,7 +413,7 @@ export class PageEmbed extends EmitterBase } /** Returns properties that can be used to send or edit messages */ - public getMsgProps(disableBtns = false) + public getMsgOpts(disableBtns = false) { if(this.pages.length === 0) return { embeds: [], components: [] }; @@ -439,7 +439,7 @@ export class PageEmbed extends EmitterBase public async sendIn(channel: TextBasedChannel) { this.pageIdx = 0; - return this.msg = await channel.send(this.getMsgProps()); + return this.msg = await channel.send(this.getMsgOpts()); } /** Replies to a passed interaction with this PageEmbed */ @@ -448,7 +448,7 @@ export class PageEmbed extends EmitterBase if(this.getPageIdx() < 0) this.setPageIdx(0); - return int.reply({ ...this.getMsgProps(), ephemeral }); + return int.reply({ ...this.getMsgOpts(), ephemeral }); } /** Edits a passed interaction with the content of this PageEmbed */ @@ -457,7 +457,7 @@ export class PageEmbed extends EmitterBase if(this.getPageIdx() < 0) this.setPageIdx(0); - return int.editReply(this.getMsgProps()); + return int.editReply(this.getMsgOpts()); } /** Edits the message with the currently stored local `msg` with this PageEmbed's content */ @@ -466,7 +466,7 @@ export class PageEmbed extends EmitterBase if(this.timedOut) removeButtons = true; - const msgProps = this.getMsgProps(removeButtons); + const msgProps = this.getMsgOpts(removeButtons); if(this.int) { @@ -524,8 +524,8 @@ export class PageEmbed extends EmitterBase const updatePageEbd = async () => { int.replied || int.deferred - ? await int.editReply(this.getMsgProps()) - : await int.reply({ ...this.getMsgProps(), ephemeral }); + ? await int.editReply(this.getMsgOpts()) + : await int.reply({ ...this.getMsgOpts(), ephemeral }); }; await updatePageEbd(); From 90a153dbb8ceb9b9cdc6bff671da8b345c25a748 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sun, 19 Mar 2023 00:02:10 +0100 Subject: [PATCH 23/40] refactor: replace deprecated enum values --- src/Command.ts | 4 ++-- src/commands/mod/Log.ts | 2 +- src/commands/util/Server.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Command.ts b/src/Command.ts index 6681485..aedd317 100644 --- a/src/Command.ts +++ b/src/Command.ts @@ -96,7 +96,7 @@ export abstract class Command opt.setName(arg.name) .setDescription(arg.desc) .setRequired(arg.required ?? false) - .addChannelTypes(ChannelType.GuildText, ChannelType.GuildNews, ChannelType.GuildPublicThread, ChannelType.GuildPrivateThread, ChannelType.GuildVoice) + .addChannelTypes(ChannelType.GuildText, ChannelType.GuildAnnouncement, ChannelType.PublicThread, ChannelType.PrivateThread, ChannelType.GuildVoice) ); else if(arg.type === ApplicationCommandOptionType.Role) data.addRoleOption(opt => @@ -187,7 +187,7 @@ export abstract class Command opt.setName(arg.name) .setDescription(arg.desc) .setRequired(arg.required ?? false) - .addChannelTypes(ChannelType.GuildText, ChannelType.GuildNews, ChannelType.GuildPublicThread, ChannelType.GuildPrivateThread, ChannelType.GuildVoice) + .addChannelTypes(ChannelType.GuildText, ChannelType.GuildAnnouncement, ChannelType.PublicThread, ChannelType.PrivateThread, ChannelType.GuildVoice) ); else if(arg.type === ApplicationCommandOptionType.Role) sc.addRoleOption(opt => diff --git a/src/commands/mod/Log.ts b/src/commands/mod/Log.ts index 3400308..be3fd14 100644 --- a/src/commands/mod/Log.ts +++ b/src/commands/mod/Log.ts @@ -65,7 +65,7 @@ export class Log extends Command { } try { - const chanTypes = [ChannelType.GuildText, ChannelType.GuildNews, ChannelType.GuildPublicThread, ChannelType.GuildPrivateThread, ChannelType.GuildVoice]; + const chanTypes = [ChannelType.GuildText, ChannelType.AnnouncementThread, ChannelType.PublicThread, ChannelType.PrivateThread, ChannelType.GuildVoice]; if (chanTypes.includes(channel?.type)) { if(!start) { channel.messages.fetch({ limit: 1 }).then(messages => { diff --git a/src/commands/util/Server.ts b/src/commands/util/Server.ts index 5f7d540..4d0c2a5 100644 --- a/src/commands/util/Server.ts +++ b/src/commands/util/Server.ts @@ -67,7 +67,7 @@ export class Server extends Command const botMembers = guild.members.cache.filter(m => m.user.bot).size ?? undefined; const onlineMembers = botMembers ? guild.members.cache.filter(m => (!m.user.bot && ["online", "idle", "dnd"].includes(m.presence?.status ?? "_"))).size : undefined; - const publicTxtChannelsAmt = guild.channels.cache.filter(ch => [ChannelType.GuildText, ChannelType.GuildPublicThread, ChannelType.GuildPrivateThread, ChannelType.GuildForum].includes(ch.type) && ch.permissionsFor(guild.roles.everyone).has(PermissionFlagsBits.ViewChannel)).size; + const publicTxtChannelsAmt = guild.channels.cache.filter(ch => [ChannelType.GuildText, ChannelType.GuildAnnouncement, ChannelType.PublicThread, ChannelType.PrivateThread, ChannelType.GuildForum].includes(ch.type) && ch.permissionsFor(guild.roles.everyone).has(PermissionFlagsBits.ViewChannel)).size; const publicVoiceChannelsAmt = guild.channels.cache.filter(ch => ch.type === ChannelType.GuildVoice && ch.permissionsFor(guild.roles.everyone).has(PermissionFlagsBits.Speak)).size; let memberCount = `Total: ${allMembers}`; From bef89c062315ba90e05d01074d10883ea16c1eb0 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sun, 19 Mar 2023 00:02:16 +0100 Subject: [PATCH 24/40] chore: readme --- src/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/README.md b/src/README.md index 9aae74f..4be5287 100644 --- a/src/README.md +++ b/src/README.md @@ -214,8 +214,7 @@ Markdown that isn't allowed anywhere: > > #### Methods: > - `destroy()` emits the `destroy` event, removes all event listeners and tells the registry to deregister this BtnMsg -> - `getReplyOpts()` returns properties that can be spread onto an interaction reply like `int.reply({ ...btmsg.getReplyOpts(), foo: "bar" })` -> - `getMsgOpts()` same as `getReplyOpts()` but for sending a message with `channel.send()` +> - `getMsgOpts()` returns properties that can be passed to or spread onto reply options or "send message" options > - `sendIn()` sends this BtnMsg in the provided channel > > #### Events: From aea90169afa4f08b7443d90d323b6117f3aea626 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sun, 19 Mar 2023 00:58:34 +0100 Subject: [PATCH 25/40] feat: shit that almost works but it might as well be completely broken --- package.json | 2 +- src/README.md | 18 +++--- src/commands/util/Reminder.ts | 105 ++++++++++++++++++++-------------- 3 files changed, 73 insertions(+), 52 deletions(-) diff --git a/package.json b/package.json index 7e7dec2..ab76614 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "predeploy": "npx prisma generate && npx prisma migrate deploy", "deploy": "tsc && tsc-alias && node out/bot.js", "win-redis": "call src\\tools\\redis.bat", - "link": "npm link" + "cli": "node --enable-source-maps out/tools/cli/index.js" }, "repository": { "type": "git", diff --git a/src/README.md b/src/README.md index 4be5287..9fce8d5 100644 --- a/src/README.md +++ b/src/README.md @@ -125,14 +125,16 @@ See `brewbot -h` for help. ### General | Command | Description | | --- | --- | -| `npm start` | start the bot regularly | -| `npm run watch` | start the bot and watch for file changes to recompile automatically | -| `npm run lint` | lints the code with eslint | -| `npm test` | runs the script at `src/test.ts` | -| `npm run clearCommands` | clears all global and guild commands (takes a few minutes) | -| `npm run deploy` | runs prisma deployment scripts and launches the bot without watching | -| `npm run predeploy` | only runs prisma deployment scripts without launching the bot | -| `npm run win-redis` | use this command on Windows devices to launch redis-server in a WSL window | +| `npm start` | Start the bot regularly | +| `npm run watch` | Start the bot and watch for file changes to recompile automatically | +| `npm run lint` | Lints the code with eslint | +| `npm test` | Runs the script at `src/test.ts` | +| `npm run clearCommands` | Clears all global and guild commands (takes a few minutes) | +| `npm run deploy` | Runs prisma deployment scripts and launches the bot without watching | +| `npm run predeploy` | Only runs prisma deployment scripts without launching the bot | +| `npm run win-redis` | (Windows only) Launches redis-server in a new WSL window | +| `npm link` then `brewbot ` | (Unix only) Runs the BrewBot CLI. Use -h to list all commands. | +| `npm run cli -- ` | (Windows only) Runs the BrewBot CLI. Use -h to list all commands. |
diff --git a/src/commands/util/Reminder.ts b/src/commands/util/Reminder.ts index 7cf8a16..99ede4f 100644 --- a/src/commands/util/Reminder.ts +++ b/src/commands/util/Reminder.ts @@ -1,24 +1,18 @@ -import { ActionRowBuilder, ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ChannelType, Client, CommandInteraction, CommandInteractionOption, EmbedBuilder, Message, TextBasedChannel } from "discord.js"; +import { ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ChannelType, Client, CommandInteraction, CommandInteractionOption, EmbedBuilder, Message, TextBasedChannel } from "discord.js"; import k from "kleur"; -import { Command } from "@src/Command"; -import { settings } from "@src/settings"; import { time } from "@discordjs/builders"; -import { createNewUser, deleteReminder, deleteReminders, getExpiredReminders, getReminder, getReminders, getUser, setReminder } from "@src/database/users"; import { Reminder as ReminderObj } from "@prisma/client"; +import { Command } from "@src/Command"; +import { settings } from "@src/settings"; import { autoPlural, BtnMsg, ButtonsTuple, embedify, PageEmbed, timeToMs, toUnix10, useEmbedify } from "@src/utils"; +import { createNewUser, deleteReminder, deleteReminders, getExpiredReminders, getReminder, getReminders, getUser, setReminder } from "@src/database/users"; import { Tuple } from "@src/types"; /** Max reminders per user (global) */ const reminderLimit = 10; const reminderCheckInterval = 2000; -/** To not exceed the embed limits */ +/** To not exceed the embed limits & strain the DB */ const maxNameLength = 250; -/** - * Contains all compound keys of reminders that are currently being checked. - * This is necessary because the check could take longer than `reminderCheckInterval` and check the same reminder twice. - * Format: `userId-reminderId` - */ -const reminderCheckBuffer = new Set(); export class Reminder extends Command { @@ -184,7 +178,7 @@ export class Reminder extends Command const setNewReminder = async (name: string, dueTimestamp: Date, ephemeral: boolean) => { if(name.length > maxNameLength) - return this.reply(int, embedify(`Please enter a name that's not longer than ${maxNameLength} characters`, settings.embedColors.error)); + return this.reply(int, embedify(`Please enter a name that's no longer than ${maxNameLength} characters`, settings.embedColors.error)); await this.deferReply(int, ephemeral); @@ -368,7 +362,7 @@ export class Reminder extends Command const deleteRem = async ({ reminderId, name }: ReminderObj) => { await deleteReminder(reminderId, user.id); - return await int.editReply(useEmbedify(`Successfully deleted the reminder \`${name}\``, settings.embedColors.default)); + return await int.editReply(useEmbedify(`Successfully deleted the following reminder:\n> ${name.replace(/\n/gm, "\n> ")}`, settings.embedColors.default)); }; const notFound = () => int.editReply(useEmbedify("Couldn't find a reminder with this name.\nUse `/reminder list` to list all your reminders and their IDs.", settings.embedColors.error)); @@ -459,6 +453,15 @@ export class Reminder extends Command } //#MARKER check reminders + +const rescheduleBtn = new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ"); +/** + * Contains all compound keys of reminders that are currently being checked. + * This is necessary because the check could take longer than `reminderCheckInterval` and check the same reminder twice. + * Format: `userId-reminderId` + */ +const reminderCheckBuffer = new Set(); + async function checkReminders(client: Client) { const expRems = await getExpiredReminders(); @@ -469,7 +472,7 @@ async function checkReminders(client: Client) const promises: Promise[] = []; const getExpiredEbd = ({ name }: ReminderObj) => new EmbedBuilder() - .setDescription(`Your reminder has expired:\n> ${name.replace(/\n/gm, "\n> ")}`) + .setDescription(name) .setColor(settings.embedColors.default); // TODO: add logger @@ -483,6 +486,10 @@ async function checkReminders(client: Client) /** null is used to pad to a new component row */ const reschedBtns = [ + { + label: "+ 2m", + val: 2 * min, + }, { label: "+ 5m", val: 5 * min, @@ -513,17 +520,16 @@ async function checkReminders(client: Client) }, { label: "+ 3d", - val: 6 * hr, + val: 3 * day, }, { label: "+ 7d", - val: 6 * hr, + val: 7 * day, }, - null, { val: 0, - label: "Submit", - btn: new ButtonBuilder().setStyle(ButtonStyle.Primary).setLabel("Submit"), + label: "Reschedule", + btn: new ButtonBuilder().setStyle(ButtonStyle.Success).setLabel("Reschedule"), }, { val: 0, @@ -536,13 +542,14 @@ async function checkReminders(client: Client) btn: new ButtonBuilder().setStyle(ButtonStyle.Secondary).setLabel("Reset"), }, ].map((props) => (props ? { - ...props, btn: new ButtonBuilder().setStyle(ButtonStyle.Secondary).setLabel(props.label), + ...props, } : null)); const getEbd = (rem: ReminderObj) => new EmbedBuilder() .setColor(settings.embedColors.default) - .setDescription(`Rescheduling the reminder.\nPress any of the buttons below to add time onto this reminder.\n\nCurrent expiry: `); + .setDescription(`Rescheduling the following reminder:\n> ${rem.name.replace(/\n/gm, "\n> ")}\n\nCurrent expiry: `) + .setFooter({ text: "Press any of the buttons below to add time onto this reminder." }); const ebd = getEbd(rem); @@ -550,7 +557,7 @@ async function checkReminders(client: Client) const slicedBtns: ButtonBuilder[][] = []; while(slicedBtnsInput.length > 0) slicedBtns.push(slicedBtnsInput.splice(0, 5).filter(b => b !== null) as ButtonBuilder[]); - + const editReschedBm = new BtnMsg(ebd, slicedBtns as ButtonsTuple); const newReminder = { ...rem }; @@ -558,13 +565,13 @@ async function checkReminders(client: Client) /** Adds the `value` in milliseconds to the newReminder */ const addValueToReminder = (value: number) => { newReminder.dueTimestamp = new Date(newReminder.dueTimestamp.getTime() + value); - msg.edit({ ...editReschedBm.getMsgOpts(), embeds: [ getEbd(newReminder) ]}); + msg.edit({ ...editReschedBm.getMsgOpts(), content: "", embeds: [ getEbd(newReminder) ]}); }; /** Resets the rescheduled reminder time back to the original */ const resetRescheduledReminder = () => { newReminder.dueTimestamp = new Date(rem.dueTimestamp.getTime()); - msg.edit({ ...editReschedBm.getMsgOpts(), embeds: [ getEbd(newReminder) ]}); + msg.edit({ ...editReschedBm.getMsgOpts(), content: "", embeds: [ getEbd(newReminder) ]}); }; /** Sets a new reminder */ @@ -580,30 +587,32 @@ async function checkReminders(client: Client) await setReminder(rem); - return await msg.edit(useEmbedify(`I've rescheduled your reminder:\n> ${rem.name}\n> Now due on ${time(toUnix10(rem.dueTimestamp), "f")}\n\nID: \`${reminderId}\` â€Ē To list your reminders use \`/reminder list\``, settings.embedColors.success)); + return await msg.edit({ + ...useEmbedify(`I've rescheduled your reminder:\n> ${rem.name}\n> Now due on ${time(toUnix10(rem.dueTimestamp), "f")}\n\nID: \`${reminderId}\` â€Ē To list your reminders use \`/reminder list\``, settings.embedColors.success), + content: "", + components: [], + }); }; /** Cancels the reminder rescheduling */ const cancelRescheduling = () => { - if(!editReschedBm.isDestroyed()) - editReschedBm.destroy(); msg.edit({ - ...editReschedBm.getMsgOpts(), + content: `🔔 <@${rem.userId}>, your reminder expired!`, embeds: [ getExpiredEbd(rem) ], - components: [ - new ActionRowBuilder().setComponents( - new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ") - ), - ] + components: [], }); + + if(!editReschedBm.isDestroyed()) + editReschedBm.destroy(); }; let submitted = false, cancelled = false; - editReschedBm.on("press", (btn, int) => { + editReschedBm.on("press", (btn, btInt) => { + btInt.deferUpdate(); const reschedBt = reschedBtns.find(b => b && b.label === btn.data.label); - if(int.user.id === rem.userId && reschedBt) { - if(btn.data.label === "Submit") { + if(btInt.user.id === rem.userId && reschedBt) { + if(btn.data.label === "Reschedule") { submitted = true; editReschedBm.destroy(); return setRescheduledReminder(newReminder); @@ -625,6 +634,7 @@ async function checkReminders(client: Client) msg.edit({ ...editReschedBm.getMsgOpts(), + content: "", }); }; @@ -637,17 +647,18 @@ async function checkReminders(client: Client) const guild = client.guilds.cache.find(g => g.id === rem.guild); const chan = guild?.channels.cache.find(c => c.id === rem.channel); - if(chan && [ChannelType.GuildText, ChannelType.GuildPublicThread, ChannelType.GuildPrivateThread, ChannelType.GuildForum].includes(chan.type)) + if(chan && [ChannelType.GuildText, ChannelType.PublicThread, ChannelType.PrivateThread, ChannelType.GuildForum].includes(chan.type)) { - const reschedBm = new BtnMsg("", new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ")); + const reschedBm = new BtnMsg(null, rescheduleBtn); const msg = (chan as TextBasedChannel).send({ ...reschedBm.getMsgOpts(), - content: `🔔 Reminder! <@${rem.userId}>`, + content: `🔔 <@${rem.userId}>, your reminder expired!`, embeds: [ getExpiredEbd(rem) ], }); reschedBm.on("press", async (btn, btInt) => { + await btInt.deferUpdate(); if(btInt.user.id === rem.userId && btn.data.label === "Reschedule") editReschedMsg(msg instanceof Promise ? await msg : msg, rem); }); @@ -689,9 +700,6 @@ async function checkReminders(client: Client) const usr = client.users.cache.find(u => u.id === rem.userId); promises.push((async () => { - const reschedBtn = new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ"); - // TODO - if(!usr) return remindPublicly(rem); @@ -699,8 +707,19 @@ async function checkReminders(client: Client) { if(rem.private) { const dm = await usr.createDM(); + const reschedBm = new BtnMsg(null, rescheduleBtn); + + const msg = await dm.send({ + ...reschedBm.getMsgOpts(), + content: "🔔 Your reminder expired!", + embeds: [ getExpiredEbd(rem) ], + }); - const msg = await dm.send({ embeds: [ getExpiredEbd(rem) ]}); + reschedBm.on("press", async (btn, btInt) => { + await btInt.deferUpdate(); + if(btn.data.label === "Reschedule") + editReschedMsg(msg instanceof Promise ? await msg : msg, rem); + }); if(!dm || !msg) return remindPublicly(rem); From 1baeb91ad8c2f08f83a66281a1653f5b6ede47dc Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sun, 19 Mar 2023 01:20:45 +0100 Subject: [PATCH 26/40] fix: switch to ferret npm package --- package-lock.json | 19 +++++++++++++++++++ package.json | 3 ++- src/commands/fun/Ferret.ts | 20 ++++++++++++-------- src/commands/util/Ping.ts | 11 +++-------- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index 26b739c..a5db780 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@prisma/client": "^4.3.1", "axios": "^1.3.4", "better-erela.js-spotify": "^1.3.8", + "canarado-ferret-api": "^0.1.9", "canvas": "^2.9.3", "discord-api-types": "^0.37.3", "discord.js": "^14.8.0", @@ -933,6 +934,15 @@ "node": ">=6" } }, + "node_modules/canarado-ferret-api": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/canarado-ferret-api/-/canarado-ferret-api-0.1.9.tgz", + "integrity": "sha512-9zTd7BzEPMI4UKycqE5yRta03z5P8Oxv1w5fkvR7Q/vIdGLdjMrqGkcjUGZ14ue0ZP5VsfKYmeTZbuzMGgkG6w==", + "dependencies": { + "axios": "^1.3.4", + "form-data": "^4.0.0" + } + }, "node_modules/canvas": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.0.tgz", @@ -4106,6 +4116,15 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, + "canarado-ferret-api": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/canarado-ferret-api/-/canarado-ferret-api-0.1.9.tgz", + "integrity": "sha512-9zTd7BzEPMI4UKycqE5yRta03z5P8Oxv1w5fkvR7Q/vIdGLdjMrqGkcjUGZ14ue0ZP5VsfKYmeTZbuzMGgkG6w==", + "requires": { + "axios": "^1.3.4", + "form-data": "^4.0.0" + } + }, "canvas": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.0.tgz", diff --git a/package.json b/package.json index ab76614..a5fb714 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@prisma/client": "^4.3.1", "axios": "^1.3.4", "better-erela.js-spotify": "^1.3.8", + "canarado-ferret-api": "^0.1.9", "canvas": "^2.9.3", "discord-api-types": "^0.37.3", "discord.js": "^14.8.0", @@ -80,4 +81,4 @@ "prisma": { "seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts" } -} \ No newline at end of file +} diff --git a/src/commands/fun/Ferret.ts b/src/commands/fun/Ferret.ts index 0f7fddb..41f4123 100644 --- a/src/commands/fun/Ferret.ts +++ b/src/commands/fun/Ferret.ts @@ -1,16 +1,20 @@ import { CommandInteraction, EmbedBuilder } from "discord.js"; +import { getRandomFerret } from "canarado-ferret-api"; import { randomItem } from "svcorelib"; import { Command } from "@src/Command"; -import { axios } from "@src/utils"; import { settings } from "@src/settings"; const titles = [ "Look at this cutie", - "One ferret, coming up", + "One ferret image, coming up", "Ferret time :)", - "", + "", // requires the bot being in the CoJ server ]; +interface FerretObj { + url: string; +} + export class Ferret extends Command { constructor() @@ -27,16 +31,16 @@ export class Ferret extends Command { await this.deferReply(int); - const { data, status, statusText } = await axios.get("https://ferretapi.canarado.xyz/", { timeout: 10000 }); + const res = await getRandomFerret() as unknown as FerretObj; - if(status < 200 || status >= 300 || !data.file) - return await this.reply(int, `Ferret API is currently unreachable. Please try again later.\nStatus: ${status} - ${statusText}`, true); + if(typeof res.url !== "string") + return await this.reply(int, "Ferret API is currently unreachable. Please try again later.", true); const embed = new EmbedBuilder() .setTitle(randomItem(titles)) .setColor(settings.embedColors.default) - .setFooter({ text: "https://ferret.canarado.xyz" }) - .setImage(data.file); + .setFooter({ text: "https://ferret-api.canarado.xyz" }) + .setImage(res.url); await this.editReply(int, embed); } diff --git a/src/commands/util/Ping.ts b/src/commands/util/Ping.ts index 74dd1a9..10c16bb 100644 --- a/src/commands/util/Ping.ts +++ b/src/commands/util/Ping.ts @@ -3,7 +3,7 @@ import { isIP } from "net"; import { Command } from "@src/Command"; import { axios, embedify } from "@src/utils"; import { settings } from "@src/settings"; -import { AxiosError } from "axios"; +import { isAxiosError } from "axios"; interface MimeInfo { exts: string[]; @@ -135,7 +135,7 @@ export class Ping extends Command { const contentType = headers["content-type"]; const hstsHeader = headers["strict-transport-security"]; - const mimeType = (contentType && contentType.includes(";") ? contentType.split(";")[0] : contentType)?.trim(); + const mimeType = (contentType && contentType.includes(";") ? contentType.split(";")[0] : contentType)?.trim() ?? ""; const mimeInfo = this.MIME_MAP.get(mimeType); const hstsEnabled = hstsHeader?.toLowerCase().includes("max-age"); @@ -179,7 +179,7 @@ export class Ping extends Command { return this.editReply(int, ebd); } catch(err) { - if(Ping.isAxiosError(err)) + if(isAxiosError(err)) { const ebd = new EmbedBuilder() .setTitle("URL Information:") @@ -208,11 +208,6 @@ export class Ping extends Command { } } - static isAxiosError(val: unknown): val is AxiosError - { - return typeof val === "object" && (val as Record)?.isAxiosError === true; - } - parseUrl(urlArg: string) { try { From 43c8823fa84fee8aeed3f0880072df0956c76979 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sun, 19 Mar 2023 01:22:52 +0100 Subject: [PATCH 27/40] mfw --- src/context/DeleteBelow.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/context/DeleteBelow.ts b/src/context/DeleteBelow.ts index 73b5cb7..35745a2 100644 --- a/src/context/DeleteBelow.ts +++ b/src/context/DeleteBelow.ts @@ -2,7 +2,7 @@ import { CtxMenu } from "@src/CtxMenu"; import { settings } from "@src/settings"; import { BtnMsg, embedify, useEmbedify } from "@src/utils"; import { ApplicationCommandType, PermissionFlagsBits } from "discord-api-types/v10"; -import { ButtonBuilder, ButtonStyle, Collection, ContextMenuCommandInteraction, GuildTextBasedChannel, Message } from "discord.js"; +import { ButtonBuilder, ButtonStyle, Collection, GuildTextBasedChannel, Message, MessageContextMenuCommandInteraction } from "discord.js"; export class DeleteBelow extends CtxMenu @@ -15,7 +15,7 @@ export class DeleteBelow extends CtxMenu }); } - async run(int: ContextMenuCommandInteraction) { + async run(int: MessageContextMenuCommandInteraction) { const err = (msg?: string) => { const ebdOpts = useEmbedify(`Couldn't delete the messages${msg ? `:\n${msg}` : " due to an error."}`, settings.embedColors.error); if(int.deferred || int.replied) @@ -24,10 +24,6 @@ export class DeleteBelow extends CtxMenu int.reply({ ...ebdOpts, ephemeral: true }); }; - // this condition will never be true, it's just for TS to shut up - if(!int.isMessageContextMenuCommand()) - return; - const msg = int.targetMessage; if(!msg.member || !msg.guild) From 198c6b15aa4a101c4c227325c6ad35cb15ad37b2 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Tue, 21 Mar 2023 21:28:43 +0100 Subject: [PATCH 28/40] chore: readme --- src/README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/README.md b/src/README.md index 9fce8d5..8cd5351 100644 --- a/src/README.md +++ b/src/README.md @@ -61,8 +61,8 @@ If you want to force your commands to be updated for whatever reason, delete or ### Context menu commands: There are two types of context menus; message and user. This dictates where they will be situated in the Discord client and what properties are passed. -Use an if-condition with `int.isUserContextMenu()` and `int.isMessageContextMenu()` to tell TS what type of context menu it's dealing with, then you will be able to access the `int.targetMessage` or `int.targetUser` and `int.targetMember` props. -Other than how the commands are sent and that a user can't pass any arguments, context commands are pretty much the same as slash commands. +To tell TS what type of context menu it's dealing with, set the type of the `int` parameter of the run method to either `MessageContextMenuCommandInteraction` or `UserContextMenuCommandInteraction`, then you will be able to access the `int.targetMessage` or `int.targetUser` and `int.targetMember` props. +Other than how the commands are sent and that a user can't pass any arguments to them, context commands are pretty much the same as slash commands. To create a new context menu, use the Template.ts in `src/context/` to create a sub-class of `src/CtxMenu.ts` Make sure the file and class name are changed, and the meta object in the constructor is filled out. @@ -183,6 +183,7 @@ Interaction replies and EmbedBuilders (title, fields & description) can have: Markdown that isn't allowed anywhere: - Tables - HTML mixins (`
` etc) +- Images (`![alt](src)`)

@@ -223,7 +224,7 @@ Markdown that isn't allowed anywhere: > Use `BtnMsg.on("name", (args) => {})` to subscribe to them > - `press` is emitted whenever the button is pressed by a user and gets passed the MessageButton and ButtonInteraction instances > - `timeout` is emitted when the timeout of the BtnMsg, set in the settings object, is reached. After the timeout, the `.destroy()` method is automatically called -> - `destroy` is emitted whenever the `.destroy()` method is called and it prompts the registry to deregister this BtnMsg instance. It gets passed an array of `MessageButton.customId`'s. After this event is emitted, all previously registered event listeners will be removed and will never receive evetns again. +> - `destroy` is emitted whenever the `.destroy()` method is called and it prompts the registry to deregister this BtnMsg instance. It gets passed an array of `MessageButton.customId`'s. After this event is emitted, all previously registered event listeners will be removed and will never receive events again.
@@ -252,14 +253,14 @@ Markdown that isn't allowed anywhere:
> ### Modal -> The modal is a configurable form dialog that gets shown to a user. -> Modals only work in the desktop client, not the mobile app. +> The modal is a configurable form dialog that opens when a user runs a command. +> In the Discord app it is shown as a popup / popover form. > > This is an abstract class, so you need to create a sub-class extending `Modal` > > #### Methods: -> - `submit()` is executed when the user submitted the modal - this method needs to be overridden in a sub-class -> - `getInternalModal()` returns the modal object that needs to be passed to an interaction's `showModal()` method +> - `submit()` is executed when the user has entered all data and submitted the modal - this method needs to be overridden in a sub-class +> - `getInternalModal()` returns the modal object that needs to be passed to an interaction's `int.showModal()` method. This will actually open the modal for the user. > > #### Events: > - `destroy` gets emitted when `.destroy()` is called to trigger the registry to delete this instance From 4904e0a5491f527c6daa1e781735dccf5d304894 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Tue, 21 Mar 2023 21:34:08 +0100 Subject: [PATCH 29/40] ngl stuff doe --- src/commands/util/Reminder.ts | 6 +++++- src/context/ResetNickname.ts | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/commands/util/Reminder.ts b/src/commands/util/Reminder.ts index 99ede4f..ba088ec 100644 --- a/src/commands/util/Reminder.ts +++ b/src/commands/util/Reminder.ts @@ -1,4 +1,4 @@ -import { ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, ChannelType, Client, CommandInteraction, CommandInteractionOption, EmbedBuilder, Message, TextBasedChannel } from "discord.js"; +import { ApplicationCommandOptionType, ButtonBuilder, ButtonInteraction, ButtonStyle, ChannelType, Client, CommandInteraction, CommandInteractionOption, EmbedBuilder, Message, TextBasedChannel } from "discord.js"; import k from "kleur"; import { time } from "@discordjs/builders"; import { Reminder as ReminderObj } from "@prisma/client"; @@ -738,3 +738,7 @@ async function checkReminders(client: Client) await Promise.allSettled(promises); } + +async function rescheduleReminder(rem: ReminderObj, btnInt: ButtonInteraction) { + void "TODO"; +} diff --git a/src/context/ResetNickname.ts b/src/context/ResetNickname.ts index a1afaa0..4d62fbd 100644 --- a/src/context/ResetNickname.ts +++ b/src/context/ResetNickname.ts @@ -32,8 +32,8 @@ export class ResetNickname extends CtxMenu } catch(err) { - if(err instanceof DiscordAPIError && err.status === 403) - return int.reply({ ...useEmbedify(`I can't reset the nickname of someone as noble as <@${int.targetMember?.user?.id}>`, settings.embedColors.error), ephemeral: true }); + if(err instanceof DiscordAPIError && err.status >= 400) + return int.reply({ ...useEmbedify(`I can't reset the nickname of someone as noble as <@${int.targetMember?.user?.id}>\nOnly users with roles below the \`BrewBot\` can have their nickname reset.`, settings.embedColors.error), ephemeral: true }); } if(!int.replied) From ba685856e29c765486c26948263bc0c4414c0391 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Tue, 21 Mar 2023 23:16:24 +0100 Subject: [PATCH 30/40] when me when the --- src/context/ResetNickname.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context/ResetNickname.ts b/src/context/ResetNickname.ts index 4d62fbd..12fa7e3 100644 --- a/src/context/ResetNickname.ts +++ b/src/context/ResetNickname.ts @@ -33,7 +33,7 @@ export class ResetNickname extends CtxMenu catch(err) { if(err instanceof DiscordAPIError && err.status >= 400) - return int.reply({ ...useEmbedify(`I can't reset the nickname of someone as noble as <@${int.targetMember?.user?.id}>\nOnly users with roles below the \`BrewBot\` can have their nickname reset.`, settings.embedColors.error), ephemeral: true }); + return int.reply({ ...useEmbedify(`I can't reset the nickname of someone as noble as <@${int.targetMember?.user?.id}>\nOnly users with roles below the \`BrewBot\` role can have their nickname reset.`, settings.embedColors.error), ephemeral: true }); } if(!int.replied) From 5a9e1e330421f06c86d07e85a144f65e34fbe745 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Thu, 23 Mar 2023 16:50:20 +0100 Subject: [PATCH 31/40] refactor: remove reactionroles --- src/commands/index.ts | 2 - src/commands/mod/ReactionRoles.ts | 205 ------------------------------ src/types/index.d.ts | 19 --- 3 files changed, 226 deletions(-) delete mode 100644 src/commands/mod/ReactionRoles.ts diff --git a/src/commands/index.ts b/src/commands/index.ts index 9a5f6b0..4ef254e 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -11,7 +11,6 @@ import { Steam } from "@commands/fun/Steam"; import { Sudoku } from "@commands/games/Sudoku"; import { TwentyFortyEight } from "@commands/games/2048"; -// import { ReactionRoles } from "@commands/mod/ReactionRoles"; import { Delete } from "@commands/mod/Delete"; import { Log } from "@commands/mod/Log"; import { Say } from "@commands/mod/Say"; @@ -74,7 +73,6 @@ export const commands = [ TicTacToe, // mod - // ReactionRoles, Delete, Log, Say, diff --git a/src/commands/mod/ReactionRoles.ts b/src/commands/mod/ReactionRoles.ts deleted file mode 100644 index 63e4b25..0000000 --- a/src/commands/mod/ReactionRoles.ts +++ /dev/null @@ -1,205 +0,0 @@ -// import { Client, CommandInteraction, Message, MessageReaction, ReactionCollector, MessageEmbed, EmbedFieldData } from "discord.js"; -// import { Command } from "@src/Command"; -// import { settings } from "@src/settings"; - - -// type EmbedMsg = { -// embed: MessageEmbed, -// emojis: ReactionRole[], -// }; - -// const roles: ReactionRole[] = [ -// { id: "978021647468609606" }, // JavaScript -// { id: "979416816512278548" }, // C -// { id: "979416784610418749" }, // C++ -// { id: "978030175470096384" }, // C# -// { id: "978030210987479091" }, // TypeScript -// { id: "979416848489676842" }, // Rust -// { id: "979416971282100324" }, // Ruby -// { id: "979416891770699916" }, // Go -// { id: "979422324912697364" }, // Python - -// { id: "978030239953354862" }, // Unity -// { id: "978030260878733372" }, // Unreal -// { id: "979421553810870322" }, // Visual Studio -// { id: "979421609423147028" }, // VS Code -// { id: "979421689484046416" }, // Atom -// { id: "979421740063150090" }, // JetBrains - -// { id: "979134412589510757" }, // React -// { id: "979134509368872970" }, // Angular -// { id: "979417658011320350" }, // Vue -// { id: "979417614474428428" }, // Bootstrap -// { id: "979417464628736070" }, // Svelte -// // { emoji: "", name: "", id: "" }, // -// ].map((v, i) => ({ ...v, emoji: settings.emojiList[i] })); - -// const rolesPerMsg = 20; - -// export class ReactionRoles extends Command -// { -// constructor(client: Client) -// { -// super({ -// name: "reactionroles", -// desc: "Sends a reaction role list in the current channel", -// perms: [ "MANAGE_ROLES", "MANAGE_MESSAGES" ], -// memberPerms: [ PermissionFlagsBits.ManageRoles, PermissionFlagsBits.ManageMessages ], -// }); - -// const reactionMsgs = persistentData.get("reactionMessages"); - -// Array.isArray(reactionMsgs) && reactionMsgs.length > 0 && this.createCollectors(client, reactionMsgs); -// } - -// async run(int: CommandInteraction): Promise -// { -// await this.deferReply(int, true); - -// const { channel, guild } = int; - -// if(!channel || !guild) return; - -// const embeds = this.buildEmbeds(); - -// await guild.fetch(); -// await guild.channels.fetch(); - -// const messages: Required["reactionMessages"] = []; - -// const sentMsgs = []; -// for await(const ebd of embeds) -// { -// const m = await channel?.send({ embeds: [ ebd.embed ] }); - -// if(m) -// { -// sentMsgs.push(m); - -// for await(const em of ebd.emojis) -// await m.react(em.emoji); - -// messages.push({ id: m.id, emojis: ebd.emojis.map(e => e.emoji) }); -// } -// } - -// this.createCollectors(int.client, reactionMsgs); - -// await persistentData.set("reactionMessages", { -// guild: sentMsgs[0].guild?.id ?? int.guild?.id ?? "unknown guild", -// channel: sentMsgs[0].channel.id, -// messages, -// }); - -// await this.editReply(int, "Sent reaction roles"); -// } - -// private buildEmbeds(): EmbedMsg[] -// { -// const totalPages = Math.ceil((roles.length - 1) / rolesPerMsg); - -// const msgs: EmbedMsg[] = []; - - -// const roleList = (roles: ReactionRole[]): EmbedFieldData => ({ -// name: "Roles", -// value: roles.reduce((acc, c) => acc += `${c.emoji} <@&${c.id}>\n`, ""), -// inline: true, -// }); - -// const ebdRoles = roles; -// let pageNbr = 0; - -// while(ebdRoles.length > 0) -// { -// pageNbr++; -// const eRoles = ebdRoles.splice(0, rolesPerMsg); - -// const half = Math.ceil(eRoles.length / 2); -// const first = eRoles.slice(0, half); -// const second = eRoles.slice((eRoles.length - half) * -1); - -// const pageDisp = totalPages > 1 ? ` (${pageNbr}/${totalPages})` : ""; - -// msgs.push({ -// embed: new MessageEmbed() -// .setTitle(`Manage your roles${pageDisp}`) -// .setColor(settings.embedColors.default) -// .setFields([ roleList(first), roleList(second) ]), -// emojis: eRoles, -// }); -// } - -// return msgs; -// } - -// private async createCollectors(client: Client, messages: ReactionMsg[]) -// { -// for(const msg of messages) -// { -// // TODO: listen for all messages - -// const gld = client.guilds.cache.find(g => g.id === msg.guild); -// } -// } - -// private async createCollector(message: Message, msgEmojis: string[]) -// { -// const filter = (reaction: MessageReaction) => msgEmojis.includes(reaction.emoji.name ?? "_"); - -// // const collector = new ReactionCollector(message, { filter, dispose: true, time: 10 * 1000 }); -// const collector = new ReactionCollector(message, { filter, dispose: true, time: 24 * 60 * 60 * 1000 }); - -// collector.on("collect", async (reaction, user) => { -// const role = roles.find(r => r.emoji === reaction.emoji.name); - -// const member = message.guild?.members.cache.find(u => u.id === user.id); - -// const guildRole = message.guild?.roles.cache.find(r => r.id === role?.id); - -// if(member && guildRole) -// { -// member.roles.add(guildRole); - -// const m = await message.channel.send(`${user.username}, I gave you the role ${guildRole?.name}`); - -// setTimeout(async () => await m.delete(), 5000); -// } -// else -// { -// const m = await message.channel.send(`${user.username}, I couldn't give you that role due to an error`); - -// setTimeout(async () => await m.delete(), 5000); -// } -// }); - -// collector.on("remove", async (reaction, user) => { -// const role = roles.find(r => r.emoji === reaction.emoji.name); - -// const member = message.guild?.members.cache.find(u => u.id === user.id); - -// const guildRole = message.guild?.roles.cache.find(r => r.id === role?.id); - -// if(member && guildRole) -// { -// member.roles.remove(guildRole); - -// const m = await message.channel.send(`${user.username}, I removed your role ${guildRole?.name}`); - -// setTimeout(async () => await m.delete(), 5000); -// } -// else -// { -// const m = await message.channel.send(`${user.username}, I couldn't remove that role due to an error`); - -// setTimeout(async () => await m.delete(), 5000); -// } -// }); - -// collector.on("end", () => { -// !collector.ended && collector.stop(); - -// this.createCollectors(roles, messages); -// }); -// } -// } diff --git a/src/types/index.d.ts b/src/types/index.d.ts index c5c618f..03243ab 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -110,25 +110,6 @@ export interface PutApplicationGuildCommandsResult { version: string; } -//#SECTION reactionroles - -export interface ReactionRole { - /** Reaction emoji */ - emoji: string; - /** Role ID */ - id: string; -} - -export interface ReactionMsg { - /** Guild ID */ - guild: string; - msgs: { - /** Message ID */ - message: string; - roles: ReactionRole[]; - }[]; -} - //#MARKER events /** Client event names */ From 0c8c0c9410a15115dbdc6fe3972ed898ddacf94c Mon Sep 17 00:00:00 2001 From: Sv443 Date: Fri, 24 Mar 2023 15:46:12 +0100 Subject: [PATCH 32/40] refactor: /define and Command.useButtons stuffs --- src/Command.ts | 14 +++++++------- src/commands/util/Define.ts | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Command.ts b/src/Command.ts index aedd317..8fbf42c 100644 --- a/src/Command.ts +++ b/src/Command.ts @@ -362,20 +362,20 @@ export abstract class Command //#SECTION static /** - * Returns an object from passed buttons that can be spread onto an interaction reply - * Returns an empty object if no buttons were passed, so it's always safe to spread + * Returns an object from passed buttons that can be passed to or spread onto an interaction reply * @example ```ts - * await int.reply({ ...Command.useButtons(btns), content: "foo" }); + * await int.reply(Command.useButtons(btns)); + * await channel.send({ ...Command.useButtons(btns), content: "foo", embeds: [] }); * ``` */ public static useButtons(buttons?: ButtonBuilder | Tuple, 1|2|3|4|5>): { components: ActionRowBuilder[] } { const actRows = Array.isArray(buttons) ? buttons : (buttons ? [[buttons]] : []); - const rows: ActionRowBuilder[] = []; - actRows.forEach(row => { - rows.push(new ActionRowBuilder().setComponents(row)); - }); + const rows = actRows.reduce[]>((a, row) => { + a.push(new ActionRowBuilder().setComponents(row)); + return a; + }, []); return { components: rows }; } diff --git a/src/commands/util/Define.ts b/src/commands/util/Define.ts index cebc102..07775bc 100644 --- a/src/commands/util/Define.ts +++ b/src/commands/util/Define.ts @@ -2,7 +2,7 @@ import { CommandInteraction, ButtonBuilder, EmbedBuilder, ButtonStyle, Applicati import { embedify, useEmbedify } from "@utils/embedify"; import { Command } from "@src/Command"; import { settings } from "@src/settings"; -import { followRedirects, rankVotes, axios, emojis } from "@src/utils"; +import { followRedirects, rankVotes, axios, emojis, autoPlural } from "@src/utils"; import { Tuple } from "@src/types"; type WikiArticle = { @@ -238,8 +238,8 @@ export class Define extends Command return { word: data.word, phonetic: data.phonetic, - partOfSpeech: meanings ? meanings[0]?.partOfSpeech : undefined, - definitions: meanings ? meanings[0].definitions.map((d: Record) => d.definition).slice(0, 8) : undefined, + partOfSpeech: meanings?.[0]?.partOfSpeech, + definitions: meanings?.[0]?.definitions?.map((d: Record) => d.definition)?.slice(0, 8), pronounciation: Array.isArray(data.phonetics) && data.phonetics.length > 0 ? data.phonetics[0]?.audio : undefined, source: Array.isArray(data.sourceUrls) ? data.sourceUrls[0] : data.sourceUrls, }; @@ -249,8 +249,8 @@ export class Define extends Command const desc = [ `**${entry.word}** ${entry.partOfSpeech ? `(${entry.partOfSpeech}) ` : ""}${entry.phonetic ? `\`${entry.phonetic}\`` : ""}\n`, - `Definition${entry.definitions?.length === 1 ? "" : "s"}:`, - entry.definitions ? `- ${entry.definitions.join("\n- ")}` : "(no definitions found)", + `${autoPlural("Definition", entry.definitions ?? 1)}:`, + entry.definitions ? `- ${entry.definitions.join("\n- ")}` : "(no definition found)", ].join("\n"); embed.setTitle(`Dictionary entry for **${term}**:`) From 1e96b5bc9704919665c1bced174ea9775e63cd69 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sun, 9 Apr 2023 20:30:22 +0200 Subject: [PATCH 33/40] feat: add env toggle for music cmds --- .env.template | 29 ++++++++++++++++++----------- src/commands/music/Dj.ts | 3 +++ src/commands/music/Filter.ts | 3 +++ src/commands/music/NowPlaying.ts | 3 +++ src/commands/music/Pause.ts | 3 +++ src/commands/music/Play.ts | 3 +++ src/commands/music/Premium.ts | 2 ++ src/commands/music/Queue.ts | 3 +++ src/commands/music/Remove.ts | 3 +++ src/commands/music/Repeat.ts | 3 +++ src/commands/music/Resume.ts | 3 +++ src/commands/music/Search.ts | 3 +++ src/commands/music/Shuffle.ts | 3 +++ src/commands/music/Skip.ts | 3 +++ src/commands/music/Stop.ts | 3 +++ src/commands/music/Volume.ts | 3 +++ src/lavalink/client.ts | 6 ++++++ 17 files changed, 68 insertions(+), 11 deletions(-) diff --git a/.env.template b/.env.template index f7d2092..d0832ae 100644 --- a/.env.template +++ b/.env.template @@ -2,22 +2,29 @@ BOT_TOKEN=123 CLIENT_ID=123 # Also called Application ID -# Dependencies (optional) -STEAM_TOKEN=123 # https://steamcommunity.com/dev/apikey -GENIURL_TOKEN= # https://api.sv443.net/geniurl +# Database +DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" #connection string -# These are both optional, and if not present, spotify can be scraped -SPOTIFY_CLIENT_ID=123123123 # https://developer.spotify.com/dashboard/ -SPOTIFY_CLIENT_SECRET=123123123 -# Settings +# Client Settings COMMAND_PREFIX="" # Set to something like an abbreviation of the client's name so all commands have that prefix and can be distinguished better - empty for none DEV_IDS="123,456" # All user IDs that should have dev perms BELL_ON_READY=false # Set to true to send a console bell sound when the client is ready -EXEC_CMD_ENABLED=true # Set to false to disable the /exec command -# Database -DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" #connection string -# Lavalink +# Commands +EXEC_CMD_ENABLED=false # Set to true to enable the /exec command +MUSIC_CMDS_ENABLED=false # Set to true to enable the VC music commands + + +# Dependencies +STEAM_TOKEN=123 # From https://steamcommunity.com/dev/apikey + +GENIURL_TOKEN= # See https://api.sv443.net/geniurl + + LAVALINK_HOSTS="ip.to.lavalink.node:somepassword,another.ip.to.another.node:anotherpassword" + +# These are both optional, and if not present, spotify can be scraped +SPOTIFY_CLIENT_ID=123123123 # https://developer.spotify.com/dashboard/ +SPOTIFY_CLIENT_SECRET=123123123 \ No newline at end of file diff --git a/src/commands/music/Dj.ts b/src/commands/music/Dj.ts index cc76a3c..9e1cfca 100644 --- a/src/commands/music/Dj.ts +++ b/src/commands/music/Dj.ts @@ -2,6 +2,7 @@ import { ApplicationCommandOptionType, CommandInteraction, CommandInteractionOpt import { Command } from "@src/Command"; import { embedify } from "@utils/embedify"; import { addDJRoleId, toggleDJOnly, getDJRoleIds, removeDJRoleId } from "@database/music"; +import { settings } from "@src/settings"; export class DJ extends Command { constructor() { @@ -47,6 +48,8 @@ export class DJ extends Command { } ] }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction, opt: CommandInteractionOption<"cached">): Promise { diff --git a/src/commands/music/Filter.ts b/src/commands/music/Filter.ts index cf92135..6a6275f 100644 --- a/src/commands/music/Filter.ts +++ b/src/commands/music/Filter.ts @@ -5,6 +5,7 @@ import { embedify } from "@src/utils"; import { ApplicationCommandOptionType, CommandInteraction, Guild, GuildMemberRoleManager } from "discord.js"; import { Player } from "erela.js"; import { filterTurnOff } from "./global.music"; +import { settings } from "@src/settings"; export class Filter extends Command { constructor() { @@ -47,6 +48,8 @@ export class Filter extends Command { } ] }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/commands/music/NowPlaying.ts b/src/commands/music/NowPlaying.ts index e933110..07b9a7f 100644 --- a/src/commands/music/NowPlaying.ts +++ b/src/commands/music/NowPlaying.ts @@ -6,6 +6,7 @@ import { formatDuration, parseDuration } from "svcorelib"; import { getPremium, isDJOnlyandhasDJRole } from "@src/database/music"; import { fetchSongInfo, SongInfo } from "./global.music"; import { Tuple } from "@src/types"; +import { settings } from "@src/settings"; const ten_secs = 10_000; @@ -16,6 +17,8 @@ export class NowPlaying extends Command { desc: "Shows the current playing song", category: "music" }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/commands/music/Pause.ts b/src/commands/music/Pause.ts index 1f5bbd3..d9a9389 100644 --- a/src/commands/music/Pause.ts +++ b/src/commands/music/Pause.ts @@ -3,6 +3,7 @@ import { CommandInteraction, GuildMemberRoleManager } from "discord.js"; import { Command } from "@src/Command"; import { getMusicManager } from "@src/lavalink/client"; import { embedify } from "@utils/embedify"; +import { settings } from "@src/settings"; export class Pause extends Command { constructor() { @@ -11,6 +12,8 @@ export class Pause extends Command { desc: "Pause the currently playing song", category: "music" }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/commands/music/Play.ts b/src/commands/music/Play.ts index 46e2f62..ff7ea77 100644 --- a/src/commands/music/Play.ts +++ b/src/commands/music/Play.ts @@ -5,6 +5,7 @@ import { four_hours, getMusicManager, reduceSongsLength } from "@src/lavalink/cl import { embedify } from "@utils/embedify"; import { getPremium, isDJOnlyandhasDJRole } from "@database/music"; import { randomizeArray, randRange } from "svcorelib"; +import { settings } from "@src/settings"; export class Play extends Command { constructor() { @@ -60,6 +61,8 @@ export class Play extends Command { } ], }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/commands/music/Premium.ts b/src/commands/music/Premium.ts index cea90b1..dead0d3 100644 --- a/src/commands/music/Premium.ts +++ b/src/commands/music/Premium.ts @@ -22,6 +22,8 @@ export class Premium extends Command { } ] }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction, opt: CommandInteractionOption<"cached">): Promise { diff --git a/src/commands/music/Queue.ts b/src/commands/music/Queue.ts index 953de14..daa5631 100644 --- a/src/commands/music/Queue.ts +++ b/src/commands/music/Queue.ts @@ -5,6 +5,7 @@ import { embedify } from "@utils/embedify"; import { Queue as ErelaQueue, Track, UnresolvedTrack } from "erela.js"; import { BtnMsg } from "@utils/BtnMsg"; import { Tuple } from "@src/types"; +import { settings } from "@src/settings"; interface QueuePage { [userid: string]: number, @@ -22,6 +23,8 @@ export class Queue extends Command { desc: "Shows the current music queue", category: "music" }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/commands/music/Remove.ts b/src/commands/music/Remove.ts index 976f177..fe75b14 100644 --- a/src/commands/music/Remove.ts +++ b/src/commands/music/Remove.ts @@ -3,6 +3,7 @@ import { Command } from "@src/Command"; import { getMusicManager } from "@src/lavalink/client"; import { embedify } from "@utils/embedify"; import { isDJOnlyandhasDJRole } from "@database/music"; +import { settings } from "@src/settings"; export class Remove extends Command { constructor() { @@ -20,6 +21,8 @@ export class Remove extends Command { } ] }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/commands/music/Repeat.ts b/src/commands/music/Repeat.ts index 1222b29..e037963 100644 --- a/src/commands/music/Repeat.ts +++ b/src/commands/music/Repeat.ts @@ -3,6 +3,7 @@ import { Command } from "@src/Command"; import { getMusicManager } from "@src/lavalink/client"; import { embedify } from "@utils/embedify"; import { isDJOnlyandhasDJRole } from "@database/music"; +import { settings } from "@src/settings"; export class Repeat extends Command { constructor() { @@ -21,6 +22,8 @@ export class Repeat extends Command { } ] }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction, opt: CommandInteractionOption<"cached">): Promise { diff --git a/src/commands/music/Resume.ts b/src/commands/music/Resume.ts index 774f4f7..ebc25c6 100644 --- a/src/commands/music/Resume.ts +++ b/src/commands/music/Resume.ts @@ -3,6 +3,7 @@ import { Command } from "@src/Command"; import { getMusicManager } from "@src/lavalink/client"; import { embedify } from "@utils/embedify"; import { isDJOnlyandhasDJRole } from "@database/music"; +import { settings } from "@src/settings"; export class Resume extends Command { constructor() { @@ -11,6 +12,8 @@ export class Resume extends Command { desc: "Resumes current song", category: "music" }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/commands/music/Search.ts b/src/commands/music/Search.ts index 8ccf642..5e182e8 100644 --- a/src/commands/music/Search.ts +++ b/src/commands/music/Search.ts @@ -5,6 +5,7 @@ import { embedify } from "@utils/embedify"; import { getPremium, isDJOnlyandhasDJRole } from "@database/music"; import { SearchQuery, SearchResult } from "erela.js"; import { randRange } from "svcorelib"; +import { settings } from "@src/settings"; const activeSearches: Set = new Set(); @@ -62,6 +63,8 @@ export class Search extends Command { } ] }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/commands/music/Shuffle.ts b/src/commands/music/Shuffle.ts index 0ab9eb5..a0170eb 100644 --- a/src/commands/music/Shuffle.ts +++ b/src/commands/music/Shuffle.ts @@ -3,6 +3,7 @@ import { Command } from "@src/Command"; import { getMusicManager } from "@src/lavalink/client"; import { embedify } from "@utils/embedify"; import { isDJOnlyandhasDJRole } from "@database/music"; +import { settings } from "@src/settings"; export class Shuffle extends Command { constructor() { @@ -11,6 +12,8 @@ export class Shuffle extends Command { desc: "Shuffles the queue", category: "music" }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/commands/music/Skip.ts b/src/commands/music/Skip.ts index b9bfab6..7ae6716 100644 --- a/src/commands/music/Skip.ts +++ b/src/commands/music/Skip.ts @@ -4,6 +4,7 @@ import { getMusicManager } from "@src/lavalink/client"; import { embedify } from "@utils/embedify"; import { isDJOnlyandhasDJRole } from "@database/music"; import { skipVotes } from "./global.music"; +import { settings } from "@src/settings"; export class Skip extends Command { constructor() { @@ -26,6 +27,8 @@ export class Skip extends Command { } ] }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/commands/music/Stop.ts b/src/commands/music/Stop.ts index df9a016..af7d199 100644 --- a/src/commands/music/Stop.ts +++ b/src/commands/music/Stop.ts @@ -3,6 +3,7 @@ import { Command } from "@src/Command"; import { getMusicManager } from "@src/lavalink/client"; import { embedify } from "@utils/embedify"; import { isDJOnlyandhasDJRole } from "@database/music"; +import { settings } from "@src/settings"; export class Stop extends Command { constructor() { @@ -11,6 +12,8 @@ export class Stop extends Command { desc: "Clears the queue and makes the bot leave the voice channel", category: "music" }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/commands/music/Volume.ts b/src/commands/music/Volume.ts index d8231c7..8cf7ba4 100644 --- a/src/commands/music/Volume.ts +++ b/src/commands/music/Volume.ts @@ -3,6 +3,7 @@ import { Command } from "@src/Command"; import { getMusicManager } from "@src/lavalink/client"; import { embedify } from "@utils/embedify"; import { isDJOnlyandhasDJRole } from "@database/music"; +import { settings } from "@src/settings"; export class Volume extends Command { constructor() { @@ -21,6 +22,8 @@ export class Volume extends Command { } ] }); + + this.enabled = settings.commands.musicEnabled; } async run(int: CommandInteraction): Promise { diff --git a/src/lavalink/client.ts b/src/lavalink/client.ts index 7afb175..20f1290 100644 --- a/src/lavalink/client.ts +++ b/src/lavalink/client.ts @@ -7,6 +7,7 @@ import { trackEnd } from "@src/lavalink/lib/trackEnd"; import { SpotifyOptions } from "better-erela.js-spotify/dist/typings"; import { playerMove } from "./lib/playerMove"; import { playerCreate } from "./lib/playerCreate"; +import { settings } from "@src/settings"; let client: Client; const plugins: Plugin[] = []; @@ -41,12 +42,17 @@ process.env.LAVALINK_HOSTS?.split(",").map((v) => { export function lavaRetrieveClient(cl: Client) { + if(!settings.commands.musicEnabled) + return; + client = cl; manager = initializeManagerFromClient(client); } export function clientReadyInitLava(cl: Client) { + if(!settings.commands.musicEnabled) + return; manager.init(cl.user?.id); } From f8eb9b1a21b7cf2732f87bcc85e06886421ca688 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sun, 9 Apr 2023 20:30:45 +0200 Subject: [PATCH 34/40] refactor: misc stuff --- src/settings.ts | 35 +++++++++++++++++++---------------- src/utils/sorting.ts | 7 +++++-- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/settings.ts b/src/settings.ts index 8b3ff73..c76a038 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -11,7 +11,7 @@ dotenv.config(); * Global miscellaneous settings for the bot * @readonly */ -export const settings: Settings = Object.freeze({ +export const settings: Settings = { debug: { /** Whether to send a bell sound in the console when the bot is ready */ bellOnReady: envVarEquals("BELL_ON_READY", true), @@ -45,20 +45,21 @@ export const settings: Settings = Object.freeze({ commandPrefix: getEnvVar("COMMAND_PREFIX", "stringNoEmpty"), }, embedColors: { - default: getEnvVar("EMBED_COLOR_DEFAULT") ?? 0xfaba05, - success: getEnvVar("EMBED_COLOR_SUCCESS") ?? Colors.Green, - gameLost: getEnvVar("EMBED_COLOR_GAME_LOST") ?? Colors.Grey, - warning: getEnvVar("EMBED_COLOR_WARNING") ?? Colors.Orange, - error: getEnvVar("EMBED_COLOR_ERROR") ?? Colors.DarkRed, - contestWinner: getEnvVar("EMBED_COLOR_CONTEST_WINNER") ?? Colors.Gold, + default: getEnvVar("EMBED_COLOR_DEFAULT") as ColorResolvable ?? 0xfaba05, + success: getEnvVar("EMBED_COLOR_SUCCESS") as ColorResolvable ?? Colors.Green, + gameLost: getEnvVar("EMBED_COLOR_GAME_LOST") as ColorResolvable ?? Colors.Grey, + warning: getEnvVar("EMBED_COLOR_WARNING") as ColorResolvable ?? Colors.Orange, + error: getEnvVar("EMBED_COLOR_ERROR") as ColorResolvable ?? Colors.DarkRed, + contestWinner: getEnvVar("EMBED_COLOR_CONTEST_WINNER") as ColorResolvable ?? Colors.Gold, }, /** Incremental list of emojis used in reactions */ emojiList: [ "ðŸ‡Ķ", "🇧", "ðŸ‡Ļ", "ðŸ‡Đ", "🇊", "ðŸ‡Ŧ", "🇎", "🇭", "ðŸ‡Ū", "ðŸ‡Ŋ", "🇰", "ðŸ‡ą", "ðŸ‡ē", "ðŸ‡ģ", "ðŸ‡ī", "ðŸ‡ĩ", "ðŸ‡ķ", "🇷", "ðŸ‡ļ", "ðŸ‡đ" ], - devs: getEnvVar("DEV_IDS", "stringArray"), + devs: getEnvVar("DEV_IDS", "stringArray") ?? [], commands: { execEnabled: !envVarEquals("EXEC_CMD_ENABLED", false), + musicEnabled:!envVarEquals("MUSIC_CMDS_ENABLED", false), }, -}) as Settings; +}; /** Tests if the environment variable `varName` equals `value` casted to string */ function envVarEquals(varName: string, value: Stringifiable, caseSensitive = false) @@ -68,17 +69,18 @@ function envVarEquals(varName: string, value: Stringifiable, caseSensitive = fal return (caseSensitive ? envVal : envVal?.toLowerCase()) === (caseSensitive ? String(val) : String(val).toLowerCase()); } -/** Grabs an environment variable's value, and casts it to a `string` - however if the string is empty (unset), undefined is returned */ -export function getEnvVar(varName: string, asType?: "stringNoEmpty"): undefined | string -/** Grabs an environment variable's value, and casts it to a `string` */ +// first one is the default overload +/** Grabs an environment variable's value, and casts it to a `string` - if the variable is present but empty, an empty string is returned */ export function getEnvVar(varName: string, asType?: "string"): undefined | string -/** Grabs an environment variable's value, and casts it to a `number` */ +/** Grabs an environment variable's value, and casts it to a `string` - if the variable is empty, undefined is returned */ +export function getEnvVar(varName: string, asType?: "stringNoEmpty"): undefined | string +/** Grabs an environment variable's value, and casts it to a `number` - returns NaN if the variable couldn't be parsed */ export function getEnvVar(varName: string, asType: "number"): undefined | number -/** Grabs an environment variable's value, and casts it to a `string[]` */ +/** Grabs an environment variable's value, and casts it to a `string[]` by splitting on commas */ export function getEnvVar(varName: string, asType: "stringArray"): undefined | string[] -/** Grabs an environment variable's value, and casts it to a `number[]` */ +/** Grabs an environment variable's value, and casts it to a `number[]` by splitting on commas - includes NaN if the number(s) couldn't be parsed */ export function getEnvVar(varName: string, asType: "numberArray"): undefined | number[] -/** Grabs an environment variable's value, and casts it to a specific type (default string) */ +/** Grabs an environment variable's value, and casts it to a specific type (`"string"` by default) */ export function getEnvVar(varName: string, asType: T = "string" as T): undefined | (string | number | string[] | number[]) { const val = process.env[varName]; @@ -133,5 +135,6 @@ interface Settings { devs: string[]; commands: { execEnabled: boolean; + musicEnabled: boolean; } } diff --git a/src/utils/sorting.ts b/src/utils/sorting.ts index 4a73868..90c0a5c 100644 --- a/src/utils/sorting.ts +++ b/src/utils/sorting.ts @@ -3,7 +3,7 @@ import memoize from "fast-memoize"; /** * Uses black magic and "Wilson score confidence interval for a Bernoulli parameter" to calculate a sortable score from upvotes and downvotes. - * See more info [here.](https://www.evanmiller.org/how-not-to-sort-by-average-rating.html) + * More info [here.](https://www.evanmiller.org/how-not-to-sort-by-average-rating.html) * @returns Returns a score between 0 and 1 */ export function rankVotes(upvotes: number, downvotes: number, confidence = 0.95) @@ -18,5 +18,8 @@ export function rankVotes(upvotes: number, downvotes: number, confidence = 0.95) // pĖ‚, the fraction of upvotes const phat = 1.0 * upvotes / votesAmt; - return (phat + z * z / (2 * votesAmt) - z * Math.sqrt((phat * (1 - phat) + z * z / (4 * votesAmt)) / votesAmt)) / (1 + z * z / votesAmt); + return ( + phat + z * z / (2 * votesAmt) - z + * Math.sqrt((phat * (1 - phat) + z * z / (4 * votesAmt)) / votesAmt) + ) / (1 + z * z / votesAmt); } From cf591108fcf1a106bc42f9f1c77a9c8111c38dcf Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sun, 9 Apr 2023 20:56:37 +0200 Subject: [PATCH 35/40] refactor: update redis section in readme --- src/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/README.md b/src/README.md index 8cd5351..2647c8f 100644 --- a/src/README.md +++ b/src/README.md @@ -97,7 +97,7 @@ When launching to production, you want redis to be daemonized, this can be done [^1]: If you are using systemd, create a `redis.conf` in `/etc/redis/redis.conf` and make sure to add the line `supervised systemd`. -In our specific application, your redis-server must be running on `127.0.0.1:6379` which is the default for redis-server, and if you are on windows, make sure to add the line `localhostForwarding=true` to your .wslconfig located in `%UserProfile%\.wslconfig`, if this file does not exist, please create one and be sure to add the header `[wsl2]` or `[wsl1]`. Also if you are on windows, be aware that WSL does not keep applications alive without a bash terminal running, so do not close the WSL window while developing. +In our specific application, your redis-server must be running on `127.0.0.1:6379` which is the default for redis-server, and if you are on windows, make sure to add the line `localhostForwarding=true` to your .wslconfig located in `%UserProfile%\.wslconfig`, if this file does not exist, please create one and be sure to add the header `[wsl2]` or `[wsl1]`. On WSL, if Redis is installed through systemd, it should be kept alive in the background even after closing the WSL process. Another thing is to have a config for your instance of Redis, in testing/development you can do something like this to have an instance that does not save to disk. On WSL, you must do this because redis will not have write permissions to save to disk. ```sh From de9b8070a11297b16e1243c4db0fcb65b5b8b982 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Sun, 9 Apr 2023 20:57:10 +0200 Subject: [PATCH 36/40] refactor: begin rewrite of /reminder :hollow: --- src/commands/index.ts | 2 +- src/commands/util/{ => Reminder}/Reminder.ts | 321 +----------------- src/commands/util/Reminder/index.ts | 1 + src/commands/util/Reminder/reminderCheck.ts | 307 +++++++++++++++++ .../util/Reminder/reminderRescheduling.ts | 21 ++ 5 files changed, 341 insertions(+), 311 deletions(-) rename src/commands/util/{ => Reminder}/Reminder.ts (62%) create mode 100644 src/commands/util/Reminder/index.ts create mode 100644 src/commands/util/Reminder/reminderCheck.ts create mode 100644 src/commands/util/Reminder/reminderRescheduling.ts diff --git a/src/commands/index.ts b/src/commands/index.ts index 4ef254e..a0f48fa 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -23,7 +23,7 @@ import { Emoji } from "@commands/util/Emoji"; import { Exec } from "@commands/util/Exec"; import { Help } from "@commands/util/Help"; import { Ping } from "@commands/util/Ping"; -import { Reminder } from "@commands/util/Reminder"; +import { Reminder } from "@src/commands/util/Reminder"; import { Server } from "@commands/util/Server"; import { Translate } from "@commands/util/Translate"; import { Whois } from "@commands/util/Whois"; diff --git a/src/commands/util/Reminder.ts b/src/commands/util/Reminder/Reminder.ts similarity index 62% rename from src/commands/util/Reminder.ts rename to src/commands/util/Reminder/Reminder.ts index ba088ec..b1d74f4 100644 --- a/src/commands/util/Reminder.ts +++ b/src/commands/util/Reminder/Reminder.ts @@ -1,22 +1,21 @@ -import { ApplicationCommandOptionType, ButtonBuilder, ButtonInteraction, ButtonStyle, ChannelType, Client, CommandInteraction, CommandInteractionOption, EmbedBuilder, Message, TextBasedChannel } from "discord.js"; -import k from "kleur"; +// contains the reminder command class and the creation of reminders + +import { ApplicationCommandOptionType, ButtonBuilder, ButtonStyle, Client, CommandInteraction, CommandInteractionOption, EmbedBuilder } from "discord.js"; import { time } from "@discordjs/builders"; import { Reminder as ReminderObj } from "@prisma/client"; import { Command } from "@src/Command"; import { settings } from "@src/settings"; -import { autoPlural, BtnMsg, ButtonsTuple, embedify, PageEmbed, timeToMs, toUnix10, useEmbedify } from "@src/utils"; -import { createNewUser, deleteReminder, deleteReminders, getExpiredReminders, getReminder, getReminders, getUser, setReminder } from "@src/database/users"; +import { autoPlural, BtnMsg, embedify, PageEmbed, timeToMs, toUnix10, useEmbedify } from "@src/utils"; +import { createNewUser, deleteReminder, deleteReminders, getReminder, getReminders, getUser, setReminder } from "@src/database/users"; import { Tuple } from "@src/types"; +import { initReminderCheck, reminderLimit } from "./reminderCheck"; +import { initReminderRescheduling } from "./reminderRescheduling"; -/** Max reminders per user (global) */ -const reminderLimit = 10; -const reminderCheckInterval = 2000; /** To not exceed the embed limits & strain the DB */ -const maxNameLength = 250; +export const maxNameLength = 250; export class Reminder extends Command { - constructor(client: Client) { super({ @@ -152,16 +151,9 @@ export class Reminder extends Command ], }); - if(client instanceof Client) - { - try { - // since the constructor is called exactly once at startup, this should work just fine - checkReminders(client); - setInterval(() => checkReminders(client), reminderCheckInterval); - } - catch(err) { - console.error(k.red("Error while checking reminders:"), err); - } + if(client instanceof Client) { + initReminderCheck(client); + initReminderRescheduling(client); } } @@ -451,294 +443,3 @@ export class Reminder extends Command } } } - -//#MARKER check reminders - -const rescheduleBtn = new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ"); -/** - * Contains all compound keys of reminders that are currently being checked. - * This is necessary because the check could take longer than `reminderCheckInterval` and check the same reminder twice. - * Format: `userId-reminderId` - */ -const reminderCheckBuffer = new Set(); - -async function checkReminders(client: Client) -{ - const expRems = await getExpiredReminders(); - - if(!expRems || expRems.length === 0) - return; - - const promises: Promise[] = []; - - const getExpiredEbd = ({ name }: ReminderObj) => new EmbedBuilder() - .setDescription(name) - .setColor(settings.embedColors.default); - - // TODO: add logger - const reminderError = (err: Error) => console.error(k.red("Error while checking expired reminders:\n"), err); - - /** Edits `msg` to have the reschedule buttons and handles the listening and reminder rescheduling */ - const editReschedMsg = (msg: Message, rem: ReminderObj) => { - const min = 60_000; - const hr = min * 60; - const day = hr * 24; - - /** null is used to pad to a new component row */ - const reschedBtns = [ - { - label: "+ 2m", - val: 2 * min, - }, - { - label: "+ 5m", - val: 5 * min, - }, - { - label: "+ 15m", - val: 15 * min, - }, - { - label: "+ 1h", - val: hr, - }, - { - label: "+ 3h", - val: 3 * hr, - }, - { - label: "+ 8h", - val: 8 * hr, - }, - { - label: "+ 12h", - val: 12 * hr, - }, - { - label: "+ 1d", - val: day, - }, - { - label: "+ 3d", - val: 3 * day, - }, - { - label: "+ 7d", - val: 7 * day, - }, - { - val: 0, - label: "Reschedule", - btn: new ButtonBuilder().setStyle(ButtonStyle.Success).setLabel("Reschedule"), - }, - { - val: 0, - label: "Cancel", - btn: new ButtonBuilder().setStyle(ButtonStyle.Danger).setLabel("Cancel"), - }, - { - val: 0, - label: "Reset", - btn: new ButtonBuilder().setStyle(ButtonStyle.Secondary).setLabel("Reset"), - }, - ].map((props) => (props ? { - btn: new ButtonBuilder().setStyle(ButtonStyle.Secondary).setLabel(props.label), - ...props, - } : null)); - - const getEbd = (rem: ReminderObj) => new EmbedBuilder() - .setColor(settings.embedColors.default) - .setDescription(`Rescheduling the following reminder:\n> ${rem.name.replace(/\n/gm, "\n> ")}\n\nCurrent expiry: `) - .setFooter({ text: "Press any of the buttons below to add time onto this reminder." }); - - const ebd = getEbd(rem); - - const slicedBtnsInput = reschedBtns.map((props) => props ? props.btn : null); - const slicedBtns: ButtonBuilder[][] = []; - while(slicedBtnsInput.length > 0) - slicedBtns.push(slicedBtnsInput.splice(0, 5).filter(b => b !== null) as ButtonBuilder[]); - - const editReschedBm = new BtnMsg(ebd, slicedBtns as ButtonsTuple); - - const newReminder = { ...rem }; - - /** Adds the `value` in milliseconds to the newReminder */ - const addValueToReminder = (value: number) => { - newReminder.dueTimestamp = new Date(newReminder.dueTimestamp.getTime() + value); - msg.edit({ ...editReschedBm.getMsgOpts(), content: "", embeds: [ getEbd(newReminder) ]}); - }; - - /** Resets the rescheduled reminder time back to the original */ - const resetRescheduledReminder = () => { - newReminder.dueTimestamp = new Date(rem.dueTimestamp.getTime()); - msg.edit({ ...editReschedBm.getMsgOpts(), content: "", embeds: [ getEbd(newReminder) ]}); - }; - - /** Sets a new reminder */ - const setRescheduledReminder = async (rem: ReminderObj) => { - const reminders = await getReminders(rem.userId); - - const reminderId = reminders && reminders.length > 0 && reminders.at(-1) - ? reminders.at(-1)!.reminderId + 1 - : 1; - - if(!await getUser(rem.userId)) - await createNewUser(rem.userId); - - await setReminder(rem); - - return await msg.edit({ - ...useEmbedify(`I've rescheduled your reminder:\n> ${rem.name}\n> Now due on ${time(toUnix10(rem.dueTimestamp), "f")}\n\nID: \`${reminderId}\` â€Ē To list your reminders use \`/reminder list\``, settings.embedColors.success), - content: "", - components: [], - }); - }; - - /** Cancels the reminder rescheduling */ - const cancelRescheduling = () => { - msg.edit({ - content: `🔔 <@${rem.userId}>, your reminder expired!`, - embeds: [ getExpiredEbd(rem) ], - components: [], - }); - - if(!editReschedBm.isDestroyed()) - editReschedBm.destroy(); - }; - - let submitted = false, cancelled = false; - - editReschedBm.on("press", (btn, btInt) => { - btInt.deferUpdate(); - const reschedBt = reschedBtns.find(b => b && b.label === btn.data.label); - if(btInt.user.id === rem.userId && reschedBt) { - if(btn.data.label === "Reschedule") { - submitted = true; - editReschedBm.destroy(); - return setRescheduledReminder(newReminder); - } - else if(btn.data.label === "Cancel") { - cancelled = true; - return cancelRescheduling(); - } - else if(btn.data.label === "Reset") - return resetRescheduledReminder(); - else - return addValueToReminder(reschedBt.val); - } - }); - - ["timeout", "destroy"].forEach(evt => - editReschedBm.on(evt as "timeout", () => !submitted && !cancelled && cancelRescheduling()) - ); - - msg.edit({ - ...editReschedBm.getMsgOpts(), - content: "", - }); - }; - - /** Sends the expiry reminder in the guild and channel it was created in, but only if it is not private */ - const remindPublicly = async (rem: ReminderObj) => { - try { - if(rem.private) - throw new Error("Can't send message in guild as reminder is private."); - - const guild = client.guilds.cache.find(g => g.id === rem.guild); - const chan = guild?.channels.cache.find(c => c.id === rem.channel); - - if(chan && [ChannelType.GuildText, ChannelType.PublicThread, ChannelType.PrivateThread, ChannelType.GuildForum].includes(chan.type)) - { - const reschedBm = new BtnMsg(null, rescheduleBtn); - - const msg = (chan as TextBasedChannel).send({ - ...reschedBm.getMsgOpts(), - content: `🔔 <@${rem.userId}>, your reminder expired!`, - embeds: [ getExpiredEbd(rem) ], - }); - - reschedBm.on("press", async (btn, btInt) => { - await btInt.deferUpdate(); - if(btInt.user.id === rem.userId && btn.data.label === "Reschedule") - editReschedMsg(msg instanceof Promise ? await msg : msg, rem); - }); - } - } - catch(err) { - // TODO: track reminder "loss rate" - // - // I │ I I - // ─────┾───── - // I I │ I ⌐® - - err instanceof Error && reminderError(err); - - void err; - } - finally { - try { - await deleteReminder(rem.reminderId, rem.userId); - } - catch(err) { - // TODO: see above - - err instanceof Error && reminderError(err); - } - finally { - reminderCheckBuffer.delete(`${rem.userId}-${rem.reminderId}`); - } - } - }; - - for(const rem of expRems) - { - if(reminderCheckBuffer.has(`${rem.userId}-${rem.reminderId}`)) - continue; - - reminderCheckBuffer.add(`${rem.userId}-${rem.reminderId}`); - - const usr = client.users.cache.find(u => u.id === rem.userId); - - promises.push((async () => { - if(!usr) - return remindPublicly(rem); - - try - { - if(rem.private) { - const dm = await usr.createDM(); - const reschedBm = new BtnMsg(null, rescheduleBtn); - - const msg = await dm.send({ - ...reschedBm.getMsgOpts(), - content: "🔔 Your reminder expired!", - embeds: [ getExpiredEbd(rem) ], - }); - - reschedBm.on("press", async (btn, btInt) => { - await btInt.deferUpdate(); - if(btn.data.label === "Reschedule") - editReschedMsg(msg instanceof Promise ? await msg : msg, rem); - }); - - if(!dm || !msg) - return remindPublicly(rem); - } - else remindPublicly(rem); - - await deleteReminder(rem.reminderId, rem.userId); - reminderCheckBuffer.delete(`${rem.userId}-${rem.reminderId}`); - } - catch(err) - { - return remindPublicly(rem); - } - })()); - } - - await Promise.allSettled(promises); -} - -async function rescheduleReminder(rem: ReminderObj, btnInt: ButtonInteraction) { - void "TODO"; -} diff --git a/src/commands/util/Reminder/index.ts b/src/commands/util/Reminder/index.ts new file mode 100644 index 0000000..3e12a85 --- /dev/null +++ b/src/commands/util/Reminder/index.ts @@ -0,0 +1 @@ +export * from "./Reminder"; diff --git a/src/commands/util/Reminder/reminderCheck.ts b/src/commands/util/Reminder/reminderCheck.ts new file mode 100644 index 0000000..4bd7027 --- /dev/null +++ b/src/commands/util/Reminder/reminderCheck.ts @@ -0,0 +1,307 @@ +// checks all expired reminders on interval to send the reminder message + +import { Reminder as ReminderObj } from "@prisma/client"; +import { createNewUser, deleteReminder, getExpiredReminders, getReminders, getUser, setReminder } from "@src/database/users"; +import { settings } from "@src/settings"; +import { BtnMsg, ButtonsTuple, toUnix10, useEmbedify } from "@src/utils"; +import { ButtonBuilder, ButtonStyle, ChannelType, Client, EmbedBuilder, Message, TextBasedChannel, time } from "discord.js"; +import k from "kleur"; + +let client: Client; + +/** Max reminders per user (global) */ +export const reminderLimit = 10; +/** Interval in ms between checking for expired reminders */ +export const reminderCheckInterval = 2000; + +/** + * Contains all compound keys of reminders that are currently being checked. + * This is necessary because the check could take longer than `reminderCheckInterval` and check the same reminder twice. + * Format: `userId-reminderId` + */ +const reminderCheckBuffer = new Set(); + +export function initReminderCheck(cl: Client) { + client = cl; + checkReminders(); + setInterval(() => checkReminders(), reminderCheckInterval); +} + +const rescheduleBtn = new ButtonBuilder().setLabel("Reschedule").setStyle(ButtonStyle.Secondary).setEmoji("⏭ïļ"); + +async function checkReminders() +{ + const expRems = await getExpiredReminders(); + + if(!expRems || expRems.length === 0) + return; + + const promises: Promise[] = []; + + const getExpiredEbd = ({ name }: ReminderObj) => new EmbedBuilder() + .setDescription(name) + .setColor(settings.embedColors.default); + + // TODO: add logger + const reminderError = (err: Error) => console.error(k.red("Error while checking expired reminders:\n"), err); + + /** Edits `msg` to have the reschedule buttons and handles the listening and reminder rescheduling */ + const editReschedMsg = (msg: Message, rem: ReminderObj) => { + const min = 60_000; + const hr = min * 60; + const day = hr * 24; + + /** null is used to pad to a new component row */ + const reschedBtns = [ + { + label: "+ 2m", + val: 2 * min, + }, + { + label: "+ 5m", + val: 5 * min, + }, + { + label: "+ 15m", + val: 15 * min, + }, + { + label: "+ 1h", + val: hr, + }, + { + label: "+ 3h", + val: 3 * hr, + }, + { + label: "+ 8h", + val: 8 * hr, + }, + { + label: "+ 12h", + val: 12 * hr, + }, + { + label: "+ 1d", + val: day, + }, + { + label: "+ 3d", + val: 3 * day, + }, + { + label: "+ 7d", + val: 7 * day, + }, + { + val: 0, + label: "Reschedule", + btn: new ButtonBuilder().setStyle(ButtonStyle.Success).setLabel("Reschedule"), + }, + { + val: 0, + label: "Cancel", + btn: new ButtonBuilder().setStyle(ButtonStyle.Danger).setLabel("Cancel"), + }, + { + val: 0, + label: "Reset", + btn: new ButtonBuilder().setStyle(ButtonStyle.Secondary).setLabel("Reset"), + }, + ].map((props) => (props ? { + btn: new ButtonBuilder().setStyle(ButtonStyle.Secondary).setLabel(props.label), + ...props, + } : null)); + + const getEbd = (rem: ReminderObj) => new EmbedBuilder() + .setColor(settings.embedColors.default) + .setDescription(`Rescheduling the following reminder:\n> ${rem.name.replace(/\n/gm, "\n> ")}\n\nCurrent expiry: `) + .setFooter({ text: "Press any of the buttons below to add time onto this reminder." }); + + const ebd = getEbd(rem); + + const slicedBtnsInput = reschedBtns.map((props) => props ? props.btn : null); + const slicedBtns: ButtonBuilder[][] = []; + while(slicedBtnsInput.length > 0) + slicedBtns.push(slicedBtnsInput.splice(0, 5).filter(b => b !== null) as ButtonBuilder[]); + + const editReschedBm = new BtnMsg(ebd, slicedBtns as ButtonsTuple); + + const newReminder = { ...rem }; + + /** Adds the `value` in milliseconds to the newReminder */ + const addValueToReminder = (value: number) => { + newReminder.dueTimestamp = new Date(newReminder.dueTimestamp.getTime() + value); + msg.edit({ ...editReschedBm.getMsgOpts(), content: "", embeds: [ getEbd(newReminder) ]}); + }; + + /** Resets the rescheduled reminder time back to the original */ + const resetRescheduledReminder = () => { + newReminder.dueTimestamp = new Date(rem.dueTimestamp.getTime()); + msg.edit({ ...editReschedBm.getMsgOpts(), content: "", embeds: [ getEbd(newReminder) ]}); + }; + + /** Sets a new reminder */ + const setRescheduledReminder = async (rem: ReminderObj) => { + const reminders = await getReminders(rem.userId); + + const reminderId = reminders && reminders.length > 0 && reminders.at(-1) + ? reminders.at(-1)!.reminderId + 1 + : 1; + + if(!await getUser(rem.userId)) + await createNewUser(rem.userId); + + await setReminder(rem); + + return await msg.edit({ + ...useEmbedify(`I've rescheduled your reminder:\n> ${rem.name}\n> Now due on ${time(toUnix10(rem.dueTimestamp), "f")}\n\nID: \`${reminderId}\` â€Ē To list your reminders use \`/reminder list\``, settings.embedColors.success), + content: "", + components: [], + }); + }; + + /** Cancels the reminder rescheduling */ + const cancelRescheduling = () => { + msg.edit({ + content: `🔔 <@${rem.userId}>, your reminder expired!`, + embeds: [ getExpiredEbd(rem) ], + components: [], + }); + + if(!editReschedBm.isDestroyed()) + editReschedBm.destroy(); + }; + + let submitted = false, cancelled = false; + + editReschedBm.on("press", (btn, btInt) => { + btInt.deferUpdate(); + const reschedBt = reschedBtns.find(b => b && b.label === btn.data.label); + if(btInt.user.id === rem.userId && reschedBt) { + if(btn.data.label === "Reschedule") { + submitted = true; + editReschedBm.destroy(); + return setRescheduledReminder(newReminder); + } + else if(btn.data.label === "Cancel") { + cancelled = true; + return cancelRescheduling(); + } + else if(btn.data.label === "Reset") + return resetRescheduledReminder(); + else + return addValueToReminder(reschedBt.val); + } + }); + + ["timeout", "destroy"].forEach(evt => + editReschedBm.on(evt as "timeout", () => !submitted && !cancelled && cancelRescheduling()) + ); + + msg.edit({ + ...editReschedBm.getMsgOpts(), + content: "", + }); + }; + + /** Sends the expiry reminder in the guild and channel it was created in, but only if it is not private */ + const remindPublicly = async (rem: ReminderObj) => { + try { + if(rem.private) + throw new Error("Can't send message in guild as reminder is private."); + + const guild = client.guilds.cache.find(g => g.id === rem.guild); + const chan = guild?.channels.cache.find(c => c.id === rem.channel); + + if(chan && [ChannelType.GuildText, ChannelType.PublicThread, ChannelType.PrivateThread, ChannelType.GuildForum].includes(chan.type)) + { + const reschedBm = new BtnMsg(null, rescheduleBtn); + + const msg = (chan as TextBasedChannel).send({ + ...reschedBm.getMsgOpts(), + content: `🔔 <@${rem.userId}>, your reminder expired!`, + embeds: [ getExpiredEbd(rem) ], + }); + + reschedBm.on("press", async (btn, btInt) => { + await btInt.deferUpdate(); + if(btInt.user.id === rem.userId && btn.data.label === "Reschedule") + editReschedMsg(msg instanceof Promise ? await msg : msg, rem); + }); + } + } + catch(err) { + // TODO: track reminder "loss rate" + // + // I │ I I + // ─────┾───── + // I I │ I ⌐® + + err instanceof Error && reminderError(err); + + void err; + } + finally { + try { + await deleteReminder(rem.reminderId, rem.userId); + } + catch(err) { + // TODO: see above + + err instanceof Error && reminderError(err); + } + finally { + reminderCheckBuffer.delete(`${rem.userId}-${rem.reminderId}`); + } + } + }; + + for(const rem of expRems) + { + if(reminderCheckBuffer.has(`${rem.userId}-${rem.reminderId}`)) + continue; + + reminderCheckBuffer.add(`${rem.userId}-${rem.reminderId}`); + + const usr = client.users.cache.find(u => u.id === rem.userId); + + promises.push((async () => { + if(!usr) + return remindPublicly(rem); + + try + { + if(rem.private) { + const dm = await usr.createDM(); + const reschedBm = new BtnMsg(null, rescheduleBtn); + + const msg = await dm.send({ + ...reschedBm.getMsgOpts(), + content: "🔔 Your reminder expired!", + embeds: [ getExpiredEbd(rem) ], + }); + + reschedBm.on("press", async (btn, btInt) => { + await btInt.deferUpdate(); + if(btn.data.label === "Reschedule") + editReschedMsg(msg instanceof Promise ? await msg : msg, rem); + }); + + if(!dm || !msg) + return remindPublicly(rem); + } + else remindPublicly(rem); + + await deleteReminder(rem.reminderId, rem.userId); + reminderCheckBuffer.delete(`${rem.userId}-${rem.reminderId}`); + } + catch(err) + { + return remindPublicly(rem); + } + })()); + } + + await Promise.allSettled(promises); +} diff --git a/src/commands/util/Reminder/reminderRescheduling.ts b/src/commands/util/Reminder/reminderRescheduling.ts new file mode 100644 index 0000000..056a93f --- /dev/null +++ b/src/commands/util/Reminder/reminderRescheduling.ts @@ -0,0 +1,21 @@ +// handles reminder rescheduling after the reminder message has been sent + +import { Reminder as ReminderObj } from "@prisma/client"; +import { ButtonInteraction, Client, Message } from "discord.js"; + +let client: Client; + +export async function initReminderRescheduling(cl: Client) { + client = cl; +} + +/** + * Initiates the process of rescheduling a reminder. + * In the initial state, the reminder is already deleted in the database and is only kept alive in memory for 15 minutes after expiry. + * @param rem + * @param btnInt + */ +export async function rescheduleReminder(rem: ReminderObj, msg: Message, btnInt: ButtonInteraction) { + void "TODO"; + void [client, rem, btnInt]; +} From 36309cd1fa16aec0f2c5e1d97423b1e255f105d7 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Mon, 10 Apr 2023 02:52:27 +0200 Subject: [PATCH 37/40] refactor: fix misc texts --- src/bot.ts | 40 +++++++------------------------ src/commands/games/HigherLower.ts | 4 ++-- src/commands/util/Translate.ts | 2 +- src/utils/misc.ts | 29 ++++++++++++++++++++++ 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/bot.ts b/src/bot.ts index 90be5d6..fec4d8d 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -1,18 +1,17 @@ import { ActivityType, ApplicationCommandType, Client, ComponentType, InteractionType } from "discord.js"; import dotenv from "dotenv"; import k from "kleur"; -import { allOfType, system, Stringifiable } from "svcorelib"; +import { allOfType, system } from "svcorelib"; import botLogs from "@src/botLogs"; import { initRegistry, registerGuildCommands, registerEvents, getCommands, modalSubmitted, getCtxMenus, btnListener } from "@src/registry"; -import { commands as slashCmds } from "@src/commands"; import { settings } from "@src/settings"; import { prisma } from "@database/client"; import { doContestStuff } from "@commands/fun/Contest/functions"; import { lavaRetrieveClient, clientReadyInitLava, clientUpdateVoiceStateLava } from "@src/lavalink/client"; import { getRedis } from "@src/redis"; import { registerFont } from "canvas"; -import { autoPlural } from "./utils"; +import { autoPlural, printDbgItmList, ringBell } from "./utils"; const { env, exit } = process; @@ -81,7 +80,8 @@ async function init() }); client.on("raw", (d) => { - clientUpdateVoiceStateLava(d); + if(settings.commands.musicEnabled) + clientUpdateVoiceStateLava(d); }); @@ -140,8 +140,11 @@ async function registerCommands(client: Client) if(!cmds) throw new Error("No commands found to listen to"); - console.log(`â€Ē Registered ${k.green(slashCmds.length)} slash ${autoPlural("command", slashCmds)}`); - printDbgItmList(cmds.map(c => c.getFullCmdName(c.meta.name))); + const enabledCmds = cmds.filter(c => c.enabled); + const ofText = enabledCmds.length != cmds.length ? ` (of ${cmds.length} total)` : ""; + + console.log(`â€Ē Registered ${k.green(enabledCmds.length)} slash ${autoPlural("command", enabledCmds)}${ofText}`); + printDbgItmList(enabledCmds.map(c => c.getFullCmdName(c.meta.name))); console.log(`â€Ē Registered ${k.green(ctxMenus.length)} context ${autoPlural("menu", ctxMenus)}`); printDbgItmList(ctxMenus.map(c => c.meta.name)); @@ -181,29 +184,4 @@ async function registerCommands(client: Client) } } -/** - * Prints a styled list of items to the console - * @param limit Max amount of items per line - */ -function printDbgItmList(list: string[] | Stringifiable[], limit = 10) -{ - let msg = ""; - - list = list.map(itm => itm.toString()).sort(); - - while(list.length > 0) - { - const items = list.splice(0, limit); - msg += `│ ${k.gray(`${items.join(", ")}${items.length === 8 ? "," : ""}`)}\n`; - } - - console.log(msg); -} - -/** Triggers the console bell sound */ -function ringBell() -{ - settings.debug.bellOnReady && process.stdout.write("\u0007"); -} - init(); diff --git a/src/commands/games/HigherLower.ts b/src/commands/games/HigherLower.ts index bbd691c..0278781 100644 --- a/src/commands/games/HigherLower.ts +++ b/src/commands/games/HigherLower.ts @@ -11,7 +11,7 @@ export class HigherLower extends Command { super({ name: "higherlower", - desc: "Guess the random number that is searched for only by getting the hints \"higher\" and \"lower\".", + desc: "Guess the random number that is searched for by only getting the hints \"higher\" and \"lower\"", category: "games", args: [ { @@ -19,7 +19,7 @@ export class HigherLower extends Command desc: "The maximum number that can be chosen. Defaults to 1000. Must be between 10 and 1,000,000,000", type: ApplicationCommandOptionType.Number, min: 10, - max: 1000000000, + max: 1_000_000_000, } ] }); diff --git a/src/commands/util/Translate.ts b/src/commands/util/Translate.ts index 387eb5b..ddc5442 100644 --- a/src/commands/util/Translate.ts +++ b/src/commands/util/Translate.ts @@ -74,7 +74,7 @@ export class Translate extends Command const ebd = new EmbedBuilder() .setTitle(`Translating ${fromLangName ? `from **${fromLangName}** ` : ""}to **${toLangName}**:`) .setColor(settings.embedColors.default) - .setDescription(`> **Translation:**\n> ${translation}\n\n> **Original text:**\n> ${text}`); + .setDescription(`> **Translation:**\n> ${translation}\n\n> **Input text:**\n> ${text}`); return await this.editReply(int, ebd); } diff --git a/src/utils/misc.ts b/src/utils/misc.ts index fde251f..05b4861 100644 --- a/src/utils/misc.ts +++ b/src/utils/misc.ts @@ -1,3 +1,7 @@ +import { Stringifiable } from "svcorelib"; +import k from "kleur"; +import { settings } from "@src/settings"; + /** Truncates a string if it exceeds `length` and inserts `endStr` at the end (empty string to disable) */ export function truncStr(str: string, length: number, endStr = "...") { @@ -26,3 +30,28 @@ export function autoPlural(word: string, num: number | unknown[]) num = num.length; return `${word}${num === 1 ? "" : "s"}`; } + +/** + * Prints a styled list of items to the console + * @param limit Max amount of items per line + */ +export function printDbgItmList(list: string[] | Stringifiable[], limit = 10) +{ + let msg = ""; + + list = list.map(itm => itm.toString()).sort(); + + while(list.length > 0) + { + const items = list.splice(0, limit); + msg += `│ ${k.gray(`${items.join(", ")}${items.length === 8 ? "," : ""}`)}\n`; + } + + console.log(msg); +} + +/** Triggers the console bell sound if enabled in the .env */ +export function ringBell() +{ + settings.debug.bellOnReady && process.stdout.write("\u0007"); +} From d4f3774c5c5b6021c4744b557cc4a48347a8af19 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Wed, 10 May 2023 15:12:20 +0200 Subject: [PATCH 38/40] feat: update clearCommands --- src/tools/clearCommands.ts | 61 ++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/tools/clearCommands.ts b/src/tools/clearCommands.ts index 0a2efd0..3e2ba2b 100644 --- a/src/tools/clearCommands.ts +++ b/src/tools/clearCommands.ts @@ -3,34 +3,50 @@ import { REST } from "@discordjs/rest"; import { Routes } from "discord-api-types/v10"; import dotenv from "dotenv"; import k from "kleur"; +import { exists, unlink } from "fs-extra"; +import { settings } from "../settings"; +import { ringBell } from "@src/utils"; + +/** Amount of commands to delete per batch */ +const batchSize = 2; +/** Timeout between deleting batches of commands */ +const deleteTimeout = 8000; dotenv.config(); const Intents = GatewayIntentBits; -console.log("Logging in..."); - const clientId = process.env.CLIENT_ID ?? "ERR_NO_ENV"; const rest = new REST({ - version: "9" + version: "10", }).setToken(process.env.BOT_TOKEN ?? "ERR_NO_ENV"); const cl = new Client({ intents: [ Intents.Guilds, Intents.GuildMessages, Intents.GuildMembers, Intents.GuildPresences ], }); +console.log("Logging in..."); + cl.login(process.env.BOT_TOKEN ?? "ERR_NO_ENV"); cl.once("ready", async (client) => { await client.user?.setPresence({ status: "dnd" }); - console.log(k.yellow("\nClearing all global and guild commands."), "\nThis might take a while since the 5 requests/s rule applies and I was too lazy to time them better.\n"); + console.log(k.yellow("\nClearing all global and guild commands."), "\nThis might take a while because of rate limiting.\n"); + + if(await exists(settings.commands.hashFilePath)) { + await unlink(settings.commands.hashFilePath); + console.log(`â€Ē Deleted command hash at '${settings.commands.hashFilePath}'`); + } // global cmds - console.log("â€Ē Clearing global commands..."); + console.log("\nâ€Ē Clearing global commands..."); const commands = await rest.get(Routes.applicationCommands(clientId)) as { id: string }[]; + if(commands.length === 0) + console.log(k.gray("(no global commands)")); + const globalCmds = []; for(const command of commands) globalCmds.push(rest.delete(`${Routes.applicationCommands(clientId)}/${command.id}`)); @@ -43,25 +59,38 @@ cl.once("ready", async (client) => { const guilds = client.guilds.cache.map(g => g.id); - for await(const guild of guilds) - { - process.stdout.write(k.gray(("│ ") + (client.guilds.cache.find(g => g.id === guild)?.name ?? ``) + ": ")); + for(const guild of guilds) { + process.stdout.write(k.gray(("│ ") + (client.guilds.cache.find(g => g.id === guild)?.name ?? ``))); const commands = await rest.get(Routes.applicationGuildCommands(clientId, guild)) as { id: string }[]; - const guildCmds: Promise[] = []; - - for(const command of commands) - guildCmds.push(new Promise(async (res) => { - await rest.delete(`${Routes.applicationGuildCommands(clientId, guild)}/${command.id}`); - process.stdout.write(k.gray("*")); - res(); + if(commands.length === 0) { + console.log(k.gray("(no commands)")); + continue; + } + process.stdout.write(k.gray(` (${commands.length}): `)); + + const cmds = [...commands]; + const delCmds: (() => Promise)[] = []; + + while(cmds.length > 0) { + const cmdsSlice = cmds.splice(0, batchSize); + delCmds.push(() => new Promise(async (res) => { + for(const cmd of cmdsSlice) { + await rest.delete(`${Routes.applicationGuildCommands(clientId, guild)}/${cmd.id}`); + process.stdout.write(k.gray("*")); + } + setTimeout(res, deleteTimeout); })); + } - await Promise.all(guildCmds); + for(const delCmd of delCmds) + await delCmd(); process.stdout.write("\n"); } console.log(k.yellow("\n\nDeleted all slash commands.") + "\nGuild commands take up to a few minutes, while global commands take about an hour or so to get updated across Discord servers.\n"); + ringBell(); + process.exit(0); }); From a333a97a4ef128b2eaaba294830a2f257b03e99d Mon Sep 17 00:00:00 2001 From: Sv443 Date: Wed, 10 May 2023 15:12:45 +0200 Subject: [PATCH 39/40] refac: consolidate command hash stuff --- src/registry.ts | 8 +++----- src/settings.ts | 2 ++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/registry.ts b/src/registry.ts index 47bde44..64c9289 100644 --- a/src/registry.ts +++ b/src/registry.ts @@ -146,12 +146,10 @@ export async function registerGuildCommands(guildIDs: (string|string[]), forceUp } } -const cmdHashPath = ".command_hash"; - /** Sets a new command hash by providing the JSON data */ async function updateCommandHash(cmds: RESTPostAPIApplicationCommandsJSONBody[]) { - const curHash = await pathExists(cmdHashPath) - ? await readFile(cmdHashPath) + const curHash = await pathExists(settings.commands.hashFilePath) + ? await readFile(settings.commands.hashFilePath) : Buffer.alloc(0); const newHash = Buffer.from( createHash("SHA512") @@ -163,7 +161,7 @@ async function updateCommandHash(cmds: RESTPostAPIApplicationCommandsJSONBody[]) let commandsChanged = false; if(curHash.compare(newHash) !== 0) { - await writeFile(cmdHashPath, newHash); + await writeFile(settings.commands.hashFilePath, newHash); commandsChanged = true; } diff --git a/src/settings.ts b/src/settings.ts index c76a038..6666a91 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -56,6 +56,7 @@ export const settings: Settings = { emojiList: [ "ðŸ‡Ķ", "🇧", "ðŸ‡Ļ", "ðŸ‡Đ", "🇊", "ðŸ‡Ŧ", "🇎", "🇭", "ðŸ‡Ū", "ðŸ‡Ŋ", "🇰", "ðŸ‡ą", "ðŸ‡ē", "ðŸ‡ģ", "ðŸ‡ī", "ðŸ‡ĩ", "ðŸ‡ķ", "🇷", "ðŸ‡ļ", "ðŸ‡đ" ], devs: getEnvVar("DEV_IDS", "stringArray") ?? [], commands: { + hashFilePath: ".command_hash", execEnabled: !envVarEquals("EXEC_CMD_ENABLED", false), musicEnabled:!envVarEquals("MUSIC_CMDS_ENABLED", false), }, @@ -134,6 +135,7 @@ interface Settings { emojiList: string[]; devs: string[]; commands: { + hashFilePath: string; execEnabled: boolean; musicEnabled: boolean; } From ec0624b5d154433aad9c683b2d22dd77ac379829 Mon Sep 17 00:00:00 2001 From: Sv443 Date: Wed, 10 May 2023 15:56:59 +0200 Subject: [PATCH 40/40] fix: too long field values despite truncating --- src/modals/exec.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/modals/exec.ts b/src/modals/exec.ts index c7ff67f..6393f31 100644 --- a/src/modals/exec.ts +++ b/src/modals/exec.ts @@ -4,7 +4,7 @@ import { transpile } from "typescript"; import { Modal } from "@utils/Modal"; import { settings } from "@src/settings"; -import { embedify, truncField } from "@src/utils"; +import { embedify, truncStr } from "@src/utils"; export class ExecModal extends Modal { @@ -99,14 +99,15 @@ export class ExecModal extends Modal if(result instanceof Buffer) result = ` i < bufTruncLen ? - (a + ((i > 0 ? " " : "") + c.toString(16))) + (a + ((i > 0 ? " " : "") + (c.toString(16).length == 1 ? "0" : "") + c.toString(16))) : (i === bufTruncLen ? a + " ..." : a), "") }>\n\nStringified:\n${result.toString()}`; - if(typeof result === "string" || String(result).length > 1000) - return truncField(String(result)); - else return result; + if(typeof result === "string" || String(result).length > 900) + return truncStr(String(result), 900); + else + return result; }; const resStr = String(result).trim(); @@ -128,7 +129,7 @@ export class ExecModal extends Modal ebd.addFields([ { name: "Error:", - value: `\`\`\`\n${truncField(String(error))}\n\`\`\``, + value: `\`\`\`\n${truncStr(String(error), 980)}\n\`\`\``, inline: false }, { @@ -142,7 +143,7 @@ export class ExecModal extends Modal } catch(err) { - const ebd = embedify(`Couldn't exec due to an error: ${err}`, settings.embedColors.error); + const ebd = embedify(`Couldn't exec due to an error:${err instanceof Error ? `\n${err.stack}` : String(err)}`, settings.embedColors.error); if(int.replied || int.deferred) return this.editReply(int, ebd);