From 097f47a5f79d11ecc833c4c90d535f55c1dd6032 Mon Sep 17 00:00:00 2001 From: John Doe <69335633+Jejebecarte@users.noreply.github.com> Date: Thu, 11 Apr 2024 20:38:55 +1000 Subject: [PATCH 1/8] refactor: rename DISCORD_PREFIX -> DISCORD_IGNORE_PREFIX, make allowed message length maximal --- .env.template | 2 +- src/@types/environment.d.ts | 2 +- src/classes/Bot.ts | 8 ++++---- src/events/discord/message.ts | 16 ++++++++-------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.env.template b/.env.template index 3003a69a..26f6d658 100644 --- a/.env.template +++ b/.env.template @@ -21,7 +21,7 @@ REMINDER_FREQUENCY=60 # How often to send the reminder, in minutes DISCORD_TOKEN=xxxxxxxxxxxxxxxxx -DISCORD_PREFIX=) +DISCORD_IGNORE_PREFIX=) DISCORD_INVITE_LINK=discord.gg/ MEMBER_CHANNEL_ID=xxxxxxxxxxxxxxxxx diff --git a/src/@types/environment.d.ts b/src/@types/environment.d.ts index dc6f4e77..4ebe923f 100644 --- a/src/@types/environment.d.ts +++ b/src/@types/environment.d.ts @@ -17,7 +17,7 @@ declare global { REMINDER_FREQUENCY: string; DISCORD_TOKEN: string; - DISCORD_PREFIX: string; + DISCORD_IGNORE_PREFIX: string; DISCORD_INVITE_LINK: `discord.gg/${string}`; USE_RANK_EMOJIS: "true" | "false"; diff --git a/src/classes/Bot.ts b/src/classes/Bot.ts index cb70bd9e..9d57e488 100644 --- a/src/classes/Bot.ts +++ b/src/classes/Bot.ts @@ -14,6 +14,10 @@ import regex from "../util/regex"; class Bot { public readonly logger = consola; + public memberChannel?: TextChannel; + public officerChannel?: TextChannel; + public readonly ignorePrefix = process.env.DISCORD_IGNORE_PREFIX ?? ")"; + public readonly chatSeparator = process.env.MINECRAFT_CHAT_SEPARATOR ?? ">"; public readonly discord = new Discord({ allowedMentions: { parse: ["users", "roles"], repliedUser: true }, intents: [ @@ -22,10 +26,6 @@ class Bot { IntentsBitField.Flags.MessageContent, ], }); - public readonly botPrefix = process.env.DISCORD_PREFIX ?? ")"; - public readonly chatSeparator = process.env.MINECRAFT_CHAT_SEPARATOR ?? ">"; - public memberChannel?: TextChannel; - public officerChannel?: TextChannel; public onlineCount = 0; public totalCount = 125; diff --git a/src/events/discord/message.ts b/src/events/discord/message.ts index 062aebca..088d3bd9 100644 --- a/src/events/discord/message.ts +++ b/src/events/discord/message.ts @@ -16,7 +16,7 @@ export default { runOnce: false, run: async (bot, message: Message) => { if ( - message.content.startsWith(bot.botPrefix) || + message.content.startsWith(bot.ignorePrefix) || message.author.bot || message.attachments.size > 0 || message.member === null || @@ -24,8 +24,13 @@ export default { ) return; - if (message.content.length > 217) { - await message.channel.send(`Your message is too long! \`${message.content.length}/217\``); + const name = + process.env.USE_FIRST_WORD_OF_AUTHOR_NAME === "true" + ? (message.member.displayName.split(" ")[0] as string) + : message.member.displayName; + + if (message.content.length > 250 - name.length) { + await message.channel.send(`Your message is too long! \`${message.content.length}/${250 - name.length}\``); return; } @@ -46,11 +51,6 @@ export default { `${emojis.warning} <@${message.author.id}> tried to say "${message.content}" but was blocked. This message was not sent to Hypixel.`, ); } else { - const name = - process.env.USE_FIRST_WORD_OF_AUTHOR_NAME === "true" - ? message.member.displayName.split(" ")[0] - : message.member.displayName; - message.content = `${name} ${bot.chatSeparator} ${message.content.replace(/\r?\n|\r/g, " ")}`; bot.sendGuildMessage(message.channel.id === bot.memberChannel?.id ? "gc" : "oc", message.content); } From 88ba4229a4cb189c70e6dc47c1835cbc63d606cc Mon Sep 17 00:00:00 2001 From: John Doe <69335633+Jejebecarte@users.noreply.github.com> Date: Thu, 11 Apr 2024 21:49:18 +1000 Subject: [PATCH 2/8] refactor: clean up tsconfig, add path aliases, move type declarations --- .../BlacklistEntry.d.ts} | 2 +- src/@types/Command.d.ts | 14 +++++ src/@types/Event.d.ts | 11 ++++ src/classes/Bot.ts | 10 ++-- src/classes/Client.ts | 1 - src/commands/blacklist.ts | 17 +++--- src/commands/command.ts | 1 - src/commands/help.ts | 1 - src/commands/invite.ts | 1 - src/commands/kick.ts | 1 - src/commands/promoteDemote.ts | 3 +- src/commands/reboot.ts | 1 - src/commands/slowmode.ts | 1 - src/commands/toggleMute.ts | 3 +- src/events/discord/interactionCreate.ts | 1 - src/events/discord/message.ts | 3 +- src/events/discord/ready.ts | 1 - src/events/mineflayer/chat/commentBlocked.ts | 3 +- src/events/mineflayer/chat/guildChat.ts | 3 +- src/events/mineflayer/chat/guildLevelUp.ts | 2 - src/events/mineflayer/chat/guildMuteUnmute.ts | 3 +- src/events/mineflayer/chat/joinLeave.ts | 3 +- src/events/mineflayer/chat/joinLimbo.ts | 2 - src/events/mineflayer/chat/joinRequest.ts | 9 ++- src/events/mineflayer/chat/lobbyJoin.ts | 2 - src/events/mineflayer/chat/memberCount.ts | 2 - src/events/mineflayer/chat/memberJoinLeave.ts | 11 ++-- src/events/mineflayer/chat/memberKick.ts | 3 +- src/events/mineflayer/chat/promoteDemote.ts | 5 +- src/events/mineflayer/chat/questComplete.ts | 3 +- .../mineflayer/chat/questTierComplete.ts | 3 +- .../mineflayer/chat/sameMessageTwice.ts | 2 - src/events/mineflayer/chat/whisper.ts | 7 +-- src/events/mineflayer/handler/end.ts | 2 - src/events/mineflayer/handler/error.ts | 2 - src/events/mineflayer/handler/kicked.ts | 3 +- src/events/mineflayer/handler/login.ts | 3 +- src/events/mineflayer/handler/message.ts | 1 - src/index.ts | 2 +- src/interfaces/Command.ts | 11 ---- src/interfaces/Event.ts | 13 ---- src/interfaces/HypixelGuildReponse.ts | 38 ------------ src/interfaces/HypixelPlayerResponse.ts | 56 ----------------- src/interfaces/MojangProfileResponse.ts | 4 -- src/util/blacklist/isUserBlacklisted.ts | 1 - .../requests/FetchError.d.ts} | 2 +- src/util/requests/fetchErrorEmbed.ts | 1 - src/util/requests/fetchHypixelGuild.ts | 42 ++++++++++++- .../requests/fetchHypixelPlayerProfile.ts | 60 ++++++++++++++++++- src/util/requests/fetchMojangProfile.ts | 8 ++- src/util/requests/isFetchError.ts | 2 - tsconfig.json | 28 +++------ 52 files changed, 174 insertions(+), 240 deletions(-) rename src/{interfaces/BlacklistEntry.ts => @types/BlacklistEntry.d.ts} (71%) create mode 100644 src/@types/Command.d.ts create mode 100644 src/@types/Event.d.ts delete mode 100644 src/interfaces/Command.ts delete mode 100644 src/interfaces/Event.ts delete mode 100644 src/interfaces/HypixelGuildReponse.ts delete mode 100644 src/interfaces/HypixelPlayerResponse.ts delete mode 100644 src/interfaces/MojangProfileResponse.ts rename src/{interfaces/FetchError.ts => util/requests/FetchError.d.ts} (65%) diff --git a/src/interfaces/BlacklistEntry.ts b/src/@types/BlacklistEntry.d.ts similarity index 71% rename from src/interfaces/BlacklistEntry.ts rename to src/@types/BlacklistEntry.d.ts index a2f08923..09e96d1e 100644 --- a/src/interfaces/BlacklistEntry.ts +++ b/src/@types/BlacklistEntry.d.ts @@ -1,4 +1,4 @@ -export interface BlacklistEntry { +declare interface BlacklistEntry { name: string; uuid: string; endDate: string; diff --git a/src/@types/Command.d.ts b/src/@types/Command.d.ts new file mode 100644 index 00000000..bfaae1a3 --- /dev/null +++ b/src/@types/Command.d.ts @@ -0,0 +1,14 @@ +declare interface Command { + data: import("discord.js").ChatInputApplicationCommandData; + run: ExecuteCommand; + staffOnly?: boolean; +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type ExecuteCommand = ( + bot: import("@classes/Bot").default, + interaction: import("discord.js").ChatInputCommandInteraction, + // TODO: use never[] below and force implementations to define types explicitly (use spread?) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + args: any[], +) => Promise; diff --git a/src/@types/Event.d.ts b/src/@types/Event.d.ts new file mode 100644 index 00000000..25376e9e --- /dev/null +++ b/src/@types/Event.d.ts @@ -0,0 +1,11 @@ +declare interface Event { + name: + | keyof typeof import("@util/regex").default + | keyof import("mineflayer").BotEvents + | keyof import("discord.js").ClientEvents; + runOnce: boolean; + run: Execute; +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type Execute = (bot: import("@classes/Bot").default, ...params: any[]) => Promise; diff --git a/src/classes/Bot.ts b/src/classes/Bot.ts index 9d57e488..7e500cf4 100644 --- a/src/classes/Bot.ts +++ b/src/classes/Bot.ts @@ -1,15 +1,13 @@ import { ActivityType, ColorResolvable, EmbedBuilder, IntentsBitField, TextChannel } from "discord.js"; import { BotEvents, createBot } from "mineflayer"; -import { Command } from "../interfaces/Command"; import Discord from "./Client"; -import { Event } from "../interfaces/Event"; import EventEmitter from "events"; import consola from "consola"; -import isObjKey from "../util/isObjKey"; -import logError from "../util/logError"; +import isObjKey from "@util/isObjKey"; +import logError from "@util/logError"; import path from "path"; -import recursiveWalkDir from "../util/recursiveWalkDir"; -import regex from "../util/regex"; +import recursiveWalkDir from "@util/recursiveWalkDir"; +import regex from "@util/regex"; class Bot { public readonly logger = consola; diff --git a/src/classes/Client.ts b/src/classes/Client.ts index eaaf8afd..667c1867 100644 --- a/src/classes/Client.ts +++ b/src/classes/Client.ts @@ -1,5 +1,4 @@ import { Client, ClientOptions, Collection } from "discord.js"; -import { Command } from "../interfaces/Command"; export default class Discord extends Client { commands: Collection = new Collection(); diff --git a/src/commands/blacklist.ts b/src/commands/blacklist.ts index 102ef80e..f033b67c 100644 --- a/src/commands/blacklist.ts +++ b/src/commands/blacklist.ts @@ -1,11 +1,9 @@ import { ApplicationCommandOptionType, EmbedBuilder, TextChannel } from "discord.js"; -import { BlacklistEntry } from "../interfaces/BlacklistEntry"; -import { Command } from "../interfaces/Command"; -import _blacklist from "../util/blacklist/_blacklist.json"; -import fetchErrorEmbed from "../util/requests/fetchErrorEmbed"; -import fetchMojangProfile from "../util/requests/fetchMojangProfile"; -import isFetchError from "../util/requests/isFetchError"; -import writeToJsonFile from "../util/writeToJsonFile"; +import _blacklist from "@util/blacklist/_blacklist.json"; +import fetchErrorEmbed from "@util/requests/fetchErrorEmbed"; +import fetchMojangProfile from "@util/requests/fetchMojangProfile"; +import isFetchError from "@util/requests/isFetchError"; +import writeToJsonFile from "@util/writeToJsonFile"; export default { data: { @@ -107,7 +105,8 @@ export default { messageId: blacklistMessage.id, }); } else { - const blacklistEntry = blacklist.find((user) => user.uuid === mojangProfile.id) as BlacklistEntry; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const blacklistEntry = blacklist.find((user) => user.uuid === mojangProfile.id)!; blacklist.splice(blacklist.indexOf(blacklistEntry)); const message = await ( @@ -122,7 +121,7 @@ export default { .setTitle("Completed!") .setDescription(`${mojangProfile.name} was ${type === "add" ? "added to" : "removed from"} the blacklist!`); - writeToJsonFile("./src/util/_blacklist.json", blacklist, interaction, successEmbed); + writeToJsonFile("./s@util/_blacklist.json", blacklist, interaction, successEmbed); }, staffOnly: true, } as Command; diff --git a/src/commands/command.ts b/src/commands/command.ts index e13d35d8..3d3e8717 100644 --- a/src/commands/command.ts +++ b/src/commands/command.ts @@ -1,5 +1,4 @@ import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; -import { Command } from "../interfaces/Command"; export default { data: { diff --git a/src/commands/help.ts b/src/commands/help.ts index 7fffb058..d50f5788 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -1,4 +1,3 @@ -import { Command } from "../interfaces/Command"; import { EmbedBuilder } from "discord.js"; export default { diff --git a/src/commands/invite.ts b/src/commands/invite.ts index 798007b5..8183803a 100644 --- a/src/commands/invite.ts +++ b/src/commands/invite.ts @@ -1,5 +1,4 @@ import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; -import { Command } from "../interfaces/Command"; export default { data: { diff --git a/src/commands/kick.ts b/src/commands/kick.ts index bf5c0dc9..45ab38f9 100644 --- a/src/commands/kick.ts +++ b/src/commands/kick.ts @@ -1,5 +1,4 @@ import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; -import { Command } from "../interfaces/Command"; export default { data: { diff --git a/src/commands/promoteDemote.ts b/src/commands/promoteDemote.ts index 9753b50f..dfaa5875 100644 --- a/src/commands/promoteDemote.ts +++ b/src/commands/promoteDemote.ts @@ -1,6 +1,5 @@ import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; -import { Command } from "../interfaces/Command"; -import capitaliseString from "../util/capitaliseString"; +import capitaliseString from "@util/capitaliseString"; export default { data: { diff --git a/src/commands/reboot.ts b/src/commands/reboot.ts index 05fb16a3..ddc7ed21 100644 --- a/src/commands/reboot.ts +++ b/src/commands/reboot.ts @@ -1,4 +1,3 @@ -import { Command } from "../interfaces/Command"; import { EmbedBuilder } from "discord.js"; export default { diff --git a/src/commands/slowmode.ts b/src/commands/slowmode.ts index 87623826..6adf5d3c 100644 --- a/src/commands/slowmode.ts +++ b/src/commands/slowmode.ts @@ -1,5 +1,4 @@ import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; -import { Command } from "../interfaces/Command"; const choices = [0, 5, 10]; diff --git a/src/commands/toggleMute.ts b/src/commands/toggleMute.ts index 14bf9f16..28218198 100644 --- a/src/commands/toggleMute.ts +++ b/src/commands/toggleMute.ts @@ -1,6 +1,5 @@ import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; -import { Command } from "../interfaces/Command"; -import capitaliseString from "../util/capitaliseString"; +import capitaliseString from "@util/capitaliseString"; export default { data: { diff --git a/src/events/discord/interactionCreate.ts b/src/events/discord/interactionCreate.ts index e2ee9ba0..aa78613e 100644 --- a/src/events/discord/interactionCreate.ts +++ b/src/events/discord/interactionCreate.ts @@ -1,5 +1,4 @@ import { ApplicationCommandOptionType, EmbedBuilder, GuildMember, Interaction } from "discord.js"; -import { Event } from "../../interfaces/Event"; export default { name: "interactionCreate", diff --git a/src/events/discord/message.ts b/src/events/discord/message.ts index 088d3bd9..c85b8385 100644 --- a/src/events/discord/message.ts +++ b/src/events/discord/message.ts @@ -1,7 +1,6 @@ import { Message } from "discord.js"; import { DataSet, RegExpMatcher, englishDataset, englishRecommendedTransformers } from "obscenity"; -import { Event } from "../../interfaces/Event"; -import emojis from "../../util/emojis"; +import emojis from "@util/emojis"; const whitelist = ["ass", "bitch", "cock", "dick", "fuck"]; const dataset = new DataSet<{ originalWord: string }>() diff --git a/src/events/discord/ready.ts b/src/events/discord/ready.ts index b1e27531..6ad1dfd3 100644 --- a/src/events/discord/ready.ts +++ b/src/events/discord/ready.ts @@ -1,4 +1,3 @@ -import { Event } from "../../interfaces/Event"; import { TextChannel } from "discord.js"; export default { diff --git a/src/events/mineflayer/chat/commentBlocked.ts b/src/events/mineflayer/chat/commentBlocked.ts index 77d7e9e9..c8b2a00b 100644 --- a/src/events/mineflayer/chat/commentBlocked.ts +++ b/src/events/mineflayer/chat/commentBlocked.ts @@ -1,5 +1,4 @@ -import Emojis from "../../../util/emojis"; -import { Event } from "../../../interfaces/Event"; +import Emojis from "@util/emojis"; export default { name: "chat:commentBlocked", diff --git a/src/events/mineflayer/chat/guildChat.ts b/src/events/mineflayer/chat/guildChat.ts index 9e28a68a..bb2455ec 100644 --- a/src/events/mineflayer/chat/guildChat.ts +++ b/src/events/mineflayer/chat/guildChat.ts @@ -1,6 +1,5 @@ -import { Event } from "../../../interfaces/Event"; import { escapeMarkdown } from "discord.js"; -import getRankColor from "../../../util/getRankColor"; +import getRankColor from "@util/getRankColor"; export default { name: "chat:guildChat", diff --git a/src/events/mineflayer/chat/guildLevelUp.ts b/src/events/mineflayer/chat/guildLevelUp.ts index 6f999411..c82d6892 100644 --- a/src/events/mineflayer/chat/guildLevelUp.ts +++ b/src/events/mineflayer/chat/guildLevelUp.ts @@ -1,5 +1,3 @@ -import { Event } from "../../../interfaces/Event"; - export default { name: "chat:guildLevelUp", runOnce: false, diff --git a/src/events/mineflayer/chat/guildMuteUnmute.ts b/src/events/mineflayer/chat/guildMuteUnmute.ts index 5b6351b3..ca98a7a5 100644 --- a/src/events/mineflayer/chat/guildMuteUnmute.ts +++ b/src/events/mineflayer/chat/guildMuteUnmute.ts @@ -1,5 +1,4 @@ -import Emojis from "../../../util/emojis"; -import { Event } from "../../../interfaces/Event"; +import Emojis from "@util/emojis"; import { escapeMarkdown } from "discord.js"; export default { diff --git a/src/events/mineflayer/chat/joinLeave.ts b/src/events/mineflayer/chat/joinLeave.ts index 8aa4fcf9..3212415a 100644 --- a/src/events/mineflayer/chat/joinLeave.ts +++ b/src/events/mineflayer/chat/joinLeave.ts @@ -1,5 +1,4 @@ -import Emojis from "../../../util/emojis"; -import { Event } from "../../../interfaces/Event"; +import Emojis from "@util/emojis"; import { escapeMarkdown } from "discord.js"; export default { diff --git a/src/events/mineflayer/chat/joinLimbo.ts b/src/events/mineflayer/chat/joinLimbo.ts index d8436091..234a403f 100644 --- a/src/events/mineflayer/chat/joinLimbo.ts +++ b/src/events/mineflayer/chat/joinLimbo.ts @@ -1,5 +1,3 @@ -import { Event } from "../../../interfaces/Event"; - export default { name: "chat:joinLimbo", runOnce: false, diff --git a/src/events/mineflayer/chat/joinRequest.ts b/src/events/mineflayer/chat/joinRequest.ts index 1552becf..58dae6a2 100644 --- a/src/events/mineflayer/chat/joinRequest.ts +++ b/src/events/mineflayer/chat/joinRequest.ts @@ -1,8 +1,7 @@ -import { Event } from "../../../interfaces/Event"; -import fetchHypixelPlayerProfile from "../../../util/requests/fetchHypixelPlayerProfile"; -import fetchMojangProfile from "../../../util/requests/fetchMojangProfile"; -import isFetchError from "../../../util/requests/isFetchError"; -import isUserBlacklisted from "../../../util/blacklist/isUserBlacklisted"; +import fetchHypixelPlayerProfile from "@util/requests/fetchHypixelPlayerProfile"; +import fetchMojangProfile from "@util/requests/fetchMojangProfile"; +import isFetchError from "@util/requests/isFetchError"; +import isUserBlacklisted from "@util/blacklist/isUserBlacklisted"; export default { name: "chat:joinRequest", diff --git a/src/events/mineflayer/chat/lobbyJoin.ts b/src/events/mineflayer/chat/lobbyJoin.ts index 48ac773b..1ce42741 100644 --- a/src/events/mineflayer/chat/lobbyJoin.ts +++ b/src/events/mineflayer/chat/lobbyJoin.ts @@ -1,5 +1,3 @@ -import { Event } from "../../../interfaces/Event"; - export default { name: "chat:lobbyJoin", runOnce: false, diff --git a/src/events/mineflayer/chat/memberCount.ts b/src/events/mineflayer/chat/memberCount.ts index 29392fbc..0a8c3899 100644 --- a/src/events/mineflayer/chat/memberCount.ts +++ b/src/events/mineflayer/chat/memberCount.ts @@ -1,5 +1,3 @@ -import { Event } from "../../../interfaces/Event"; - export default { name: "chat:memberCount", runOnce: false, diff --git a/src/events/mineflayer/chat/memberJoinLeave.ts b/src/events/mineflayer/chat/memberJoinLeave.ts index 915876d1..573a1906 100644 --- a/src/events/mineflayer/chat/memberJoinLeave.ts +++ b/src/events/mineflayer/chat/memberJoinLeave.ts @@ -1,10 +1,9 @@ -import Emojis from "../../../util/emojis"; -import { Event } from "../../../interfaces/Event"; +import Emojis from "@util/emojis"; import { escapeMarkdown } from "discord.js"; -import fetchMojangProfile from "../../../util/requests/fetchMojangProfile"; -import isFetchError from "../../../util/requests/isFetchError"; -import isUserBlacklisted from "../../../util/blacklist/isUserBlacklisted"; -import getRankColor from "../../../util/getRankColor"; +import fetchMojangProfile from "@util/requests/fetchMojangProfile"; +import isFetchError from "@util/requests/isFetchError"; +import isUserBlacklisted from "@util/blacklist/isUserBlacklisted"; +import getRankColor from "@util/getRankColor"; export default { name: "chat:memberJoinLeave", diff --git a/src/events/mineflayer/chat/memberKick.ts b/src/events/mineflayer/chat/memberKick.ts index e7c08a23..322dbb7f 100644 --- a/src/events/mineflayer/chat/memberKick.ts +++ b/src/events/mineflayer/chat/memberKick.ts @@ -1,5 +1,4 @@ -import Emojis from "../../../util/emojis"; -import { Event } from "../../../interfaces/Event"; +import Emojis from "@util/emojis"; import { escapeMarkdown } from "discord.js"; export default { diff --git a/src/events/mineflayer/chat/promoteDemote.ts b/src/events/mineflayer/chat/promoteDemote.ts index d39e7fb6..82194686 100644 --- a/src/events/mineflayer/chat/promoteDemote.ts +++ b/src/events/mineflayer/chat/promoteDemote.ts @@ -1,7 +1,6 @@ -import Emojis from "../../../util/emojis"; -import { Event } from "../../../interfaces/Event"; import { escapeMarkdown } from "discord.js"; -import getRankColor from "../../../util/getRankColor"; +import Emojis from "@util/emojis"; +import getRankColor from "@util/getRankColor"; export default { name: "chat:promoteDemote", diff --git a/src/events/mineflayer/chat/questComplete.ts b/src/events/mineflayer/chat/questComplete.ts index 8747b977..4542dac9 100644 --- a/src/events/mineflayer/chat/questComplete.ts +++ b/src/events/mineflayer/chat/questComplete.ts @@ -1,5 +1,4 @@ -import Emojis from "../../../util/emojis"; -import { Event } from "../../../interfaces/Event"; +import Emojis from "@util/emojis"; export default { name: "chat:questComplete", diff --git a/src/events/mineflayer/chat/questTierComplete.ts b/src/events/mineflayer/chat/questTierComplete.ts index 6b5563bb..e32bf5b7 100644 --- a/src/events/mineflayer/chat/questTierComplete.ts +++ b/src/events/mineflayer/chat/questTierComplete.ts @@ -1,5 +1,4 @@ -import Emojis from "../../../util/emojis"; -import { Event } from "../../../interfaces/Event"; +import Emojis from "@util/emojis"; export default { name: "chat:questTierComplete", diff --git a/src/events/mineflayer/chat/sameMessageTwice.ts b/src/events/mineflayer/chat/sameMessageTwice.ts index 5f40071c..8ae1439d 100644 --- a/src/events/mineflayer/chat/sameMessageTwice.ts +++ b/src/events/mineflayer/chat/sameMessageTwice.ts @@ -1,5 +1,3 @@ -import { Event } from "../../../interfaces/Event"; - export default { name: "chat:sameMessageTwice", runOnce: false, diff --git a/src/events/mineflayer/chat/whisper.ts b/src/events/mineflayer/chat/whisper.ts index 93ed317c..77f8707c 100644 --- a/src/events/mineflayer/chat/whisper.ts +++ b/src/events/mineflayer/chat/whisper.ts @@ -1,7 +1,6 @@ -import { Event } from "../../../interfaces/Event"; -import fetchHypixelGuild from "../../../util/requests/fetchHypixelGuild"; -import fetchMojangProfile from "../../../util/requests/fetchMojangProfile"; -import isFetchError from "../../../util/requests/isFetchError"; +import fetchHypixelGuild from "@util/requests/fetchHypixelGuild"; +import fetchMojangProfile from "@util/requests/fetchMojangProfile"; +import isFetchError from "@util/requests/isFetchError"; export default { name: "chat:whisper", diff --git a/src/events/mineflayer/handler/end.ts b/src/events/mineflayer/handler/end.ts index 3fc9dfa7..65937827 100644 --- a/src/events/mineflayer/handler/end.ts +++ b/src/events/mineflayer/handler/end.ts @@ -1,5 +1,3 @@ -import { Event } from "../../../interfaces/Event"; - export default { name: "end", runOnce: false, diff --git a/src/events/mineflayer/handler/error.ts b/src/events/mineflayer/handler/error.ts index beef8f65..c91c4c3d 100644 --- a/src/events/mineflayer/handler/error.ts +++ b/src/events/mineflayer/handler/error.ts @@ -1,5 +1,3 @@ -import { Event } from "../../../interfaces/Event"; - export default { name: "error", runOnce: false, diff --git a/src/events/mineflayer/handler/kicked.ts b/src/events/mineflayer/handler/kicked.ts index a0fad7ec..853387ad 100644 --- a/src/events/mineflayer/handler/kicked.ts +++ b/src/events/mineflayer/handler/kicked.ts @@ -1,5 +1,4 @@ -import Emojis from "../../../util/emojis"; -import { Event } from "../../../interfaces/Event"; +import Emojis from "@util/emojis"; export default { name: "kicked", diff --git a/src/events/mineflayer/handler/login.ts b/src/events/mineflayer/handler/login.ts index c29aa021..b6ca9836 100644 --- a/src/events/mineflayer/handler/login.ts +++ b/src/events/mineflayer/handler/login.ts @@ -1,5 +1,4 @@ -import Emojis from "../../../util/emojis"; -import { Event } from "../../../interfaces/Event"; +import Emojis from "@util/emojis"; export default { name: "login", diff --git a/src/events/mineflayer/handler/message.ts b/src/events/mineflayer/handler/message.ts index ddcb3027..71d12a07 100644 --- a/src/events/mineflayer/handler/message.ts +++ b/src/events/mineflayer/handler/message.ts @@ -1,5 +1,4 @@ import { ChatMessage } from "prismarine-chat"; -import { Event } from "../../../interfaces/Event"; export default { name: "message", diff --git a/src/index.ts b/src/index.ts index 1eb9280f..fa8964c2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import { config } from "dotenv"; config(); -import Bot from "./classes/Bot"; +import Bot from "@classes/Bot"; export default new Bot(); diff --git a/src/interfaces/Command.ts b/src/interfaces/Command.ts deleted file mode 100644 index 0190a8ec..00000000 --- a/src/interfaces/Command.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ChatInputApplicationCommandData, ChatInputCommandInteraction } from "discord.js"; -import Bot from "../classes/Bot"; - -export interface Command { - data: ChatInputApplicationCommandData; - run: ExecuteCommand; - staffOnly?: boolean; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type ExecuteCommand = (bot: Bot, interaction: ChatInputCommandInteraction, args: any[]) => Promise; diff --git a/src/interfaces/Event.ts b/src/interfaces/Event.ts deleted file mode 100644 index e41f90a3..00000000 --- a/src/interfaces/Event.ts +++ /dev/null @@ -1,13 +0,0 @@ -import Bot from "../classes/Bot"; -import { BotEvents } from "mineflayer"; -import { ClientEvents } from "discord.js"; -import regex from "../util/regex"; - -export interface Event { - name: keyof typeof regex | keyof BotEvents | keyof ClientEvents; - runOnce: boolean; - run: Execute; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type Execute = (bot: Bot, ...params: any[]) => Promise; diff --git a/src/interfaces/HypixelGuildReponse.ts b/src/interfaces/HypixelGuildReponse.ts deleted file mode 100644 index 895ae5b0..00000000 --- a/src/interfaces/HypixelGuildReponse.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Source: https://github.com/unaussprechlich/hypixel-api-typescript/ - */ -export interface HypixelGuildResponse { - _id: string; - name: string; - coins: number; - memberSizeLevel: number; - bankSizeLevel: number; - coinsEver: number; - created: number; - members: Member[]; - canParty: boolean; - canTag: boolean; - tag?: string; - banner?: Banner; - canMotd?: boolean; - vipCount?: number; - mvpCount?: number; - tagColor?: string; -} - -interface Member { - uuid: string; - rank: string; - joined: number; - expHistory: { [key: number]: number }; -} - -interface Banner { - Base?: string; - Patterns?: Pattern[]; -} - -interface Pattern { - Pattern?: string; - Color?: string | number; -} diff --git a/src/interfaces/HypixelPlayerResponse.ts b/src/interfaces/HypixelPlayerResponse.ts deleted file mode 100644 index e194c5ed..00000000 --- a/src/interfaces/HypixelPlayerResponse.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Attenuated Version of Source: https://github.com/unaussprechlich/hypixel-api-typescript/ - */ -export interface HypixelPlayerResponse { - id: string; - achievementsOneTime?: (string | null[] | null)[] | null; - channel?: string; - disguise?: string; - displayname: string; - eulaCoins?: boolean; - firstLogin?: number; - friendRequests?: null[] | null; - karma?: number; - knownAliases?: string[] | null; - knownAliasesLower?: string[] | null; - lastLogin?: number; - mainlobbytutorial?: boolean; - mostRecentMinecraftVersion?: number; - mostRecentlyThanked?: string; - mostRecentlyThankedUuid?: string; - mostRecentlyTipped?: string; - mostRecentlyTippedUuid?: string; - networkExp?: number; - newClock?: string; - notifications?: boolean; - packageRank?: string; - playername?: string; - pp?: string; - spectators_invisible?: boolean; - testPass?: boolean; - thanksSent?: number; - timePlaying?: number; - uuid?: string; - vanityTokens?: number; - wardrobe?: string; - websiteSet?: boolean; - gadget?: string; - friendRequestsUuid?: null[] | null; - lastEugeneMessage?: number; - last_survey?: number; - particleQuality?: string; - mcVersionRp?: string; - - rankPlusColor?: string; - lastAdsenseGenerateTime?: number; - lastClaimedReward?: number; - totalRewards?: number; - totalDailyRewards?: number; - rewardStreak?: number; - rewardScore?: number; - rewardHighScore?: number; - vanityConvertedBoxToday?: number; - vanityFirstConvertedBox?: number; - adsense_tokens?: number; - userLanguage?: string; -} diff --git a/src/interfaces/MojangProfileResponse.ts b/src/interfaces/MojangProfileResponse.ts deleted file mode 100644 index 760ca0e7..00000000 --- a/src/interfaces/MojangProfileResponse.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface MojangProfileResponse { - readonly id: string; - readonly name: string; -} diff --git a/src/util/blacklist/isUserBlacklisted.ts b/src/util/blacklist/isUserBlacklisted.ts index d906ad3d..093ec11b 100644 --- a/src/util/blacklist/isUserBlacklisted.ts +++ b/src/util/blacklist/isUserBlacklisted.ts @@ -1,4 +1,3 @@ -import { BlacklistEntry } from "../../interfaces/BlacklistEntry"; import _blacklist from "./_blacklist.json"; export default (uuid: string) => { diff --git a/src/interfaces/FetchError.ts b/src/util/requests/FetchError.d.ts similarity index 65% rename from src/interfaces/FetchError.ts rename to src/util/requests/FetchError.d.ts index a2f11871..99a79e22 100644 --- a/src/interfaces/FetchError.ts +++ b/src/util/requests/FetchError.d.ts @@ -1,4 +1,4 @@ -export interface FetchError { +declare interface FetchError { readonly status: number; readonly statusText: string; } diff --git a/src/util/requests/fetchErrorEmbed.ts b/src/util/requests/fetchErrorEmbed.ts index 0f9b8d5a..af694d78 100644 --- a/src/util/requests/fetchErrorEmbed.ts +++ b/src/util/requests/fetchErrorEmbed.ts @@ -1,4 +1,3 @@ -import { FetchError } from "../../interfaces/FetchError"; import { EmbedBuilder } from "discord.js"; export default (requestError: FetchError) => { diff --git a/src/util/requests/fetchHypixelGuild.ts b/src/util/requests/fetchHypixelGuild.ts index 6be4e7f4..70dbcaeb 100644 --- a/src/util/requests/fetchHypixelGuild.ts +++ b/src/util/requests/fetchHypixelGuild.ts @@ -1,6 +1,3 @@ -import { FetchError } from "../../interfaces/FetchError"; -import { HypixelGuildResponse } from "../../interfaces/HypixelGuildReponse"; - export default async (uuid: string) => { const response = await fetch(`https://api.hypixel.net/guild?key=${process.env.HYPIXEL_API_KEY}&player=${uuid}`); @@ -8,3 +5,42 @@ export default async (uuid: string) => { ? (((await response.json()) as any).guild as HypixelGuildResponse) // eslint-disable-line @typescript-eslint/no-explicit-any : (response as FetchError); }; + +/** + * Source: https://github.com/unaussprechlich/hypixel-api-typescript/ + */ +interface HypixelGuildResponse { + _id: string; + name: string; + coins: number; + memberSizeLevel: number; + bankSizeLevel: number; + coinsEver: number; + created: number; + members: Member[]; + canParty: boolean; + canTag: boolean; + tag?: string; + banner?: Banner; + canMotd?: boolean; + vipCount?: number; + mvpCount?: number; + tagColor?: string; +} + +interface Member { + uuid: string; + rank: string; + joined: number; + expHistory: { [key: number]: number }; +} + +interface Banner { + Base?: string; + Patterns?: Pattern[]; +} + +interface Pattern { + Pattern?: string; + Color?: string | number; +} diff --git a/src/util/requests/fetchHypixelPlayerProfile.ts b/src/util/requests/fetchHypixelPlayerProfile.ts index f633e195..08f0b61d 100644 --- a/src/util/requests/fetchHypixelPlayerProfile.ts +++ b/src/util/requests/fetchHypixelPlayerProfile.ts @@ -1,6 +1,3 @@ -import { FetchError } from "../../interfaces/FetchError"; -import { HypixelPlayerResponse } from "../../interfaces/HypixelPlayerResponse"; - export default async (username: string) => { const response = await fetch(`https://api.hypixel.net/player?key=${process.env.HYPIXEL_API_KEY}&name=${username}`); @@ -8,3 +5,60 @@ export default async (username: string) => { ? (((await response.json()) as any).player as HypixelPlayerResponse) // eslint-disable-line @typescript-eslint/no-explicit-any : (response as FetchError); }; + +/** + * Attenuated Version of Source: https://github.com/unaussprechlich/hypixel-api-typescript/ + */ +interface HypixelPlayerResponse { + id: string; + achievementsOneTime?: (string | null[] | null)[] | null; + channel?: string; + disguise?: string; + displayname: string; + eulaCoins?: boolean; + firstLogin?: number; + friendRequests?: null[] | null; + karma?: number; + knownAliases?: string[] | null; + knownAliasesLower?: string[] | null; + lastLogin?: number; + mainlobbytutorial?: boolean; + mostRecentMinecraftVersion?: number; + mostRecentlyThanked?: string; + mostRecentlyThankedUuid?: string; + mostRecentlyTipped?: string; + mostRecentlyTippedUuid?: string; + networkExp?: number; + newClock?: string; + notifications?: boolean; + packageRank?: string; + playername?: string; + pp?: string; + spectators_invisible?: boolean; + testPass?: boolean; + thanksSent?: number; + timePlaying?: number; + uuid?: string; + vanityTokens?: number; + wardrobe?: string; + websiteSet?: boolean; + gadget?: string; + friendRequestsUuid?: null[] | null; + lastEugeneMessage?: number; + last_survey?: number; + particleQuality?: string; + mcVersionRp?: string; + + rankPlusColor?: string; + lastAdsenseGenerateTime?: number; + lastClaimedReward?: number; + totalRewards?: number; + totalDailyRewards?: number; + rewardStreak?: number; + rewardScore?: number; + rewardHighScore?: number; + vanityConvertedBoxToday?: number; + vanityFirstConvertedBox?: number; + adsense_tokens?: number; + userLanguage?: string; +} diff --git a/src/util/requests/fetchMojangProfile.ts b/src/util/requests/fetchMojangProfile.ts index ba346f5a..5d5fa239 100644 --- a/src/util/requests/fetchMojangProfile.ts +++ b/src/util/requests/fetchMojangProfile.ts @@ -1,8 +1,10 @@ -import { FetchError } from "../../interfaces/FetchError"; -import { MojangProfileResponse } from "../../interfaces/MojangProfileResponse"; - export default async (username: string) => { const response = await fetch(`https://api.mojang.com/users/profiles/minecraft/${username}`); return response.status === 200 ? ((await response.json()) as MojangProfileResponse) : (response as FetchError); }; + +interface MojangProfileResponse { + readonly id: string; + readonly name: string; +} diff --git a/src/util/requests/isFetchError.ts b/src/util/requests/isFetchError.ts index 0dccddea..07576634 100644 --- a/src/util/requests/isFetchError.ts +++ b/src/util/requests/isFetchError.ts @@ -1,5 +1,3 @@ -import { FetchError } from "../../interfaces/FetchError"; - // eslint-disable-next-line @typescript-eslint/no-explicit-any export default (response: any | FetchError): response is FetchError => { return !response || ("status" in response && "statusText" in response); diff --git a/tsconfig.json b/tsconfig.json index 7f683cbc..f224757f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,37 +1,23 @@ { "compilerOptions": { - "lib": ["ESNext"], - "module": "CommonJS", "target": "ESNext", - "noImplicitAny": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, + "module": "NodeNext", + "moduleResolution": "NodeNext", "outDir": "./dist", - "moduleResolution": "Node", "resolveJsonModule": true, - "removeComments": true, "preserveConstEnums": true, "strict": true, - "alwaysStrict": true, - "strictNullChecks": true, "noUncheckedIndexedAccess": true, "noImplicitReturns": true, - "noImplicitThis": true, - "noUnusedLocals": true, - "noUnusedParameters": true, "allowUnreachableCode": false, - "noFallthroughCasesInSwitch": true, - "declaration": true, - "sourceMap": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "allowJs": false, "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, "isolatedModules": true, - "incremental": true, - "typeRoots": ["node_modules/@types", "src/@types"] - }, - "exclude": ["./node_modules/**/*", "**/*.spec.ts"], - "include": ["./src", "./setupFiles.js"] + "paths": { + "@classes/*": ["./src/classes/*"], + "@util/*": ["./src/util/*"] + } + } } From 3f703c59e806a95c82d88a20dedcd3964e8413b8 Mon Sep 17 00:00:00 2001 From: John Doe <69335633+Jejebecarte@users.noreply.github.com> Date: Fri, 12 Apr 2024 12:13:09 +1000 Subject: [PATCH 3/8] refactor: add prettier and ESLint config and path aliases --- .eslintignore | 3 - .eslintrc.json | 18 +- .github/dependabot.yml | 6 +- .prettierrc | 10 - .prettierrc.js | 1 + package.json | 68 +- pnpm-lock.yaml | 1270 ++++++++++++++++- scripts/setup-files.js | 20 + setupFiles.js | 17 - src/@types/BlacklistEntry.d.ts | 10 +- src/@types/Command.d.ts | 16 +- src/@types/Event.d.ts | 15 +- src/@types/environment.d.ts | 48 +- src/classes/Bot.ts | 376 ++--- src/classes/Client.ts | 8 +- src/commands/blacklist.ts | 237 +-- src/commands/command.ts | 62 +- src/commands/help.ts | 24 +- src/commands/invite.ts | 59 +- src/commands/kick.ts | 73 +- src/commands/promoteDemote.ts | 102 +- src/commands/reboot.ts | 39 +- src/commands/slowmode.ts | 50 +- src/commands/toggleMute.ts | 126 +- src/events/discord/interactionCreate.ts | 102 +- src/events/discord/message.ts | 116 +- src/events/discord/ready.ts | 22 +- src/events/mineflayer/chat/commentBlocked.ts | 20 +- src/events/mineflayer/chat/guildChat.ts | 34 +- src/events/mineflayer/chat/guildLevelUp.ts | 15 +- src/events/mineflayer/chat/guildMuteUnmute.ts | 40 +- src/events/mineflayer/chat/joinLeave.ts | 26 +- src/events/mineflayer/chat/joinLimbo.ts | 10 +- src/events/mineflayer/chat/joinRequest.ts | 51 +- src/events/mineflayer/chat/lobbyJoin.ts | 12 +- src/events/mineflayer/chat/memberCount.ts | 20 +- src/events/mineflayer/chat/memberJoinLeave.ts | 52 +- src/events/mineflayer/chat/memberKick.ts | 42 +- src/events/mineflayer/chat/promoteDemote.ts | 44 +- src/events/mineflayer/chat/questComplete.ts | 22 +- .../mineflayer/chat/questTierComplete.ts | 22 +- .../mineflayer/chat/sameMessageTwice.ts | 10 +- src/events/mineflayer/chat/whisper.ts | 54 +- src/events/mineflayer/handler/end.ts | 16 +- src/events/mineflayer/handler/error.ts | 18 +- src/events/mineflayer/handler/kicked.ts | 100 +- src/events/mineflayer/handler/login.ts | 44 +- src/events/mineflayer/handler/message.ts | 14 +- src/index.ts | 5 +- src/util/blacklist/isUserBlacklisted.ts | 6 +- src/util/capitaliseString.ts | 4 +- src/util/emojis.ts | 64 +- src/util/getRankColor.ts | 40 +- src/util/isObjKey.ts | 5 +- src/util/logError.ts | 16 +- src/util/recursiveWalkDir.ts | 38 +- src/util/regex.ts | 253 ++-- src/util/requests/FetchError.d.ts | 4 +- src/util/requests/fetchErrorEmbed.ts | 17 +- src/util/requests/fetchHypixelGuild.ts | 58 +- .../requests/fetchHypixelPlayerProfile.ts | 110 +- src/util/requests/fetchMojangProfile.ts | 10 +- src/util/requests/isFetchError.ts | 6 +- src/util/writeToJsonFile.ts | 51 +- tsconfig.json | 42 +- 65 files changed, 2795 insertions(+), 1498 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .prettierrc create mode 100644 .prettierrc.js create mode 100644 scripts/setup-files.js delete mode 100644 setupFiles.js diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 9be3fbfa..00000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -node_modules -dist -pnpm-lock.yaml diff --git a/.eslintrc.json b/.eslintrc.json index c6c64d68..a93fc462 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,18 +1,4 @@ { - "env": { - "node": true - }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "eslint-config-prettier" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module", - "project": "./tsconfig.json" - }, - "plugins": ["@typescript-eslint"] + "extends": "@jejebecarte", + "ignorePatterns": ["dist", "pnpm-lock.yaml"] } diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 82ef6ac7..599c3a2e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,7 +5,7 @@ version: 2 updates: - - package-ecosystem: "npm" # See documentation for possible values - directory: "/" # Location of package manifests + - package-ecosystem: 'npm' # See documentation for possible values + directory: '/' # Location of package manifests schedule: - interval: "monthly" + interval: 'monthly' diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 4ddd1d66..00000000 --- a/.prettierrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "bracketSpacing": true, - "singleQuote": false, - "semi": true, - "trailingComma": "all", - "arrowParens": "always", - "useTabs": true, - "tabWidth": 4, - "printWidth": 120 -} diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000..3a40ba70 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1 @@ +module.exports = require('@jejebecarte/eslint-config/prettier'); diff --git a/package.json b/package.json index 812ba1d3..68f4110b 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,36 @@ { - "name": "bridge-bot", - "version": "1.0.0", - "main": "dist", - "license": "MIT", - "private": false, - "scripts": { - "build": "tsc", - "clean": "rm -r dist/", - "dev": "ts-node-dev --respawn --transpile-only --poll src/index.ts", - "format": "prettier --write .", - "lint": "prettier --check . && eslint .", - "pm2": "pm2 logs && pm2 start dist/index.js --name bridge", - "pm2:kill": "pm2 kill", - "setup-files": "node setupFiles.js", - "start": "node ." - }, - "dependencies": { - "consola": "^2.15.3", - "discord.js": "14.10.2", - "dotenv": "^16.0.3", - "mineflayer": "^4.4.0", - "obscenity": "^0.1.4", - "prismarine-chat": "^1.9.1" - }, - "devDependencies": { - "@types/node-fetch": "^2.6.2", - "@typescript-eslint/eslint-plugin": "^5.40.1", - "@typescript-eslint/parser": "^5.36.1", - "eslint": "^8.26.0", - "eslint-config-prettier": "^8.6.0", - "prettier": "^2.8.4", - "ts-node-dev": "^2.0.0", - "typescript": "^4.8.4" - } + "name": "bridge-bot", + "version": "1.0.0", + "main": "dist", + "license": "MIT", + "private": false, + "scripts": { + "build": "tsc && tsc-alias", + "clean": "rm -r dist/", + "dev": "ts-node-dev --respawn --transpile-only --poll -r tsconfig-paths/register src/index.ts", + "format": "prettier --write .", + "lint": "prettier --check . && eslint .", + "pm2": "pm2 logs && pm2 start dist/index.js --name bridge", + "pm2:kill": "pm2 kill", + "setup-files": "node scripts/setup-files.js", + "start": "node ." + }, + "dependencies": { + "consola": "^2.15.3", + "discord.js": "14.10.2", + "dotenv": "^16.0.3", + "mineflayer": "^4.4.0", + "obscenity": "^0.1.4", + "prismarine-chat": "^1.9.1" + }, + "devDependencies": { + "@jejebecarte/eslint-config": "^1.0.6", + "@types/node-fetch": "^2.6.2", + "eslint": "^8.26.0", + "prettier": "^2.8.4", + "ts-node-dev": "^2.0.0", + "tsc-alias": "^1.8.8", + "tsconfig-paths": "^4.2.0", + "typescript": "^4.8.4" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 063db655..4604e676 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,27 +25,27 @@ dependencies: version: 1.9.1 devDependencies: + '@jejebecarte/eslint-config': + specifier: ^1.0.6 + version: 1.0.6(eslint@8.54.0)(prettier@2.8.8)(typescript@4.9.5) '@types/node-fetch': specifier: ^2.6.2 version: 2.6.9 - '@typescript-eslint/eslint-plugin': - specifier: ^5.40.1 - version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0)(typescript@4.9.5) - '@typescript-eslint/parser': - specifier: ^5.36.1 - version: 5.62.0(eslint@8.54.0)(typescript@4.9.5) eslint: specifier: ^8.26.0 version: 8.54.0 - eslint-config-prettier: - specifier: ^8.6.0 - version: 8.10.0(eslint@8.54.0) prettier: specifier: ^2.8.4 version: 2.8.8 ts-node-dev: specifier: ^2.0.0 version: 2.0.0(@types/node@20.9.2)(typescript@4.9.5) + tsc-alias: + specifier: ^1.8.8 + version: 1.8.8 + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 typescript: specifier: ^4.8.4 version: 4.9.5 @@ -71,6 +71,13 @@ packages: uuid: 8.3.2 dev: false + /@babel/runtime@7.24.4: + resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: true + /@cspotcode/source-map-support@0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -207,6 +214,32 @@ packages: resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} dev: true + /@jejebecarte/eslint-config@1.0.6(eslint@8.54.0)(prettier@2.8.8)(typescript@4.9.5): + resolution: {integrity: sha512-GhPWxJBu6D6KuzXVu68hS5dAkjep9uG88ckhCMBXQLjIWAkEZH4dUfkPvEyzedWdjH7s7eLuxcZEpF3dEfKrfQ==} + peerDependencies: + eslint: ^8.38.0 + prettier: ^2.8.7 + dependencies: + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0)(typescript@4.9.5) + '@typescript-eslint/parser': 5.62.0(eslint@8.54.0)(typescript@4.9.5) + eslint: 8.54.0 + eslint-config-airbnb: 19.0.4(eslint-plugin-import@2.29.1)(eslint-plugin-jsx-a11y@6.8.0)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.34.1)(eslint@8.54.0) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1)(eslint@8.54.0) + eslint-config-airbnb-typescript: 17.1.0(@typescript-eslint/eslint-plugin@5.62.0)(@typescript-eslint/parser@5.62.0)(eslint-plugin-import@2.29.1)(eslint@8.54.0) + eslint-config-prettier: 8.10.0(eslint@8.54.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0)(eslint@8.54.0) + eslint-plugin-jsx-a11y: 6.8.0(eslint@8.54.0) + eslint-plugin-react: 7.34.1(eslint@8.54.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.54.0) + eslint-plugin-testing-library: 5.11.1(eslint@8.54.0)(typescript@4.9.5) + prettier: 2.8.8 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + - typescript + dev: true + /@jridgewell/resolve-uri@3.1.1: resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} engines: {node: '>=6.0.0'} @@ -286,6 +319,10 @@ packages: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} dev: true + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + /@types/node-fetch@2.6.9: resolution: {integrity: sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA==} dependencies: @@ -541,19 +578,138 @@ packages: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true + /aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + dependencies: + dequal: 2.0.3 + dev: true + + /array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + is-array-buffer: 3.0.4 + dev: true + + /array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + is-string: 1.0.7 + dev: true + /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} dev: true + /array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.findlastindex@1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.toreversed@1.1.2: + resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.tosorted@1.1.3: + resolution: {integrity: sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-shim-unscopables: 1.0.2 + dev: true + + /arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + is-array-buffer: 3.0.4 + is-shared-array-buffer: 1.0.3 + dev: true + /asn1@0.2.3: resolution: {integrity: sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w==} dev: false + /ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + dev: true + /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: true + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 + dev: true + + /axe-core@4.7.0: + resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} + engines: {node: '>=4'} + dev: true + /axios@0.21.4(debug@4.3.4): resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} dependencies: @@ -562,6 +718,12 @@ packages: - debug dev: false + /axobject-query@3.2.1: + resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + dependencies: + dequal: 2.0.3 + dev: true + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true @@ -609,6 +771,17 @@ packages: ieee754: 1.2.1 dev: false + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + dev: true + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -659,10 +832,19 @@ packages: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} dev: false + /commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + dev: true + /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true + /confusing-browser-globals@1.0.11: + resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} + dev: true + /consola@2.15.3: resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} dev: false @@ -680,6 +862,48 @@ packages: which: 2.0.2 dev: true + /damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + dev: true + + /data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -695,11 +919,34 @@ packages: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + dev: true + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + dev: true + /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} dev: true + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: true + /diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} @@ -743,6 +990,13 @@ packages: - utf-8-validate dev: false + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + /doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} @@ -767,15 +1021,184 @@ packages: safe-buffer: 5.2.1 dev: false + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + /endian-toggle@0.0.0: resolution: {integrity: sha512-ShfqhXeHRE4TmggSlHXG8CMGIcsOsqDw/GcoPcosToE59Rm9e4aXaMhEQf2kPBsBRrKem1bbOAv5gOKnkliMFQ==} dev: false + /es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.1 + arraybuffer.prototype.slice: 1.0.3 + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + data-view-buffer: 1.0.1 + data-view-byte-length: 1.0.1 + data-view-byte-offset: 1.0.0 + es-define-property: 1.0.0 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-set-tostringtag: 2.0.3 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.4 + get-symbol-description: 1.0.2 + globalthis: 1.0.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + internal-slot: 1.0.7 + is-array-buffer: 3.0.4 + is-callable: 1.2.7 + is-data-view: 1.0.1 + is-negative-zero: 2.0.3 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.3 + is-string: 1.0.7 + is-typed-array: 1.1.13 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.2 + safe-array-concat: 1.1.2 + safe-regex-test: 1.0.3 + string.prototype.trim: 1.2.9 + string.prototype.trimend: 1.0.8 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.2 + typed-array-byte-length: 1.0.1 + typed-array-byte-offset: 1.0.2 + typed-array-length: 1.0.6 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.15 + dev: true + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + dev: true + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + dev: true + + /es-iterator-helpers@1.0.18: + resolution: {integrity: sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-set-tostringtag: 2.0.3 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + globalthis: 1.0.3 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + internal-slot: 1.0.7 + iterator.prototype: 1.1.2 + safe-array-concat: 1.1.2 + dev: true + + /es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + dev: true + + /es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + dev: true + + /es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + dependencies: + hasown: 2.0.2 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} dev: true + /eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.29.1)(eslint@8.54.0): + resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: ^7.32.0 || ^8.2.0 + eslint-plugin-import: ^2.25.2 + dependencies: + confusing-browser-globals: 1.0.11 + eslint: 8.54.0 + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0)(eslint@8.54.0) + object.assign: 4.1.5 + object.entries: 1.1.8 + semver: 6.3.1 + dev: true + + /eslint-config-airbnb-typescript@17.1.0(@typescript-eslint/eslint-plugin@5.62.0)(@typescript-eslint/parser@5.62.0)(eslint-plugin-import@2.29.1)(eslint@8.54.0): + resolution: {integrity: sha512-GPxI5URre6dDpJ0CtcthSZVBAfI+Uw7un5OYNVxP2EYi3H81Jw701yFP7AU+/vCE7xBtFmjge7kfhhk4+RAiig==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^5.13.0 || ^6.0.0 + '@typescript-eslint/parser': ^5.0.0 || ^6.0.0 + eslint: ^7.32.0 || ^8.2.0 + eslint-plugin-import: ^2.25.3 + dependencies: + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0)(typescript@4.9.5) + '@typescript-eslint/parser': 5.62.0(eslint@8.54.0)(typescript@4.9.5) + eslint: 8.54.0 + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1)(eslint@8.54.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0)(eslint@8.54.0) + dev: true + + /eslint-config-airbnb@19.0.4(eslint-plugin-import@2.29.1)(eslint-plugin-jsx-a11y@6.8.0)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.34.1)(eslint@8.54.0): + resolution: {integrity: sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==} + engines: {node: ^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.32.0 || ^8.2.0 + eslint-plugin-import: ^2.25.3 + eslint-plugin-jsx-a11y: ^6.5.1 + eslint-plugin-react: ^7.28.0 + eslint-plugin-react-hooks: ^4.3.0 + dependencies: + eslint: 8.54.0 + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1)(eslint@8.54.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0)(eslint@8.54.0) + eslint-plugin-jsx-a11y: 6.8.0(eslint@8.54.0) + eslint-plugin-react: 7.34.1(eslint@8.54.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.54.0) + object.assign: 4.1.5 + object.entries: 1.1.8 + dev: true + /eslint-config-prettier@8.10.0(eslint@8.54.0): resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==} hasBin: true @@ -785,6 +1208,154 @@ packages: eslint: 8.54.0 dev: true + /eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.1 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils@2.8.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.54.0): + resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 5.62.0(eslint@8.54.0)(typescript@4.9.5) + debug: 3.2.7 + eslint: 8.54.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-import@2.29.1(@typescript-eslint/parser@5.62.0)(eslint@8.54.0): + resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 5.62.0(eslint@8.54.0)(typescript@4.9.5) + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.54.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.54.0) + hasown: 2.0.2 + is-core-module: 2.13.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.0 + semver: 6.3.1 + tsconfig-paths: 3.15.0 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-jsx-a11y@6.8.0(eslint@8.54.0): + resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + '@babel/runtime': 7.24.4 + aria-query: 5.3.0 + array-includes: 3.1.8 + array.prototype.flatmap: 1.3.2 + ast-types-flow: 0.0.8 + axe-core: 4.7.0 + axobject-query: 3.2.1 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + es-iterator-helpers: 1.0.18 + eslint: 8.54.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + dev: true + + /eslint-plugin-react-hooks@4.6.0(eslint@8.54.0): + resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + dependencies: + eslint: 8.54.0 + dev: true + + /eslint-plugin-react@7.34.1(eslint@8.54.0): + resolution: {integrity: sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + array-includes: 3.1.8 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.2 + array.prototype.toreversed: 1.1.2 + array.prototype.tosorted: 1.1.3 + doctrine: 2.1.0 + es-iterator-helpers: 1.0.18 + eslint: 8.54.0 + estraverse: 5.3.0 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + object.hasown: 1.1.4 + object.values: 1.2.0 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.11 + dev: true + + /eslint-plugin-testing-library@5.11.1(eslint@8.54.0)(typescript@4.9.5): + resolution: {integrity: sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} + peerDependencies: + eslint: ^7.5.0 || ^8.0.0 + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@8.54.0)(typescript@4.9.5) + eslint: 8.54.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} @@ -984,6 +1555,12 @@ packages: debug: 4.3.4 dev: false + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -1009,6 +1586,40 @@ packages: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} dev: true + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + dev: true + + /get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + dev: true + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1041,6 +1652,13 @@ packages: type-fest: 0.20.2 dev: true + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: true + /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -1053,25 +1671,65 @@ packages: slash: 3.0.0 dev: true + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + dev: true + /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} dev: true - /hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} - engines: {node: '>= 0.4'} + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} dependencies: - function-bind: 1.1.2 + es-define-property: 1.0.0 dev: true - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: false + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false /ignore@5.3.0: resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} @@ -1101,6 +1759,36 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + /internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 + dev: true + + /is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /is-async-function@2.0.0: + resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + /is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -1108,17 +1796,57 @@ packages: binary-extensions: 2.2.0 dev: true + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + /is-core-module@2.13.1: resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} dependencies: hasown: 2.0.0 dev: true + /is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + dependencies: + is-typed-array: 1.1.13 + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} dev: true + /is-finalizationregistry@1.0.2: + resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + /is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -1126,6 +1854,23 @@ packages: is-extglob: 2.1.1 dev: true + /is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + dev: true + + /is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -1136,14 +1881,92 @@ packages: engines: {node: '>=8'} dev: true + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + dev: true + + /is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.15 + dev: true + + /is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-weakset@2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true + /iterator.prototype@1.1.2: + resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} + dependencies: + define-properties: 1.2.1 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + reflect.getprototypeof: 1.0.6 + set-function-name: 2.0.2 + dev: true + /jose@4.15.4: resolution: {integrity: sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==} dev: false + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + /js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -1162,6 +1985,19 @@ packages: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + /jsonwebtoken@9.0.2: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} @@ -1178,6 +2014,16 @@ packages: semver: 7.5.4 dev: false + /jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + dependencies: + array-includes: 3.1.8 + array.prototype.flat: 1.3.2 + object.assign: 4.1.5 + object.values: 1.2.0 + dev: true + /jwa@1.4.1: resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} dependencies: @@ -1199,6 +2045,17 @@ packages: json-buffer: 3.0.1 dev: true + /language-subtag-registry@0.3.22: + resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} + dev: true + + /language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + dependencies: + language-subtag-registry: 0.3.22 + dev: true + /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1261,6 +2118,13 @@ packages: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: false + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: true + /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -1392,7 +2256,11 @@ packages: /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: false + + /mylas@2.1.13: + resolution: {integrity: sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==} + engines: {node: '>=12.0.0'} + dev: true /natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} @@ -1435,6 +2303,76 @@ packages: engines: {node: '>=0.10.0'} dev: true + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.entries@1.1.8: + resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + dev: true + + /object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + dev: true + + /object.hasown@1.1.4: + resolution: {integrity: sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + dev: true + + /object.values@1.2.0: + resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + /obscenity@0.1.4: resolution: {integrity: sha512-Uw0uCWcwF038YLIiYjdjXZ7fn5WKDEqMVZ2xIs9/dSm1Ho0+EpZANOzO/6rmu/ziRRXaopbPCeh5hid/O8zdZw==} engines: {node: '>=12.0.0'} @@ -1513,6 +2451,18 @@ packages: engines: {node: '>=8.6'} dev: true + /plimit-lit@1.6.1: + resolution: {integrity: sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==} + engines: {node: '>=12'} + dependencies: + queue-lit: 1.5.2 + dev: true + + /possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + dev: true + /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -1660,6 +2610,14 @@ packages: engines: {node: '>= 0.6.0'} dev: false + /prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + dev: true + /protodef-validator@1.3.1: resolution: {integrity: sha512-lZ5FWKZYR9xOjpMw1+EfZRfCjzNRQWPq+Dk+jki47Sikl2EeWEPnTfnJERwnU/EwFq6us+0zqHHzSsmLeYX+Lg==} hasBin: true @@ -1681,6 +2639,11 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + /queue-lit@1.5.2: + resolution: {integrity: sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==} + engines: {node: '>=12'} + dev: true + /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true @@ -1697,6 +2660,10 @@ packages: ret: 0.1.15 dev: false + /react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + dev: true + /readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -1731,6 +2698,33 @@ packages: picomatch: 2.3.1 dev: true + /reflect.getprototypeof@1.0.6: + resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + globalthis: 1.0.3 + which-builtin-type: 1.1.3 + dev: true + + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: true + + /regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + dev: true + /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1745,6 +2739,15 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true + /resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + /ret@0.1.15: resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} engines: {node: '>=0.12'} @@ -1783,6 +2786,16 @@ packages: dev: false optional: true + /safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + /safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} dev: false @@ -1791,6 +2804,20 @@ packages: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} dev: false + /safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-regex: 1.1.4 + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + /semver@7.5.4: resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} @@ -1798,6 +2825,28 @@ packages: dependencies: lru-cache: 6.0.0 + /set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + dev: true + + /set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + dev: true + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -1810,6 +2859,16 @@ packages: engines: {node: '>=8'} dev: true + /side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.1 + dev: true + /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -1832,6 +2891,51 @@ packages: engines: {node: '>=0.10.0'} dev: true + /string.prototype.matchall@4.0.11: + resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.7 + regexp.prototype.flags: 1.5.2 + set-function-name: 2.0.2 + side-channel: 1.0.6 + dev: true + + /string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + dev: true + + /string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + /string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: @@ -1971,6 +3075,36 @@ packages: yn: 3.1.1 dev: true + /tsc-alias@1.8.8: + resolution: {integrity: sha512-OYUOd2wl0H858NvABWr/BoSKNERw3N9GTi3rHPK8Iv4O1UyUXIrTTOAZNHsjlVpXFOhpJBVARI1s+rzwLivN3Q==} + hasBin: true + dependencies: + chokidar: 3.5.3 + commander: 9.5.0 + globby: 11.1.0 + mylas: 2.1.13 + normalize-path: 3.0.0 + plimit-lit: 1.6.1 + dev: true + + /tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + /tsconfig@7.0.0: resolution: {integrity: sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==} dependencies: @@ -2010,6 +3144,50 @@ packages: engines: {node: '>=10'} dev: true + /typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-typed-array: 1.1.13 + dev: true + + /typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + dev: true + + /typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + dev: true + + /typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + possible-typed-array-names: 1.0.0 + dev: true + /typed-emitter@1.4.0: resolution: {integrity: sha512-weBmoo3HhpKGgLBOYwe8EB31CzDFuaK7CCL+axXhUYhn4jo6DSkHnbefboCF5i4DQ2aMFe0C/FdTWcPdObgHyg==} dev: false @@ -2030,6 +3208,15 @@ packages: resolution: {integrity: sha512-lhEx78gdTwFWG+mt6cWAZD/R6qrIj0TTBeH5xwyuDJyswLNlGe+KVlUPQ6+mx5Ld332pS0AMUTo9hIly7YsWxQ==} dev: false + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.7 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -2079,6 +3266,55 @@ packages: webidl-conversions: 3.0.1 dev: false + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-builtin-type@1.1.3: + resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} + engines: {node: '>= 0.4'} + dependencies: + function.prototype.name: 1.1.6 + has-tostringtag: 1.0.2 + is-async-function: 2.0.0 + is-date-object: 1.0.5 + is-finalizationregistry: 1.0.2 + is-generator-function: 1.0.10 + is-regex: 1.1.4 + is-weakref: 1.0.2 + isarray: 2.0.5 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.2 + which-typed-array: 1.1.15 + dev: true + + /which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 + dev: true + + /which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + dev: true + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} diff --git a/scripts/setup-files.js b/scripts/setup-files.js new file mode 100644 index 00000000..3a6c56cc --- /dev/null +++ b/scripts/setup-files.js @@ -0,0 +1,20 @@ +/* eslint-disable no-console */ +const fs = require('fs'); + +const oldPaths = ['.env.template', 'src/util/blacklist/_blacklist.json.template']; +oldPaths.forEach((path) => { + if (!fs.existsSync(path)) { + console.warn( + `File ${path} does not exist. If you have NOT run this command before, you may need to repair your installation.` + ); + + return; + } + + const newPath = path.substring(0, path.indexOf('.template')); + if (fs.existsSync(newPath)) { + console.warn(`File '${newPath}' already exists.`); + } else { + fs.copyFileSync(newPath, path, fs.constants.COPYFILE_EXCL); + } +}); diff --git a/setupFiles.js b/setupFiles.js deleted file mode 100644 index 00c21bf8..00000000 --- a/setupFiles.js +++ /dev/null @@ -1,17 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-var-requires -const fs = require("fs"); - -const files = [".env", "src/util/blacklist/_blacklist.json"]; -for (const newPath of files) { - const oldPath = `${newPath}.template`; - - if (!fs.existsSync(oldPath)) { - console.warn( - `Path ${oldPath} does not exist. If you have NOT run this command before, you may need to repair your installation.`, - ); - } else if (fs.existsSync(newPath)) { - console.warn(`Path ${newPath} already exists.`); - } else { - fs.copyFileSync(oldPath, newPath); - } -} diff --git a/src/@types/BlacklistEntry.d.ts b/src/@types/BlacklistEntry.d.ts index 09e96d1e..903d981b 100644 --- a/src/@types/BlacklistEntry.d.ts +++ b/src/@types/BlacklistEntry.d.ts @@ -1,7 +1,7 @@ declare interface BlacklistEntry { - name: string; - uuid: string; - endDate: string; - reason: string; - messageId: string; + name: string; + uuid: string; + endDate: string; + reason: string; + messageId: string; } diff --git a/src/@types/Command.d.ts b/src/@types/Command.d.ts index bfaae1a3..4a61f96c 100644 --- a/src/@types/Command.d.ts +++ b/src/@types/Command.d.ts @@ -1,14 +1,12 @@ declare interface Command { - data: import("discord.js").ChatInputApplicationCommandData; - run: ExecuteCommand; - staffOnly?: boolean; + data: import('discord.js').ChatInputApplicationCommandData; + run: ExecuteCommand; + staffOnly?: boolean; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any type ExecuteCommand = ( - bot: import("@classes/Bot").default, - interaction: import("discord.js").ChatInputCommandInteraction, - // TODO: use never[] below and force implementations to define types explicitly (use spread?) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - args: any[], + bot: import('@classes/Bot').default, + interaction: import('discord.js').ChatInputCommandInteraction, + // TODO: use never[] below and force implementations to define types explicitly (use spread?) + args: any[] ) => Promise; diff --git a/src/@types/Event.d.ts b/src/@types/Event.d.ts index 25376e9e..9e52eb2e 100644 --- a/src/@types/Event.d.ts +++ b/src/@types/Event.d.ts @@ -1,11 +1,10 @@ declare interface Event { - name: - | keyof typeof import("@util/regex").default - | keyof import("mineflayer").BotEvents - | keyof import("discord.js").ClientEvents; - runOnce: boolean; - run: Execute; + name: + | keyof typeof import('@util/regex').default + | keyof import('mineflayer').BotEvents + | keyof import('discord.js').ClientEvents; + runOnce: boolean; + run: Execute; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type Execute = (bot: import("@classes/Bot").default, ...params: any[]) => Promise; +type Execute = (bot: import('@classes/Bot').default, ...params: any[]) => Promise; diff --git a/src/@types/environment.d.ts b/src/@types/environment.d.ts index 4ebe923f..b4b1e396 100644 --- a/src/@types/environment.d.ts +++ b/src/@types/environment.d.ts @@ -1,36 +1,36 @@ declare global { - namespace NodeJS { - interface ProcessEnv { - MINECRAFT_EMAIL: string; - MINECRAFT_PASSWORD: string; + namespace NodeJS { + interface ProcessEnv { + MINECRAFT_EMAIL: string; + MINECRAFT_PASSWORD: string; - HYPIXEL_API_KEY: string; + HYPIXEL_API_KEY: string; - MINECRAFT_CHAT_SEPARATOR: string; + MINECRAFT_CHAT_SEPARATOR: string; - USE_FIRST_WORD_OF_AUTHOR_NAME: "true" | "false"; + USE_FIRST_WORD_OF_AUTHOR_NAME: 'true' | 'false'; - MINIMUM_NETWORK_LEVEL: string; + MINIMUM_NETWORK_LEVEL: string; - REMINDER_ENABLED: "true" | "false"; - REMINDER_MESSAGE: string; - REMINDER_FREQUENCY: string; + REMINDER_ENABLED: 'true' | 'false'; + REMINDER_MESSAGE: string; + REMINDER_FREQUENCY: string; - DISCORD_TOKEN: string; - DISCORD_IGNORE_PREFIX: string; - DISCORD_INVITE_LINK: `discord.gg/${string}`; - USE_RANK_EMOJIS: "true" | "false"; + DISCORD_TOKEN: string; + DISCORD_IGNORE_PREFIX: string; + DISCORD_INVITE_LINK: `discord.gg/${string}`; + USE_RANK_EMOJIS: 'true' | 'false'; - DISCORD_SERVER_ID: string; - MEMBER_CHANNEL_ID: string; - OFFICER_CHANNEL_ID: string; - BLACKLIST_CHANNEL_ID: string; - ERROR_CHANNEL_ID: string; + DISCORD_SERVER_ID: string; + MEMBER_CHANNEL_ID: string; + OFFICER_CHANNEL_ID: string; + BLACKLIST_CHANNEL_ID: string; + ERROR_CHANNEL_ID: string; - BOT_OWNER_ID: string; - STAFF_ROLE_ID: string; - } - } + BOT_OWNER_ID: string; + STAFF_ROLE_ID: string; + } + } } export {}; diff --git a/src/classes/Bot.ts b/src/classes/Bot.ts index 7e500cf4..7f2a9b9f 100644 --- a/src/classes/Bot.ts +++ b/src/classes/Bot.ts @@ -1,184 +1,204 @@ -import { ActivityType, ColorResolvable, EmbedBuilder, IntentsBitField, TextChannel } from "discord.js"; -import { BotEvents, createBot } from "mineflayer"; -import Discord from "./Client"; -import EventEmitter from "events"; -import consola from "consola"; -import isObjKey from "@util/isObjKey"; -import logError from "@util/logError"; -import path from "path"; -import recursiveWalkDir from "@util/recursiveWalkDir"; -import regex from "@util/regex"; +import { + ActivityType, + ColorResolvable, + EmbedBuilder, + IntentsBitField, + TextChannel, +} from 'discord.js'; +import { BotEvents, createBot } from 'mineflayer'; +import EventEmitter from 'events'; +import consola from 'consola'; +import isObjKey from '@util/isObjKey'; +import logError from '@util/logError'; +import path from 'path'; +import recursiveWalkDir from '@util/recursiveWalkDir'; +import regex from '@util/regex'; +import Discord from './Client'; class Bot { - public readonly logger = consola; - - public memberChannel?: TextChannel; - public officerChannel?: TextChannel; - public readonly ignorePrefix = process.env.DISCORD_IGNORE_PREFIX ?? ")"; - public readonly chatSeparator = process.env.MINECRAFT_CHAT_SEPARATOR ?? ">"; - public readonly discord = new Discord({ - allowedMentions: { parse: ["users", "roles"], repliedUser: true }, - intents: [ - IntentsBitField.Flags.Guilds, - IntentsBitField.Flags.GuildMessages, - IntentsBitField.Flags.MessageContent, - ], - }); - - public onlineCount = 0; - public totalCount = 125; - public readonly mineflayer = createBot({ - username: process.env.MINECRAFT_EMAIL, - password: process.env.MINECRAFT_PASSWORD, - host: "mc.hypixel.net", - auth: "microsoft", - version: "1.16.4", - logErrors: true, - hideErrors: true, - checkTimeoutInterval: 30000, - defaultChatPatterns: false, - }); - - constructor() { - try { - this.start(); - } catch (error) { - this.logger.error(error); - } - } - - public async sendToDiscord( - channel: "gc" | "oc", - content: string, - color: ColorResolvable = 0x2f3136, - padMessage = false, - ) { - const embed = new EmbedBuilder() - .setDescription(padMessage ? `${"-".repeat(54)}\n${content}\n${"-".repeat(54)}` : content) - .setColor(color); - - channel === "gc" - ? await this.memberChannel?.send({ embeds: [embed] }) - : await this.officerChannel?.send({ embeds: [embed] }); - } - - public sendGuildMessage(channel: "gc" | "oc", message: string) { - this.executeCommand(`/${channel} ${message}`); - } - - public executeCommand(message: string) { - this.mineflayer.chat(message); - } - - public async executeTask(task: string) { - let listener: BotEvents["message"]; - - await new Promise((resolve, reject) => { - listener = (message) => { - const str = message.toString(); - const motd = message.toMotd(); - const matches = motd.match(/^(.+)§c(.+)§r$/) ?? motd.match(/^§c(.+)$/); - - if (matches?.length && !str.toLowerCase().includes("limbo")) { - reject(str); - } - }; - - this.mineflayer.chat(task); - this.mineflayer.on("message", listener); - - setTimeout(() => { - resolve(undefined); - }, 300); - }).finally(() => { - this.mineflayer.removeListener("message", listener); - }); - } - - public sendToLimbo() { - this.executeCommand("§"); - } - - public setStatus() { - const plural = this.onlineCount - 1 !== 1; - - if (this.discord.isReady()) { - this.discord.user.setActivity(`${this.onlineCount - 1} online player${plural ? "s" : ""}`, { - type: ActivityType.Watching, - }); - } - } - - private async loadCommands(dir: string) { - const callback = async (currentDir: string, file: string) => { - if (!(file.endsWith(".ts") || file.endsWith(".js")) || file.endsWith(".d.ts")) return; - - const command = (await import(path.join(currentDir, file))).default as Command; - - if (!command.data) { - console.warn(`The command ${path.join(currentDir, file)} doesn't have a name!`); - return; - } - - if (!command.run) { - console.warn(`The command ${command.data.name} doesn't have an executable function!`); - return; - } - - this.discord.commands.set(command.data.name, command); - }; - - await recursiveWalkDir(path.join(__dirname, dir), callback, "Error while loading commands: "); - } - - private async loadEvents(dir: string, emitter: EventEmitter) { - const callback = async (currentDir: string, file: string) => { - if (!(file.endsWith(".ts") || file.endsWith(".js")) || file.endsWith(".d.ts")) return; - - const { name, runOnce, run } = (await import(path.join(currentDir, file))).default as Event; - - if (!name) { - console.warn(`The event ${path.join(currentDir, file)} doesn't have a name!`); - return; - } - - if (!run) { - console.warn(`The event ${name} doesn't have an executable function!`); - return; - } - - if (isObjKey(name, regex)) { - this.mineflayer.addChatPattern(name.replace("chat:", ""), regex[name], { - repeat: true, - parse: true, - }); - } - - if (runOnce) { - emitter.once(name, run.bind(null, this)); - return; - } - - emitter.on(name, (...args) => { - run(this, ...args.flat(2)); - }); - }; - - await recursiveWalkDir(path.join(__dirname, dir), callback, "Error while loading events: "); - } - - private async start() { - this.mineflayer.setMaxListeners(20); - await Promise.all([ - this.loadCommands("../commands"), - this.loadEvents("../events/discord", this.discord), - this.loadEvents("../events/mineflayer", this.mineflayer), - ]); - - await this.discord.login(process.env.DISCORD_TOKEN); - } + public readonly logger = consola; + + public memberChannel?: TextChannel; + public officerChannel?: TextChannel; + public readonly ignorePrefix = process.env.DISCORD_IGNORE_PREFIX ?? ')'; + public readonly chatSeparator = process.env.MINECRAFT_CHAT_SEPARATOR ?? '>'; + public readonly discord = new Discord({ + allowedMentions: { parse: ['users', 'roles'], repliedUser: true }, + intents: [ + IntentsBitField.Flags.Guilds, + IntentsBitField.Flags.GuildMessages, + IntentsBitField.Flags.MessageContent, + ], + }); + + public onlineCount = 0; + public totalCount = 125; + public readonly mineflayer = createBot({ + username: process.env.MINECRAFT_EMAIL, + password: process.env.MINECRAFT_PASSWORD, + host: 'mc.hypixel.net', + auth: 'microsoft', + version: '1.16.4', + logErrors: true, + hideErrors: true, + checkTimeoutInterval: 30000, + defaultChatPatterns: false, + }); + + constructor() { + try { + this.start(); + } catch (error) { + this.logger.error(error); + } + } + + public async sendToDiscord( + channel: 'gc' | 'oc', + content: string, + color: ColorResolvable = 0x36393f, + padMessage = false + ) { + const embed = new EmbedBuilder() + .setDescription( + padMessage ? `${'-'.repeat(54)}\n${content}\n${'-'.repeat(54)}` : content + ) + .setColor(color); + + if (channel === 'gc') { + await this.memberChannel?.send({ embeds: [embed] }); + } else { + await this.officerChannel?.send({ embeds: [embed] }); + } + } + + public sendGuildMessage(channel: 'gc' | 'oc', message: string) { + this.executeCommand(`/${channel} ${message}`); + } + + public executeCommand(message: string) { + this.mineflayer.chat(message); + } + + public async executeTask(task: string) { + let listener: BotEvents['message']; + + await new Promise((resolve, reject) => { + listener = (message) => { + const str = message.toString(); + const motd = message.toMotd(); + const matches = motd.match(/^(.+)§c(.+)§r$/) ?? motd.match(/^§c(.+)$/); + + if (matches?.length && !str.toLowerCase().includes('limbo')) { + reject(str); + } + }; + + this.mineflayer.chat(task); + this.mineflayer.on('message', listener); + + setTimeout(() => { + resolve(undefined); + }, 300); + }).finally(() => { + this.mineflayer.removeListener('message', listener); + }); + } + + public sendToLimbo() { + this.executeCommand('§'); + } + + public setStatus() { + const plural = this.onlineCount - 1 !== 1; + + if (this.discord.isReady()) { + this.discord.user.setActivity( + `${this.onlineCount - 1} online player${plural ? 's' : ''}`, + { + type: ActivityType.Watching, + } + ); + } + } + + private async loadCommands(dir: string) { + const callback = async (currentDir: string, file: string) => { + if (!(file.endsWith('.ts') || file.endsWith('.js')) || file.endsWith('.d.ts')) return; + + const command = (await import(path.join(currentDir, file))).default as Command; + + if (!command.data) { + this.logger.warn(`The command ${path.join(currentDir, file)} doesn't have a name!`); + return; + } + + if (!command.run) { + this.logger.warn( + `The command ${command.data.name} doesn't have an executable function!` + ); + return; + } + + this.discord.commands.set(command.data.name, command); + }; + + await recursiveWalkDir( + path.join(__dirname, dir), + callback, + 'Error while loading commands:' + ); + } + + private async loadEvents(dir: string, emitter: EventEmitter) { + const callback = async (currentDir: string, file: string) => { + if (!(file.endsWith('.ts') || file.endsWith('.js')) || file.endsWith('.d.ts')) return; + + const { name, runOnce, run } = (await import(path.join(currentDir, file))) + .default as Event; + + if (!name) { + this.logger.warn(`The event ${path.join(currentDir, file)} doesn't have a name!`); + return; + } + + if (!run) { + this.logger.warn(`The event ${name} doesn't have an executable function!`); + return; + } + + if (isObjKey(name, regex)) { + this.mineflayer.addChatPattern(name.replace('chat:', ''), regex[name], { + repeat: true, + parse: true, + }); + } + + if (runOnce) { + emitter.once(name, run.bind(null, this)); + return; + } + + emitter.on(name, (...args) => { + run(this, ...args.flat(2)); + }); + }; + + await recursiveWalkDir(path.join(__dirname, dir), callback, 'Error while loading events:'); + } + + private async start() { + this.mineflayer.setMaxListeners(20); + await Promise.all([ + this.loadCommands('../commands'), + this.loadEvents('../events/discord', this.discord), + this.loadEvents('../events/mineflayer', this.mineflayer), + ]); + + await this.discord.login(process.env.DISCORD_TOKEN); + } } -process.on("uncaughtException", logError).on("unhandledRejection", logError); +process.on('uncaughtException', logError).on('unhandledRejection', logError); export default Bot; diff --git a/src/classes/Client.ts b/src/classes/Client.ts index 667c1867..5d396c19 100644 --- a/src/classes/Client.ts +++ b/src/classes/Client.ts @@ -1,9 +1,5 @@ -import { Client, ClientOptions, Collection } from "discord.js"; +import { Client, Collection } from 'discord.js'; export default class Discord extends Client { - commands: Collection = new Collection(); - - constructor(options: ClientOptions) { - super(options); - } + public readonly commands: Collection = new Collection(); } diff --git a/src/commands/blacklist.ts b/src/commands/blacklist.ts index f033b67c..6a0ac062 100644 --- a/src/commands/blacklist.ts +++ b/src/commands/blacklist.ts @@ -1,127 +1,134 @@ -import { ApplicationCommandOptionType, EmbedBuilder, TextChannel } from "discord.js"; -import _blacklist from "@util/blacklist/_blacklist.json"; -import fetchErrorEmbed from "@util/requests/fetchErrorEmbed"; -import fetchMojangProfile from "@util/requests/fetchMojangProfile"; -import isFetchError from "@util/requests/isFetchError"; -import writeToJsonFile from "@util/writeToJsonFile"; +import { ApplicationCommandOptionType, EmbedBuilder, TextChannel } from 'discord.js'; +import _blacklist from '@util/blacklist/_blacklist.json'; +import fetchErrorEmbed from '@util/requests/fetchErrorEmbed'; +import fetchMojangProfile from '@util/requests/fetchMojangProfile'; +import isFetchError from '@util/requests/isFetchError'; +import writeToJsonFile from '@util/writeToJsonFile'; export default { - data: { - name: "blacklist", - description: "Add or remove a user from the blacklist!", - options: [ - { - name: "add", - description: "Add a user to the blacklist", - type: ApplicationCommandOptionType.Subcommand, - options: [ - { - name: "user", - description: "The user to add to the blacklist", - type: ApplicationCommandOptionType.String, - required: true, - }, - { - name: "end", - description: "The end date of the blacklist", - type: ApplicationCommandOptionType.String, - required: true, - }, - { - name: "reason", - description: "The reason for the blacklist", - type: ApplicationCommandOptionType.String, - required: true, - }, - ], - }, - { - name: "remove", - description: "Removes a user from the blacklist", - type: ApplicationCommandOptionType.Subcommand, - options: [ - { - name: "user", - description: "The user to remove from the blacklist", - type: ApplicationCommandOptionType.String, - required: true, - }, - ], - }, - ], - }, - run: async (bot, interaction, args) => { - const type = interaction.options.getSubcommand() as "add" | "remove"; - const mojangProfile = await fetchMojangProfile(args[0]); - const blacklist = _blacklist as BlacklistEntry[]; + data: { + name: 'blacklist', + description: 'Add or remove a user from the blacklist!', + options: [ + { + name: 'add', + description: 'Add a user to the blacklist', + type: ApplicationCommandOptionType.Subcommand, + options: [ + { + name: 'user', + description: 'The user to add to the blacklist', + type: ApplicationCommandOptionType.String, + required: true, + }, + { + name: 'end', + description: 'The end date of the blacklist', + type: ApplicationCommandOptionType.String, + required: true, + }, + { + name: 'reason', + description: 'The reason for the blacklist', + type: ApplicationCommandOptionType.String, + required: true, + }, + ], + }, + { + name: 'remove', + description: 'Removes a user from the blacklist', + type: ApplicationCommandOptionType.Subcommand, + options: [ + { + name: 'user', + description: 'The user to remove from the blacklist', + type: ApplicationCommandOptionType.String, + required: true, + }, + ], + }, + ], + }, + run: async (bot, interaction, args) => { + const type = interaction.options.getSubcommand() as 'add' | 'remove'; + const mojangProfile = await fetchMojangProfile(args[0]); + const blacklist = _blacklist as BlacklistEntry[]; - if (isFetchError(mojangProfile)) { - const embed = fetchErrorEmbed(mojangProfile); - await interaction.reply({ embeds: [embed] }); - return; - } + if (isFetchError(mojangProfile)) { + const embed = fetchErrorEmbed(mojangProfile); + await interaction.reply({ embeds: [embed] }); + return; + } - const isOnBlacklist = blacklist.some((user) => user.uuid === mojangProfile.id); - if ((type === "add" && isOnBlacklist) || (type === "remove" && !isOnBlacklist)) { - const embed = new EmbedBuilder() - .setColor("Red") - .setTitle("Error") - .setDescription(`That user is ${type === "add" ? "already" : "not"} on the blacklist!`); + const isOnBlacklist = blacklist.some((user) => user.uuid === mojangProfile.id); + if ((type === 'add' && isOnBlacklist) || (type === 'remove' && !isOnBlacklist)) { + const embed = new EmbedBuilder() + .setColor('Red') + .setTitle('Error') + .setDescription( + `That user is ${type === 'add' ? 'already' : 'not'} on the blacklist!` + ); - await interaction.reply({ embeds: [embed] }); - return; - } + await interaction.reply({ embeds: [embed] }); + return; + } - if (type === "add") { - const endDate = args[1]; - const reason = args[2]; - const embed = new EmbedBuilder() - .setAuthor({ - name: "Blacklist", - iconURL: "https://media.discordapp.net/attachments/522930879413092388/849317688517853294/misc.png", - }) - .setColor("Red") - .setFooter({ text: `UUID: ${mojangProfile.id}` }) - .setThumbnail(`https://visage.surgeplay.com/full/${mojangProfile.id}.png`) - .setTimestamp() - .setTitle(mojangProfile.name) - .setURL(`http://plancke.io/hypixel/player/stats/${mojangProfile.id}`) - .addFields([ - { name: "End:", value: endDate }, - { name: "Reason:", value: reason }, - ]); + if (type === 'add') { + const endDate = args[1]; + const reason = args[2]; + const embed = new EmbedBuilder() + .setAuthor({ + name: 'Blacklist', + iconURL: + 'https://media.discordapp.net/attachments/522930879413092388/849317688517853294/misc.png', + }) + .setColor('Red') + .setFooter({ text: `UUID: ${mojangProfile.id}` }) + .setThumbnail(`https://visage.surgeplay.com/full/${mojangProfile.id}.png`) + .setTimestamp() + .setTitle(mojangProfile.name) + .setURL(`http://plancke.io/hypixel/player/stats/${mojangProfile.id}`) + .addFields([ + { name: 'End:', value: endDate }, + { name: 'Reason:', value: reason }, + ]); - const blacklistMessage = await ( - (await bot.discord.channels.fetch(process.env.BLACKLIST_CHANNEL_ID)) as TextChannel - ).send({ - embeds: [embed], - }); + const blacklistMessage = await ( + (await bot.discord.channels.fetch(process.env.BLACKLIST_CHANNEL_ID)) as TextChannel + ).send({ + embeds: [embed], + }); - blacklist.push({ - name: mojangProfile.name, - uuid: mojangProfile.id, - endDate: endDate, - reason: reason, - messageId: blacklistMessage.id, - }); - } else { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const blacklistEntry = blacklist.find((user) => user.uuid === mojangProfile.id)!; - blacklist.splice(blacklist.indexOf(blacklistEntry)); + blacklist.push({ + name: mojangProfile.name, + uuid: mojangProfile.id, + endDate, + reason, + messageId: blacklistMessage.id, + }); + } else { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const blacklistEntry = blacklist.find((user) => user.uuid === mojangProfile.id)!; + blacklist.splice(blacklist.indexOf(blacklistEntry)); - const message = await ( - bot.discord.channels.cache.get(process.env.BLACKLIST_CHANNEL_ID) as TextChannel - ).messages.fetch(blacklistEntry.messageId); - await message.delete(); - } + const message = await ( + bot.discord.channels.cache.get(process.env.BLACKLIST_CHANNEL_ID) as TextChannel + ).messages.fetch(blacklistEntry.messageId); + await message.delete(); + } - const successEmbed = new EmbedBuilder() - .setColor(type === "add" ? "Red" : "Green") - .setThumbnail(`https://crafatar.com/avatars/${mojangProfile.id}`) - .setTitle("Completed!") - .setDescription(`${mojangProfile.name} was ${type === "add" ? "added to" : "removed from"} the blacklist!`); + const successEmbed = new EmbedBuilder() + .setColor(type === 'add' ? 'Red' : 'Green') + .setThumbnail(`https://crafatar.com/avatars/${mojangProfile.id}`) + .setTitle('Completed!') + .setDescription( + `${mojangProfile.name} was ${ + type === 'add' ? 'added to' : 'removed from' + } the blacklist!` + ); - writeToJsonFile("./s@util/_blacklist.json", blacklist, interaction, successEmbed); - }, - staffOnly: true, + writeToJsonFile('./s@util/_blacklist.json', blacklist, interaction, successEmbed); + }, + staffOnly: true, } as Command; diff --git a/src/commands/command.ts b/src/commands/command.ts index 3d3e8717..b92304e5 100644 --- a/src/commands/command.ts +++ b/src/commands/command.ts @@ -1,37 +1,37 @@ -import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; +import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; export default { - data: { - name: "command", - description: "Execute any command in game!", - options: [ - { - name: "command", - description: "What command would you like to execute?", - type: ApplicationCommandOptionType.String, - required: true, - }, - ], - }, - run: async (bot, interaction, args) => { - const command = (args[0] as string).startsWith("/") ? (args[0] as string) : `/${args[0]}`; - const embed = new EmbedBuilder(); + data: { + name: 'command', + description: 'Execute any command in game!', + options: [ + { + name: 'command', + description: 'What command would you like to execute?', + type: ApplicationCommandOptionType.String, + required: true, + }, + ], + }, + run: async (bot, interaction, args) => { + const command = (args[0] as string).startsWith('/') ? (args[0] as string) : `/${args[0]}`; + const embed = new EmbedBuilder(); - try { - await bot.executeTask(command); + try { + await bot.executeTask(command); - embed - .setColor("Green") - .setTitle("Completed!") - .setDescription(`The command \`${command}\` has been executed.`); - } catch (e) { - embed - .setColor("Red") - .setTitle("Error") - .setDescription(e as string); - } + embed + .setColor('Green') + .setTitle('Completed!') + .setDescription(`The command \`${command}\` has been executed.`); + } catch (e) { + embed + .setColor('Red') + .setTitle('Error') + .setDescription(e as string); + } - await interaction.reply({ embeds: [embed] }); - }, - staffOnly: true, + await interaction.reply({ embeds: [embed] }); + }, + staffOnly: true, } as Command; diff --git a/src/commands/help.ts b/src/commands/help.ts index d50f5788..ca6a0f5e 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -1,17 +1,17 @@ -import { EmbedBuilder } from "discord.js"; +import { EmbedBuilder } from 'discord.js'; export default { - data: { - name: "help", - description: "View a list of all commands!", - }, - run: async (bot, interaction) => { - const embed = new EmbedBuilder().setColor("Purple").setTitle("Commands"); + data: { + name: 'help', + description: 'View a list of all commands!', + }, + run: async (bot, interaction) => { + const embed = new EmbedBuilder().setColor('Purple').setTitle('Commands'); - bot.discord.commands.forEach((command) => { - embed.addFields({ name: command.data.name, value: command.data.description }); - }); + bot.discord.commands.forEach((command) => { + embed.addFields({ name: command.data.name, value: command.data.description }); + }); - await interaction.reply({ embeds: [embed] }); - }, + await interaction.reply({ embeds: [embed] }); + }, } as Command; diff --git a/src/commands/invite.ts b/src/commands/invite.ts index 8183803a..dc0bfe9b 100644 --- a/src/commands/invite.ts +++ b/src/commands/invite.ts @@ -1,33 +1,36 @@ -import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; +import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; export default { - data: { - name: "invite", - description: "Invite a user to the guild!", - options: [ - { - name: "user", - description: "What is the name of the user you want to invite?", - type: ApplicationCommandOptionType.String, - required: true, - }, - ], - }, - run: async (bot, interaction, args) => { - const user = args[0]; + data: { + name: 'invite', + description: 'Invite a user to the guild!', + options: [ + { + name: 'user', + description: 'What is the name of the user you want to invite?', + type: ApplicationCommandOptionType.String, + required: true, + }, + ], + }, + run: async (bot, interaction, args) => { + const user = args[0]; - const embed = new EmbedBuilder(); - try { - await bot.executeTask(`/g invite ${user}`); - embed.setTitle("Invited!").setDescription(`\`${user}\` has been invited to the guild!`).setColor("Green"); - } catch (e) { - embed - .setColor("Red") - .setTitle("Error") - .setDescription(e as string); - } + const embed = new EmbedBuilder(); + try { + await bot.executeTask(`/g invite ${user}`); + embed + .setTitle('Invited!') + .setDescription(`\`${user}\` has been invited to the guild!`) + .setColor('Green'); + } catch (e) { + embed + .setColor('Red') + .setTitle('Error') + .setDescription(e as string); + } - await interaction.reply({ embeds: [embed] }); - }, - staffOnly: true, + await interaction.reply({ embeds: [embed] }); + }, + staffOnly: true, } as Command; diff --git a/src/commands/kick.ts b/src/commands/kick.ts index 45ab38f9..fbb6fb26 100644 --- a/src/commands/kick.ts +++ b/src/commands/kick.ts @@ -1,40 +1,43 @@ -import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; +import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; export default { - data: { - name: "kick", - description: "Kick a user from the guild!", - options: [ - { - name: "user", - description: "What is the name of the user you want to kick?", - type: ApplicationCommandOptionType.String, - required: true, - }, - { - name: "reason", - description: "Why are you kicking this user?", - type: ApplicationCommandOptionType.String, - required: true, - }, - ], - }, - run: async (bot, interaction, args) => { - const user: string = args[0]; - const reason: string = args[1]; + data: { + name: 'kick', + description: 'Kick a user from the guild!', + options: [ + { + name: 'user', + description: 'What is the name of the user you want to kick?', + type: ApplicationCommandOptionType.String, + required: true, + }, + { + name: 'reason', + description: 'Why are you kicking this user?', + type: ApplicationCommandOptionType.String, + required: true, + }, + ], + }, + run: async (bot, interaction, args) => { + const user: string = args[0]; + const reason: string = args[1]; - const embed = new EmbedBuilder(); - try { - await bot.executeTask(`/g kick ${user} ${reason}`); - embed.setTitle("Kicked!").setDescription(`\`${user}\` has been kicked for \`${reason}\``).setColor("Red"); - } catch (e) { - embed - .setColor("Red") - .setTitle("Error") - .setDescription(e as string); - } + const embed = new EmbedBuilder(); + try { + await bot.executeTask(`/g kick ${user} ${reason}`); + embed + .setTitle('Kicked!') + .setDescription(`\`${user}\` has been kicked for \`${reason}\``) + .setColor('Red'); + } catch (e) { + embed + .setColor('Red') + .setTitle('Error') + .setDescription(e as string); + } - await interaction.reply({ embeds: [embed] }); - }, - staffOnly: true, + await interaction.reply({ embeds: [embed] }); + }, + staffOnly: true, } as Command; diff --git a/src/commands/promoteDemote.ts b/src/commands/promoteDemote.ts index dfaa5875..805ae374 100644 --- a/src/commands/promoteDemote.ts +++ b/src/commands/promoteDemote.ts @@ -1,56 +1,56 @@ -import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; -import capitaliseString from "@util/capitaliseString"; +import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; +import capitaliseString from '@util/capitaliseString'; export default { - data: { - name: "promotedemote", - description: "Promote or demote a user in the guild!", - options: [ - { - name: "type", - description: "Would you like to promote or demote the user?", - type: ApplicationCommandOptionType.String, - choices: [ - { - name: "promote", - value: "promote", - }, - { - name: "demote", - value: "demote", - }, - ], - required: true, - }, - { - name: "user", - description: "What is the name of the user you want to promote/demote?", - type: ApplicationCommandOptionType.String, - required: true, - }, - ], - }, - run: async (bot, interaction, args) => { - const type: string = args[0] as "promote" | "demote"; - const user: string = args[1]; + data: { + name: 'promotedemote', + description: 'Promote or demote a user in the guild!', + options: [ + { + name: 'type', + description: 'Would you like to promote or demote the user?', + type: ApplicationCommandOptionType.String, + choices: [ + { + name: 'promote', + value: 'promote', + }, + { + name: 'demote', + value: 'demote', + }, + ], + required: true, + }, + { + name: 'user', + description: 'What is the name of the user you want to promote/demote?', + type: ApplicationCommandOptionType.String, + required: true, + }, + ], + }, + run: async (bot, interaction, args) => { + const type: string = args[0] as 'promote' | 'demote'; + const user: string = args[1]; - const embed = new EmbedBuilder(); - try { - await bot.executeTask(`/g ${type} ${user}`); - embed - .setColor(type === "promote" ? "Green" : "Red") - .setTitle(capitaliseString(`${type}d!`)) - .setDescription(`${user} has been ${type}d!`); - } catch (e) { - embed - .setColor("Red") - .setTitle("Error") - .setDescription(e as string); - } + const embed = new EmbedBuilder(); + try { + await bot.executeTask(`/g ${type} ${user}`); + embed + .setColor(type === 'promote' ? 'Green' : 'Red') + .setTitle(capitaliseString(`${type}d!`)) + .setDescription(`${user} has been ${type}d!`); + } catch (e) { + embed + .setColor('Red') + .setTitle('Error') + .setDescription(e as string); + } - await interaction.reply({ - embeds: [embed], - }); - }, - staffOnly: true, + await interaction.reply({ + embeds: [embed], + }); + }, + staffOnly: true, } as Command; diff --git a/src/commands/reboot.ts b/src/commands/reboot.ts index ddc7ed21..94c47b7f 100644 --- a/src/commands/reboot.ts +++ b/src/commands/reboot.ts @@ -1,24 +1,27 @@ -import { EmbedBuilder } from "discord.js"; +import { EmbedBuilder } from 'discord.js'; export default { - data: { - name: "reboot", - description: "Reboot the bot! (Only works if your host automatically restarts the application)", - }, - run: async (bot, interaction) => { - const embed = new EmbedBuilder() - .setColor("Green") - .setTitle("Rebooting") - .setDescription("Rebooting in 15 seconds..."); + data: { + name: 'reboot', + description: + 'Reboot the bot! (Only works if your host automatically restarts the application)', + }, + run: async (bot, interaction) => { + const embed = new EmbedBuilder() + .setColor('Green') + .setTitle('Rebooting') + .setDescription('Rebooting in 15 seconds...'); - bot.sendGuildMessage("gc", "Rebooting in 15 seconds..."); - bot.logger.info(`Rebooting due to ${interaction.member?.user.username} running the reboot command.`); + bot.sendGuildMessage('gc', 'Rebooting in 15 seconds...'); + bot.logger.info( + `Rebooting due to ${interaction.member?.user.username} running the reboot command.` + ); - setTimeout(() => { - process.exit(); - }, 15_000); + setTimeout(() => { + process.exit(); + }, 15_000); - await interaction.reply({ embeds: [embed] }); - }, - staffOnly: true, + await interaction.reply({ embeds: [embed] }); + }, + staffOnly: true, } as Command; diff --git a/src/commands/slowmode.ts b/src/commands/slowmode.ts index 6adf5d3c..1f6d23ae 100644 --- a/src/commands/slowmode.ts +++ b/src/commands/slowmode.ts @@ -1,34 +1,32 @@ -import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; +import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; const choices = [0, 5, 10]; export default { - data: { - name: "slowmode", - description: "Enable slowmode for the member channel!", - options: [ - { - name: "time", - description: "What should the interval be between sending messages?", - type: ApplicationCommandOptionType.Integer, - choices: choices.map((value) => { - return { name: value.toString(), value: value }; - }), - required: true, - }, - ], - }, - run: async (bot, interaction, args) => { - const time = (args[0] as number) || 0; + data: { + name: 'slowmode', + description: 'Enable slowmode for the member channel!', + options: [ + { + name: 'time', + description: 'What should the interval be between sending messages?', + type: ApplicationCommandOptionType.Integer, + choices: choices.map((value) => ({ name: value.toString(), value })), + required: true, + }, + ], + }, + run: async (bot, interaction, args) => { + const time = (args[0] as number) || 0; - bot.memberChannel?.setRateLimitPerUser(time); + bot.memberChannel?.setRateLimitPerUser(time); - const embed = new EmbedBuilder() - .setColor("Green") - .setTitle("Slowmode set!") - .setDescription(`Slowmode has been set to ${time}s`); + const embed = new EmbedBuilder() + .setColor('Green') + .setTitle('Slowmode set!') + .setDescription(`Slowmode has been set to ${time}s`); - await interaction.reply({ embeds: [embed] }); - }, - staffOnly: true, + await interaction.reply({ embeds: [embed] }); + }, + staffOnly: true, } as Command; diff --git a/src/commands/toggleMute.ts b/src/commands/toggleMute.ts index 28218198..1f966f9b 100644 --- a/src/commands/toggleMute.ts +++ b/src/commands/toggleMute.ts @@ -1,67 +1,69 @@ -import { ApplicationCommandOptionType, EmbedBuilder } from "discord.js"; -import capitaliseString from "@util/capitaliseString"; +import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; +import capitaliseString from '@util/capitaliseString'; export default { - data: { - name: "togglemute", - description: "Mute or unmute a user in the guild!", - options: [ - { - name: "mute", - description: "Mute a user in the guild!", - type: ApplicationCommandOptionType.Subcommand, - options: [ - { - name: "user", - description: "What is the name of the user you want to mute?", - type: ApplicationCommandOptionType.String, - required: true, - }, - { - name: "duration", - description: "How long do you want to mute this user for?", - type: ApplicationCommandOptionType.String, - required: true, - }, - ], - }, - { - name: "unmute", - description: "Unmute a user in the guild!", - type: ApplicationCommandOptionType.Subcommand, - options: [ - { - name: "user", - description: "What is the name of the user you want to unmute?", - type: ApplicationCommandOptionType.String, - required: true, - }, - ], - }, - ], - }, - run: async (bot, interaction, args) => { - const type = interaction.options.getSubcommand() as "mute" | "unmute"; - const user: string = args[0]; - const duration: string = args[1]; + data: { + name: 'togglemute', + description: 'Mute or unmute a user in the guild!', + options: [ + { + name: 'mute', + description: 'Mute a user in the guild!', + type: ApplicationCommandOptionType.Subcommand, + options: [ + { + name: 'user', + description: 'What is the name of the user you want to mute?', + type: ApplicationCommandOptionType.String, + required: true, + }, + { + name: 'duration', + description: 'How long do you want to mute this user for?', + type: ApplicationCommandOptionType.String, + required: true, + }, + ], + }, + { + name: 'unmute', + description: 'Unmute a user in the guild!', + type: ApplicationCommandOptionType.Subcommand, + options: [ + { + name: 'user', + description: 'What is the name of the user you want to unmute?', + type: ApplicationCommandOptionType.String, + required: true, + }, + ], + }, + ], + }, + run: async (bot, interaction, args) => { + const type = interaction.options.getSubcommand() as 'mute' | 'unmute'; + const user: string = args[0]; + const duration: string = args[1]; - const embed = new EmbedBuilder(); - try { - await bot.executeTask(`/g ${type} ${user} ${duration}`); - embed - .setTitle(capitaliseString(`${type}d!`)) - .setDescription(`${user} was ${type}d` + (type === "mute" ? ` for ${duration}!` : "!")) - .setColor(type === "mute" ? "Red" : "Green"); - } catch (e) { - embed - .setColor("Red") - .setTitle("Error") - .setDescription(e as string); - } + const embed = new EmbedBuilder(); + try { + await bot.executeTask(`/g ${type} ${user} ${duration}`); + embed + .setTitle(capitaliseString(`${type}d!`)) + .setDescription( + `${user} was ${type}d${type === 'mute' ? ` for ${duration}!` : '!'}` + ) + .setColor(type === 'mute' ? 'Red' : 'Green'); + } catch (e) { + embed + .setColor('Red') + .setTitle('Error') + .setDescription(e as string); + } - await interaction.reply({ - embeds: [embed], - }); - }, - staffOnly: true, + await interaction.reply({ + embeds: [embed], + }); + }, + staffOnly: true, } as Command; diff --git a/src/events/discord/interactionCreate.ts b/src/events/discord/interactionCreate.ts index aa78613e..2e13b9b4 100644 --- a/src/events/discord/interactionCreate.ts +++ b/src/events/discord/interactionCreate.ts @@ -1,53 +1,55 @@ -import { ApplicationCommandOptionType, EmbedBuilder, GuildMember, Interaction } from "discord.js"; +import { ApplicationCommandOptionType, EmbedBuilder, GuildMember, Interaction } from 'discord.js'; export default { - name: "interactionCreate", - runOnce: false, - run: async (bot, interaction: Interaction) => { - if (!interaction.isChatInputCommand()) return; - - const command = bot.discord.commands.get(interaction.commandName); - - if (!command) { - bot.logger.error(`Unknown slash command: ${interaction.commandName}`); - return; - } - - const member = interaction.member as GuildMember; - if ( - command.staffOnly && - !member.roles.cache.has(process.env.STAFF_ROLE_ID) && - member.id !== process.env.BOT_OWNER_ID - ) { - const embed = new EmbedBuilder() - .setColor("Red") - .setTitle("Error") - .setDescription("You do not have permission to run that command!"); - - await interaction.reply({ embeds: [embed] }); - return; - } - - const args = []; - for (const option of interaction.options.data) { - if (option.value) args.push(option.value); - - if (option.type === ApplicationCommandOptionType.Subcommand && option.options) { - for (const v of option.options) { - if (v.value) args.push(v.value); - } - } - } - - try { - command.run(bot, interaction, args); - } catch (e: unknown) { - await interaction.reply({ - content: "There was an error while executing this command!", - ephemeral: true, - }); - - bot.logger.error(`An error occured in ${interaction.commandName}: ${(e as Error).message}`); - } - }, + name: 'interactionCreate', + runOnce: false, + run: async (bot, interaction: Interaction) => { + if (!interaction.isChatInputCommand()) return; + + const command = bot.discord.commands.get(interaction.commandName); + + if (!command) { + bot.logger.error(`Unknown slash command: ${interaction.commandName}`); + return; + } + + const member = interaction.member as GuildMember; + if ( + command.staffOnly && + !member.roles.cache.has(process.env.STAFF_ROLE_ID) && + member.id !== process.env.BOT_OWNER_ID + ) { + const embed = new EmbedBuilder() + .setColor('Red') + .setTitle('Error') + .setDescription('You do not have permission to run that command!'); + + await interaction.reply({ embeds: [embed] }); + return; + } + + const args: any[] = []; + interaction.options.data.forEach((option) => { + if (option.value) args.push(option.value); + + if (option.type === ApplicationCommandOptionType.Subcommand && option.options) { + option.options.forEach((subOption) => { + if (subOption.value) args.push(subOption.value); + }); + } + }); + + try { + command.run(bot, interaction, args); + } catch (e: unknown) { + await interaction.reply({ + content: 'There was an error while executing this command!', + ephemeral: true, + }); + + bot.logger.error( + `An error occured in ${interaction.commandName}: ${(e as Error).message}` + ); + } + }, } as Event; diff --git a/src/events/discord/message.ts b/src/events/discord/message.ts index c85b8385..54d49909 100644 --- a/src/events/discord/message.ts +++ b/src/events/discord/message.ts @@ -1,57 +1,71 @@ -import { Message } from "discord.js"; -import { DataSet, RegExpMatcher, englishDataset, englishRecommendedTransformers } from "obscenity"; -import emojis from "@util/emojis"; +import { Message } from 'discord.js'; +import { DataSet, RegExpMatcher, englishDataset, englishRecommendedTransformers } from 'obscenity'; +import emojis from '@util/emojis'; -const whitelist = ["ass", "bitch", "cock", "dick", "fuck"]; +const whitelist = ['ass', 'bitch', 'cock', 'dick', 'fuck']; const dataset = new DataSet<{ originalWord: string }>() - .addAll(englishDataset) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - .removePhrasesIf((phrase) => whitelist.includes(phrase.metadata!.originalWord)); + .addAll(englishDataset) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + .removePhrasesIf((phrase) => whitelist.includes(phrase.metadata!.originalWord)); -const profanityMatcher = new RegExpMatcher({ ...dataset.build(), ...englishRecommendedTransformers }); +const profanityMatcher = new RegExpMatcher({ + ...dataset.build(), + ...englishRecommendedTransformers, +}); export default { - name: "messageCreate", - runOnce: false, - run: async (bot, message: Message) => { - if ( - message.content.startsWith(bot.ignorePrefix) || - message.author.bot || - message.attachments.size > 0 || - message.member === null || - (message.channel != bot.memberChannel && message.channel != bot.officerChannel) - ) - return; - - const name = - process.env.USE_FIRST_WORD_OF_AUTHOR_NAME === "true" - ? (message.member.displayName.split(" ")[0] as string) - : message.member.displayName; - - if (message.content.length > 250 - name.length) { - await message.channel.send(`Your message is too long! \`${message.content.length}/${250 - name.length}\``); - return; - } - - try { - await message.delete(); - } catch (e) { - await message.channel.send(`${emojis.warning} ${message.author.username}, could not delete message.`); - bot.logger.error(e); - } - - if (profanityMatcher.hasMatch(message.content)) { - await message.channel.send( - `${emojis.warning} ${message.author.username}, you may not use profane language!`, - ); - bot.logger.warn(`Comment blocked: ${message.content}`); - bot.sendToDiscord( - "oc", - `${emojis.warning} <@${message.author.id}> tried to say "${message.content}" but was blocked. This message was not sent to Hypixel.`, - ); - } else { - message.content = `${name} ${bot.chatSeparator} ${message.content.replace(/\r?\n|\r/g, " ")}`; - bot.sendGuildMessage(message.channel.id === bot.memberChannel?.id ? "gc" : "oc", message.content); - } - }, + name: 'messageCreate', + runOnce: false, + run: async (bot, message: Message) => { + if ( + message.content.startsWith(bot.ignorePrefix) || + message.author.bot || + message.attachments.size > 0 || + message.member === null || + (message.channel !== bot.memberChannel && message.channel !== bot.officerChannel) + ) + return; + + const name = + process.env.USE_FIRST_WORD_OF_AUTHOR_NAME === 'true' + ? (message.member.displayName.split(' ')[0] as string) + : message.member.displayName; + + if (message.content.length > 250 - name.length) { + await message.channel.send( + `Your message is too long! \`${message.content.length}/${250 - name.length}\`` + ); + return; + } + + try { + await message.delete(); + } catch (e) { + await message.channel.send( + `${emojis.warning} ${message.author.username}, could not delete message.` + ); + bot.logger.error(e); + } + + if (profanityMatcher.hasMatch(message.content)) { + await message.channel.send( + `${emojis.warning} ${message.author.username}, you may not use profane language!` + ); + bot.logger.warn(`Comment blocked: ${message.content}`); + bot.sendToDiscord( + 'oc', + `${emojis.warning} <@${message.author.id}> tried to say "${message.content}" but was blocked. This message was not sent to Hypixel.` + ); + } else { + const content = `${name} ${bot.chatSeparator} ${message.content.replace( + /\r?\n|\r/g, + ' ' + )}`; + + bot.sendGuildMessage( + message.channel.id === bot.memberChannel?.id ? 'gc' : 'oc', + content + ); + } + }, } as Event; diff --git a/src/events/discord/ready.ts b/src/events/discord/ready.ts index 6ad1dfd3..e4c070f5 100644 --- a/src/events/discord/ready.ts +++ b/src/events/discord/ready.ts @@ -1,14 +1,18 @@ -import { TextChannel } from "discord.js"; +import { TextChannel } from 'discord.js'; export default { - name: "ready", - runOnce: true, - run: async (bot) => { - bot.discord.application?.commands.set(bot.discord.commands.map((command) => command.data)); + name: 'ready', + runOnce: true, + run: async (bot) => { + bot.discord.application?.commands.set(bot.discord.commands.map((command) => command.data)); - bot.memberChannel = (await bot.discord.channels.fetch(process.env.MEMBER_CHANNEL_ID)) as TextChannel; - bot.officerChannel = (await bot.discord.channels.fetch(process.env.OFFICER_CHANNEL_ID)) as TextChannel; + bot.memberChannel = (await bot.discord.channels.fetch( + process.env.MEMBER_CHANNEL_ID + )) as TextChannel; + bot.officerChannel = (await bot.discord.channels.fetch( + process.env.OFFICER_CHANNEL_ID + )) as TextChannel; - bot.setStatus(); - }, + bot.setStatus(); + }, } as Event; diff --git a/src/events/mineflayer/chat/commentBlocked.ts b/src/events/mineflayer/chat/commentBlocked.ts index c8b2a00b..395a06f4 100644 --- a/src/events/mineflayer/chat/commentBlocked.ts +++ b/src/events/mineflayer/chat/commentBlocked.ts @@ -1,13 +1,13 @@ -import Emojis from "@util/emojis"; +import Emojis from '@util/emojis'; export default { - name: "chat:commentBlocked", - runOnce: false, - run: async (bot, comment: string, reason: string) => { - bot.logger.warn(`Comment blocked by Hypixel: ${comment} (${reason})`); - await bot.sendToDiscord( - "oc", - `${Emojis.alert} "${comment}" was blocked by Hypixel because **${reason}**. Developers will not take responsibility for banned accounts.`, - ); - }, + name: 'chat:commentBlocked', + runOnce: false, + run: async (bot, comment: string, reason: string) => { + bot.logger.warn(`Comment blocked by Hypixel: ${comment} (${reason})`); + await bot.sendToDiscord( + 'oc', + `${Emojis.alert} "${comment}" was blocked by Hypixel because **${reason}**. Developers will not take responsibility for banned accounts.` + ); + }, } as Event; diff --git a/src/events/mineflayer/chat/guildChat.ts b/src/events/mineflayer/chat/guildChat.ts index bb2455ec..04d192e6 100644 --- a/src/events/mineflayer/chat/guildChat.ts +++ b/src/events/mineflayer/chat/guildChat.ts @@ -1,21 +1,21 @@ -import { escapeMarkdown } from "discord.js"; -import getRankColor from "@util/getRankColor"; +import { escapeMarkdown } from 'discord.js'; +import getRankColor from '@util/getRankColor'; export default { - name: "chat:guildChat", - runOnce: false, - run: async ( - bot, - channel: "Guild" | "Officer", - rank: string | undefined, - playerName: string, - guildRank: string | undefined, - message: string, - ) => { - const content = ` **${rank ? rank + " " : ""}${escapeMarkdown(playerName)}${ - guildRank ? " " + guildRank : "" - }:** ${escapeMarkdown(message)}`; + name: 'chat:guildChat', + runOnce: false, + run: async ( + bot, + channel: 'Guild' | 'Officer', + rank: string | undefined, + playerName: string, + guildRank: string | undefined, + message: string + ) => { + const content = ` **${rank ? `${rank} ` : ''}${escapeMarkdown(playerName)}${ + guildRank ? ` ${guildRank}` : '' + }:** ${escapeMarkdown(message)}`; - await bot.sendToDiscord(channel === "Guild" ? "gc" : "oc", content, getRankColor(rank)); - }, + await bot.sendToDiscord(channel === 'Guild' ? 'gc' : 'oc', content, getRankColor(rank)); + }, } as Event; diff --git a/src/events/mineflayer/chat/guildLevelUp.ts b/src/events/mineflayer/chat/guildLevelUp.ts index c82d6892..4f395d81 100644 --- a/src/events/mineflayer/chat/guildLevelUp.ts +++ b/src/events/mineflayer/chat/guildLevelUp.ts @@ -1,7 +1,12 @@ export default { - name: "chat:guildLevelUp", - runOnce: false, - run: async (bot, guildLevel: number) => { - await bot.sendToDiscord("gc", `The guild has leveled up to level **${guildLevel}**!`, 0x00aa00, true); - }, + name: 'chat:guildLevelUp', + runOnce: false, + run: async (bot, guildLevel: number) => { + await bot.sendToDiscord( + 'gc', + `The guild has leveled up to level **${guildLevel}**!`, + 0x00aa00, + true + ); + }, } as Event; diff --git a/src/events/mineflayer/chat/guildMuteUnmute.ts b/src/events/mineflayer/chat/guildMuteUnmute.ts index ca98a7a5..9eaef473 100644 --- a/src/events/mineflayer/chat/guildMuteUnmute.ts +++ b/src/events/mineflayer/chat/guildMuteUnmute.ts @@ -1,24 +1,24 @@ -import Emojis from "@util/emojis"; -import { escapeMarkdown } from "discord.js"; +import Emojis from '@util/emojis'; +import { escapeMarkdown } from 'discord.js'; export default { - name: "chat:guildMuteUnmute", - runOnce: false, - run: async ( - bot, - authorRank: string | undefined, - authorName: string, - type: "muted" | "unmuted", - victimRank: string | undefined, - victimName: string, - duration: string | undefined, - ) => { - const content = `${type === "unmuted" ? Emojis.positiveGuildEvent : Emojis.negativeGuildEvent} **${ - authorRank ? authorRank + " " : "" - }${escapeMarkdown(authorName)}** has ${type} **${victimRank ? victimRank + " " : ""}${escapeMarkdown( - victimName, - )}**${duration ? ` for ${duration}` : ""}`; + name: 'chat:guildMuteUnmute', + runOnce: false, + run: async ( + bot, + authorRank: string | undefined, + authorName: string, + type: 'muted' | 'unmuted', + victimRank: string | undefined, + victimName: string, + duration: string | undefined + ) => { + const content = `${ + type === 'unmuted' ? Emojis.positiveGuildEvent : Emojis.negativeGuildEvent + } **${authorRank ? `${authorRank} ` : ''}${escapeMarkdown(authorName)}** has ${type} **${ + victimRank ? `${victimRank} ` : '' + }${escapeMarkdown(victimName)}**${duration ? ` for ${duration}` : ''}`; - await bot.sendToDiscord("gc", content, undefined, true); - }, + await bot.sendToDiscord('gc', content, undefined, true); + }, } as Event; diff --git a/src/events/mineflayer/chat/joinLeave.ts b/src/events/mineflayer/chat/joinLeave.ts index 3212415a..93c904da 100644 --- a/src/events/mineflayer/chat/joinLeave.ts +++ b/src/events/mineflayer/chat/joinLeave.ts @@ -1,16 +1,18 @@ -import Emojis from "@util/emojis"; -import { escapeMarkdown } from "discord.js"; +import Emojis from '@util/emojis'; +import { escapeMarkdown } from 'discord.js'; export default { - name: "chat:joinLeave", - runOnce: false, - run: async (bot, playerName: string, status: "joined" | "left") => { - const emoji = status === "joined" ? Emojis.join : Emojis.leave; - status === "joined" ? bot.onlineCount++ : bot.onlineCount--; + name: 'chat:joinLeave', + runOnce: false, + run: async (bot, playerName: string, status: 'joined' | 'left') => { + const emoji = status === 'joined' ? Emojis.join : Emojis.leave; + bot.onlineCount = status === 'joined' ? bot.onlineCount++ : bot.onlineCount--; - await bot.sendToDiscord( - "gc", - `${emoji} **${escapeMarkdown(playerName)}** ${status}. \`(${bot.onlineCount}/${bot.totalCount})\``, - ); - }, + await bot.sendToDiscord( + 'gc', + `${emoji} **${escapeMarkdown(playerName)}** ${status}. \`(${bot.onlineCount}/${ + bot.totalCount + })\`` + ); + }, } as Event; diff --git a/src/events/mineflayer/chat/joinLimbo.ts b/src/events/mineflayer/chat/joinLimbo.ts index 234a403f..9976bb91 100644 --- a/src/events/mineflayer/chat/joinLimbo.ts +++ b/src/events/mineflayer/chat/joinLimbo.ts @@ -1,7 +1,7 @@ export default { - name: "chat:joinLimbo", - runOnce: false, - run: (bot) => { - bot.logger.info("Bot has joined Limbo!"); - }, + name: 'chat:joinLimbo', + runOnce: false, + run: (bot) => { + bot.logger.info('Bot has joined Limbo!'); + }, } as Event; diff --git a/src/events/mineflayer/chat/joinRequest.ts b/src/events/mineflayer/chat/joinRequest.ts index 58dae6a2..c03a9ca0 100644 --- a/src/events/mineflayer/chat/joinRequest.ts +++ b/src/events/mineflayer/chat/joinRequest.ts @@ -1,30 +1,33 @@ -import fetchHypixelPlayerProfile from "@util/requests/fetchHypixelPlayerProfile"; -import fetchMojangProfile from "@util/requests/fetchMojangProfile"; -import isFetchError from "@util/requests/isFetchError"; -import isUserBlacklisted from "@util/blacklist/isUserBlacklisted"; +import fetchHypixelPlayerProfile from '@util/requests/fetchHypixelPlayerProfile'; +import fetchMojangProfile from '@util/requests/fetchMojangProfile'; +import isFetchError from '@util/requests/isFetchError'; +import isUserBlacklisted from '@util/blacklist/isUserBlacklisted'; export default { - name: "chat:joinRequest", - runOnce: false, - run: async (bot, playerName: string) => { - const mojangProfile = await fetchMojangProfile(playerName); - if (isFetchError(mojangProfile)) return; + name: 'chat:joinRequest', + runOnce: false, + run: async (bot, playerName: string) => { + const mojangProfile = await fetchMojangProfile(playerName); + if (isFetchError(mojangProfile)) return; - const playerProfile = await fetchHypixelPlayerProfile(playerName); - if (!isFetchError(playerProfile)) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const networkLevel = Math.sqrt(2 * playerProfile.networkExp! + 30625) / 50 - 2.5; + const playerProfile = await fetchHypixelPlayerProfile(playerName); + if (!isFetchError(playerProfile)) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const networkLevel = Math.sqrt(2 * playerProfile.networkExp! + 30625) / 50 - 2.5; - if (networkLevel < parseFloat(process.env.MINIMUM_NETWORK_LEVEL)) { - bot.sendGuildMessage( - "oc", - `The player ${playerName} is not network level ${process.env.MINIMUM_NETWORK_LEVEL}!`, - ); - } - } + if (networkLevel < parseFloat(process.env.MINIMUM_NETWORK_LEVEL)) { + bot.sendGuildMessage( + 'oc', + `The player ${playerName} is not network level ${process.env.MINIMUM_NETWORK_LEVEL}!` + ); + } + } - if (isUserBlacklisted(mojangProfile.id)) { - bot.sendGuildMessage("oc", `The player ${playerName} is blacklisted. Do NOT accept their join request.`); - } - }, + if (isUserBlacklisted(mojangProfile.id)) { + bot.sendGuildMessage( + 'oc', + `The player ${playerName} is blacklisted. Do NOT accept their join request.` + ); + } + }, } as Event; diff --git a/src/events/mineflayer/chat/lobbyJoin.ts b/src/events/mineflayer/chat/lobbyJoin.ts index 1ce42741..f9457446 100644 --- a/src/events/mineflayer/chat/lobbyJoin.ts +++ b/src/events/mineflayer/chat/lobbyJoin.ts @@ -1,8 +1,8 @@ export default { - name: "chat:lobbyJoin", - runOnce: false, - run: (bot) => { - bot.logger.warn("Detected that the bot is not in Limbo, sending to limbo."); - bot.sendToLimbo(); - }, + name: 'chat:lobbyJoin', + runOnce: false, + run: (bot) => { + bot.logger.warn('Detected that the bot is not in Limbo, sending to limbo.'); + bot.sendToLimbo(); + }, } as Event; diff --git a/src/events/mineflayer/chat/memberCount.ts b/src/events/mineflayer/chat/memberCount.ts index 0a8c3899..453160cc 100644 --- a/src/events/mineflayer/chat/memberCount.ts +++ b/src/events/mineflayer/chat/memberCount.ts @@ -1,13 +1,13 @@ export default { - name: "chat:memberCount", - runOnce: false, - run: (bot, type: "Online" | "Total", count: number) => { - if (type === "Online") { - bot.onlineCount = count; - } else { - bot.totalCount = count; - } + name: 'chat:memberCount', + runOnce: false, + run: (bot, type: 'Online' | 'Total', count: number) => { + if (type === 'Online') { + bot.onlineCount = count; + } else { + bot.totalCount = count; + } - bot.setStatus(); - }, + bot.setStatus(); + }, } as Event; diff --git a/src/events/mineflayer/chat/memberJoinLeave.ts b/src/events/mineflayer/chat/memberJoinLeave.ts index 573a1906..20835bdd 100644 --- a/src/events/mineflayer/chat/memberJoinLeave.ts +++ b/src/events/mineflayer/chat/memberJoinLeave.ts @@ -1,31 +1,31 @@ -import Emojis from "@util/emojis"; -import { escapeMarkdown } from "discord.js"; -import fetchMojangProfile from "@util/requests/fetchMojangProfile"; -import isFetchError from "@util/requests/isFetchError"; -import isUserBlacklisted from "@util/blacklist/isUserBlacklisted"; -import getRankColor from "@util/getRankColor"; +import Emojis from '@util/emojis'; +import { escapeMarkdown } from 'discord.js'; +import fetchMojangProfile from '@util/requests/fetchMojangProfile'; +import isFetchError from '@util/requests/isFetchError'; +import isUserBlacklisted from '@util/blacklist/isUserBlacklisted'; +import getRankColor from '@util/getRankColor'; export default { - name: "chat:memberJoinLeave", - runOnce: false, - run: async (bot, rank: string | undefined, playerName: string, type: "joined" | "left") => { - if (type === "joined") { - const mojangProfile = await fetchMojangProfile(playerName); + name: 'chat:memberJoinLeave', + runOnce: false, + run: async (bot, rank: string | undefined, playerName: string, type: 'joined' | 'left') => { + if (type === 'joined') { + const mojangProfile = await fetchMojangProfile(playerName); - if (!isFetchError(mojangProfile) && isUserBlacklisted(mojangProfile.id)) { - bot.executeCommand( - `/g kick ${playerName} You have been blacklisted from the guild. Mistake? --> ${process.env.DISCORD_INVITE_LINK}`, - ); - } - } + if (!isFetchError(mojangProfile) && isUserBlacklisted(mojangProfile.id)) { + bot.executeCommand( + `/g kick ${playerName} You have been blacklisted from the guild. Mistake? --> ${process.env.DISCORD_INVITE_LINK}` + ); + } + } - await bot.sendToDiscord( - "gc", - `${type === "joined" ? Emojis.positiveGuildEvent : Emojis.negativeGuildEvent} **${ - rank ? rank + " " : "" - }${escapeMarkdown(playerName)}** ${type} the guild!`, - getRankColor(rank), - true, - ); - }, + await bot.sendToDiscord( + 'gc', + `${type === 'joined' ? Emojis.positiveGuildEvent : Emojis.negativeGuildEvent} **${ + rank ? `${rank} ` : '' + }${escapeMarkdown(playerName)}** ${type} the guild!`, + getRankColor(rank), + true + ); + }, } as Event; diff --git a/src/events/mineflayer/chat/memberKick.ts b/src/events/mineflayer/chat/memberKick.ts index 322dbb7f..7d855f54 100644 --- a/src/events/mineflayer/chat/memberKick.ts +++ b/src/events/mineflayer/chat/memberKick.ts @@ -1,23 +1,25 @@ -import Emojis from "@util/emojis"; -import { escapeMarkdown } from "discord.js"; +import Emojis from '@util/emojis'; +import { escapeMarkdown } from 'discord.js'; export default { - name: "chat:memberKick", - runOnce: false, - run: async ( - bot, - rank: string | undefined, - playerName: string, - kickedByRank: string | undefined, - kickedByPlayerName: string, - ) => { - await bot.sendToDiscord( - "gc", - `${Emojis.negativeGuildEvent} **${rank ? rank + " " : ""}${escapeMarkdown(playerName)}** was kicked by **${ - kickedByRank ? kickedByRank + " " : "" - }${escapeMarkdown(kickedByPlayerName)}**`, - undefined, - true, - ); - }, + name: 'chat:memberKick', + runOnce: false, + run: async ( + bot, + rank: string | undefined, + playerName: string, + kickedByRank: string | undefined, + kickedByPlayerName: string + ) => { + await bot.sendToDiscord( + 'gc', + `${Emojis.negativeGuildEvent} **${rank ? `${rank} ` : ''}${escapeMarkdown( + playerName + )}** was kicked by **${kickedByRank ? `${kickedByRank} ` : ''}${escapeMarkdown( + kickedByPlayerName + )}**`, + undefined, + true + ); + }, } as Event; diff --git a/src/events/mineflayer/chat/promoteDemote.ts b/src/events/mineflayer/chat/promoteDemote.ts index 82194686..af642037 100644 --- a/src/events/mineflayer/chat/promoteDemote.ts +++ b/src/events/mineflayer/chat/promoteDemote.ts @@ -1,25 +1,25 @@ -import { escapeMarkdown } from "discord.js"; -import Emojis from "@util/emojis"; -import getRankColor from "@util/getRankColor"; +import { escapeMarkdown } from 'discord.js'; +import Emojis from '@util/emojis'; +import getRankColor from '@util/getRankColor'; export default { - name: "chat:promoteDemote", - runOnce: false, - run: async ( - bot, - rank: string | undefined, - playerName: string, - type: "promoted" | "demoted", - guildRankFrom: string, - guildRankTo: string, - ) => { - await bot.sendToDiscord( - "gc", - `${type === "promoted" ? Emojis.positiveGuildEvent : Emojis.negativeGuildEvent} **${ - rank ? rank + " " : "" - }${escapeMarkdown(playerName)}** was ${type} to ${guildRankTo} from ${guildRankFrom}!`, - getRankColor(rank), - true, - ); - }, + name: 'chat:promoteDemote', + runOnce: false, + run: async ( + bot, + rank: string | undefined, + playerName: string, + type: 'promoted' | 'demoted', + guildRankFrom: string, + guildRankTo: string + ) => { + await bot.sendToDiscord( + 'gc', + `${type === 'promoted' ? Emojis.positiveGuildEvent : Emojis.negativeGuildEvent} **${ + rank ? `${rank} ` : '' + }${escapeMarkdown(playerName)}** was ${type} to ${guildRankTo} from ${guildRankFrom}!`, + getRankColor(rank), + true + ); + }, } as Event; diff --git a/src/events/mineflayer/chat/questComplete.ts b/src/events/mineflayer/chat/questComplete.ts index 4542dac9..cc953b75 100644 --- a/src/events/mineflayer/chat/questComplete.ts +++ b/src/events/mineflayer/chat/questComplete.ts @@ -1,14 +1,14 @@ -import Emojis from "@util/emojis"; +import Emojis from '@util/emojis'; export default { - name: "chat:questComplete", - runOnce: false, - run: async (bot) => { - await bot.sendToDiscord( - "gc", - `${Emojis.positiveGuildEvent} The guild has completed this week's Guild Quest!`, - 0xffaa00, - true, - ); - }, + name: 'chat:questComplete', + runOnce: false, + run: async (bot) => { + await bot.sendToDiscord( + 'gc', + `${Emojis.positiveGuildEvent} The guild has completed this week's Guild Quest!`, + 0xffaa00, + true + ); + }, } as Event; diff --git a/src/events/mineflayer/chat/questTierComplete.ts b/src/events/mineflayer/chat/questTierComplete.ts index e32bf5b7..86c2973c 100644 --- a/src/events/mineflayer/chat/questTierComplete.ts +++ b/src/events/mineflayer/chat/questTierComplete.ts @@ -1,14 +1,14 @@ -import Emojis from "@util/emojis"; +import Emojis from '@util/emojis'; export default { - name: "chat:questTierComplete", - runOnce: false, - run: async (bot, completedTier: number) => { - await bot.sendToDiscord( - "gc", - `${Emojis.positiveGuildEvent} The guild has completed Tier **${completedTier}** of this week's Guild Quest!`, - 0x36393f, - true, - ); - }, + name: 'chat:questTierComplete', + runOnce: false, + run: async (bot, completedTier: number) => { + await bot.sendToDiscord( + 'gc', + `${Emojis.positiveGuildEvent} The guild has completed Tier **${completedTier}** of this week's Guild Quest!`, + 0x36393f, + true + ); + }, } as Event; diff --git a/src/events/mineflayer/chat/sameMessageTwice.ts b/src/events/mineflayer/chat/sameMessageTwice.ts index 8ae1439d..8ff22f71 100644 --- a/src/events/mineflayer/chat/sameMessageTwice.ts +++ b/src/events/mineflayer/chat/sameMessageTwice.ts @@ -1,7 +1,7 @@ export default { - name: "chat:sameMessageTwice", - runOnce: false, - run: async (bot) => { - await bot.sendToDiscord("gc", "`You cannot say the same message twice!`", 0x36393f); - }, + name: 'chat:sameMessageTwice', + runOnce: false, + run: async (bot) => { + await bot.sendToDiscord('gc', '`You cannot say the same message twice!`', 0x36393f); + }, } as Event; diff --git a/src/events/mineflayer/chat/whisper.ts b/src/events/mineflayer/chat/whisper.ts index 77f8707c..dfbe1aa5 100644 --- a/src/events/mineflayer/chat/whisper.ts +++ b/src/events/mineflayer/chat/whisper.ts @@ -1,30 +1,38 @@ -import fetchHypixelGuild from "@util/requests/fetchHypixelGuild"; -import fetchMojangProfile from "@util/requests/fetchMojangProfile"; -import isFetchError from "@util/requests/isFetchError"; +import fetchHypixelGuild from '@util/requests/fetchHypixelGuild'; +import fetchMojangProfile from '@util/requests/fetchMojangProfile'; +import isFetchError from '@util/requests/isFetchError'; export default { - name: "chat:whisper", - runOnce: false, - run: async (bot, playerName: string, message: string) => { - const errorMessage = `/w ${playerName} There was an error attempting your request! (Check spelling and/or try again later)`; - const target = message.startsWith("weeklygexp" || "weeklygxp") ? playerName : (message.split(" ")[0] as string); + name: 'chat:whisper', + runOnce: false, + run: async (bot, playerName: string, message: string) => { + const errorMessage = `/w ${playerName} There was an error attempting your request! (Check spelling and/or try again later)`; + const target = message.startsWith('weeklygexp' || 'weeklygxp') + ? playerName + : (message.split(' ')[0] as string); - const mojangProfile = await fetchMojangProfile(target); - if (isFetchError(mojangProfile)) { - bot.executeCommand(errorMessage); - return; - } + const mojangProfile = await fetchMojangProfile(target); + if (isFetchError(mojangProfile)) { + bot.executeCommand(errorMessage); + return; + } - const playerGuild = await fetchHypixelGuild(mojangProfile.id); - if (isFetchError(playerGuild)) { - bot.executeCommand(errorMessage); - return; - } + const playerGuild = await fetchHypixelGuild(mojangProfile.id); + if (isFetchError(playerGuild)) { + bot.executeCommand(errorMessage); + return; + } - const member = playerGuild.members.find((guildMember) => guildMember.uuid === mojangProfile.id); + const member = playerGuild.members.find( + (guildMember) => guildMember.uuid === mojangProfile.id + ); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const gexp = Object.values(member!.expHistory).reduce((previous, current) => previous + current); - bot.executeCommand(`/w ${playerName} ${target}'s total weekly gexp: ${gexp.toLocaleString()}`); - }, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const gexp = Object.values(member!.expHistory).reduce( + (previous, current) => previous + current + ); + bot.executeCommand( + `/w ${playerName} ${target}'s total weekly gexp: ${gexp.toLocaleString()}` + ); + }, } as Event; diff --git a/src/events/mineflayer/handler/end.ts b/src/events/mineflayer/handler/end.ts index 65937827..a665e4b6 100644 --- a/src/events/mineflayer/handler/end.ts +++ b/src/events/mineflayer/handler/end.ts @@ -1,11 +1,11 @@ export default { - name: "end", - runOnce: false, - run: (bot) => { - bot.logger.fatal("The bot session has abruptly ended. Restarting the bot in 15 seconds..."); + name: 'end', + runOnce: false, + run: (bot) => { + bot.logger.fatal('The bot session has abruptly ended. Restarting the bot in 15 seconds...'); - setTimeout(() => { - process.exit(1); - }, 15_000); - }, + setTimeout(() => { + process.exit(1); + }, 15_000); + }, } as Event; diff --git a/src/events/mineflayer/handler/error.ts b/src/events/mineflayer/handler/error.ts index c91c4c3d..1b235596 100644 --- a/src/events/mineflayer/handler/error.ts +++ b/src/events/mineflayer/handler/error.ts @@ -1,12 +1,12 @@ export default { - name: "error", - runOnce: false, - run: (bot, error: Error) => { - bot.logger.fatal("Encountered an unexpected error. Restarting the bot in 15 seconds..."); - bot.logger.fatal(error); + name: 'error', + runOnce: false, + run: (bot, error: Error) => { + bot.logger.fatal('Encountered an unexpected error. Restarting the bot in 15 seconds...'); + bot.logger.fatal(error); - setTimeout(() => { - process.exit(1); - }, 15_000); - }, + setTimeout(() => { + process.exit(1); + }, 15_000); + }, } as Event; diff --git a/src/events/mineflayer/handler/kicked.ts b/src/events/mineflayer/handler/kicked.ts index 853387ad..21340f66 100644 --- a/src/events/mineflayer/handler/kicked.ts +++ b/src/events/mineflayer/handler/kicked.ts @@ -1,53 +1,53 @@ -import Emojis from "@util/emojis"; +import Emojis from '@util/emojis'; export default { - name: "kicked", - runOnce: false, - run: async (bot, reason: string, loggedIn: boolean) => { - let message: string; - switch (true) { - // Proxy reboot - case reason.includes("This proxy is being rebooted."): - message = "a proxy reboot"; - break; - - // Duplicate Login - case reason.includes("You logged in from another location!"): - message = "a duplicate login"; - break; - - // Authentication error - case reason.includes("Failed to authenticate your connection!"): - message = "an authentication error"; - break; - - // Invalid packets - case reason.includes("Why do you send us invalid packets?"): - message = "it sending invalid packets"; - break; - - // Maintenance - case reason.includes("This server is currently in maintenance mode") || - reason.includes("is currently down for maintenance"): - message = "hypixel currently being in maintenance mode"; - break; - - default: - message = "an unkown reason"; - break; - } - - await bot.sendToDiscord( - "gc", - `${Emojis.error} The bot was kicked from the server due to ${message}. Restarting the bot in 15 seconds...`, - ); - - bot.logger.error( - `The bot was kicked from the server. Restarting the bot in 15 seconds...\nReason: ${reason}\nLogged in: ${loggedIn}`, - ); - - setTimeout(() => { - process.exit(1); - }, 15_000); - }, + name: 'kicked', + runOnce: false, + run: async (bot, reason: string, loggedIn: boolean) => { + let message: string; + switch (true) { + // Proxy reboot + case reason.includes('This proxy is being rebooted.'): + message = 'a proxy reboot'; + break; + + // Duplicate Login + case reason.includes('You logged in from another location!'): + message = 'a duplicate login'; + break; + + // Authentication error + case reason.includes('Failed to authenticate your connection!'): + message = 'an authentication error'; + break; + + // Invalid packets + case reason.includes('Why do you send us invalid packets?'): + message = 'it sending invalid packets'; + break; + + // Maintenance + case reason.includes('This server is currently in maintenance mode') || + reason.includes('is currently down for maintenance'): + message = 'hypixel currently being in maintenance mode'; + break; + + default: + message = 'an unkown reason'; + break; + } + + await bot.sendToDiscord( + 'gc', + `${Emojis.error} The bot was kicked from the server due to ${message}. Restarting the bot in 15 seconds...` + ); + + bot.logger.error( + `The bot was kicked from the server. Restarting the bot in 15 seconds...\nReason: ${reason}\nLogged in: ${loggedIn}` + ); + + setTimeout(() => { + process.exit(1); + }, 15_000); + }, } as Event; diff --git a/src/events/mineflayer/handler/login.ts b/src/events/mineflayer/handler/login.ts index b6ca9836..442ee894 100644 --- a/src/events/mineflayer/handler/login.ts +++ b/src/events/mineflayer/handler/login.ts @@ -1,29 +1,29 @@ -import Emojis from "@util/emojis"; +import Emojis from '@util/emojis'; export default { - name: "login", - runOnce: true, - run: async (bot) => { - await bot.sendToDiscord( - "gc", - `${Emojis.success} **\`${bot.mineflayer.username}\` has logged in and is now ready!**`, - ); + name: 'login', + runOnce: true, + run: async (bot) => { + await bot.sendToDiscord( + 'gc', + `${Emojis.success} **\`${bot.mineflayer.username}\` has logged in and is now ready!**` + ); - if (process.env.REMINDER_ENABLED === "true") { - const frequency = parseInt(process.env.REMINDER_FREQUENCY, 10); + if (process.env.REMINDER_ENABLED === 'true') { + const frequency = parseInt(process.env.REMINDER_FREQUENCY, 10); - setInterval(() => { - bot.sendGuildMessage("gc", process.env.REMINDER_MESSAGE); - }, 1000 * 60 * (isNaN(frequency) ? 60 : frequency)); - } + setInterval(() => { + bot.sendGuildMessage('gc', process.env.REMINDER_MESSAGE); + }, 1000 * 60 * (Number.isNaN(frequency) ? 60 : frequency)); + } - setInterval(() => { - bot.executeCommand("/g online"); - }, 1000 * 60 * 5); + setInterval(() => { + bot.executeCommand('/g online'); + }, 1000 * 60 * 5); - setTimeout(() => { - bot.executeCommand("/g online"); - bot.sendToLimbo(); - }, 1000 * 3); - }, + setTimeout(() => { + bot.executeCommand('/g online'); + bot.sendToLimbo(); + }, 1000 * 3); + }, } as Event; diff --git a/src/events/mineflayer/handler/message.ts b/src/events/mineflayer/handler/message.ts index 71d12a07..0805af0e 100644 --- a/src/events/mineflayer/handler/message.ts +++ b/src/events/mineflayer/handler/message.ts @@ -1,10 +1,10 @@ -import { ChatMessage } from "prismarine-chat"; +import { ChatMessage } from 'prismarine-chat'; export default { - name: "message", - runOnce: false, - run: (bot, message: ChatMessage) => { - // Log color chat to console - bot.logger.log(message.toAnsi()); - }, + name: 'message', + runOnce: false, + run: (bot, message: ChatMessage) => { + // Log color chat to console + bot.logger.log(message.toAnsi()); + }, } as Event; diff --git a/src/index.ts b/src/index.ts index fa8964c2..1efd486c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ -import { config } from "dotenv"; +import { config } from 'dotenv'; +import Bot from '@classes/Bot'; + config(); -import Bot from "@classes/Bot"; export default new Bot(); diff --git a/src/util/blacklist/isUserBlacklisted.ts b/src/util/blacklist/isUserBlacklisted.ts index 093ec11b..1565d023 100644 --- a/src/util/blacklist/isUserBlacklisted.ts +++ b/src/util/blacklist/isUserBlacklisted.ts @@ -1,6 +1,6 @@ -import _blacklist from "./_blacklist.json"; +import _blacklist from './_blacklist.json'; export default (uuid: string) => { - const blacklist = _blacklist as BlacklistEntry[]; - return blacklist.some((entry) => entry.uuid === uuid); + const blacklist = _blacklist as BlacklistEntry[]; + return blacklist.some((entry) => entry.uuid === uuid); }; diff --git a/src/util/capitaliseString.ts b/src/util/capitaliseString.ts index ca8b0faf..cb99705e 100644 --- a/src/util/capitaliseString.ts +++ b/src/util/capitaliseString.ts @@ -1,3 +1 @@ -export default (str: string) => { - return str.charAt(0).toUpperCase() + str.slice(1); -}; +export default (str: string) => str.charAt(0).toUpperCase() + str.slice(1); diff --git a/src/util/emojis.ts b/src/util/emojis.ts index 44a3fdb4..87718e35 100644 --- a/src/util/emojis.ts +++ b/src/util/emojis.ts @@ -1,41 +1,41 @@ export default { - /** - * Join Emoji - */ - join: "📥", + /** + * Join Emoji + */ + join: '📥', - /** - * Leave Emoji - */ - leave: "📤", + /** + * Leave Emoji + */ + leave: '📤', - /** - * Success Emoji - */ - success: "✅", + /** + * Success Emoji + */ + success: '✅', - /** - * Error Emoji - */ - error: "❌", + /** + * Error Emoji + */ + error: '❌', - /** - * Warning Emoji - */ - warning: "⚠️", + /** + * Warning Emoji + */ + warning: '⚠️', - /** - * Alert Emoji - */ - alert: "🚨", + /** + * Alert Emoji + */ + alert: '🚨', - /** - * Positive Guild Event Emoji - */ - positiveGuildEvent: "🎉", + /** + * Positive Guild Event Emoji + */ + positiveGuildEvent: '🎉', - /** - * Negative Guild Event Emoji - */ - negativeGuildEvent: "👋", + /** + * Negative Guild Event Emoji + */ + negativeGuildEvent: '👋', }; diff --git a/src/util/getRankColor.ts b/src/util/getRankColor.ts index e2f988cd..b9e628f1 100644 --- a/src/util/getRankColor.ts +++ b/src/util/getRankColor.ts @@ -1,22 +1,26 @@ export default (rank?: string) => { - let color = undefined; + let color; - switch (rank) { - case "[ADMIN]": - case "[YOUTUBE]": - color = 0xff5555; - break; - case "[MVP++]": - color = 0xffaa00; - break; - case "[MVP+]": - case "[MVP]": - color = 0x55ffff; - break; - case "[VIP+]": - case "[VIP]": - color = 0x55ff55; - } + switch (rank) { + case '[ADMIN]': + case '[YOUTUBE]': + color = 0xf55; + break; + case '[MVP++]': + color = 0xfa0; + break; + case '[MVP+]': + case '[MVP]': + color = 0x5ff; + break; + case '[VIP+]': + case '[VIP]': + color = 0x5f5; + break; - return color; + default: + color = 0xaaa; + } + + return color; }; diff --git a/src/util/isObjKey.ts b/src/util/isObjKey.ts index 35308e5e..3af8008b 100644 --- a/src/util/isObjKey.ts +++ b/src/util/isObjKey.ts @@ -1,4 +1 @@ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export default (key: any, obj: T): key is keyof T => { - return key in obj; -}; +export default (key: any, obj: T): key is keyof T => key in obj; diff --git a/src/util/logError.ts b/src/util/logError.ts index 284196da..bfe99fd6 100644 --- a/src/util/logError.ts +++ b/src/util/logError.ts @@ -1,12 +1,12 @@ -import { TextChannel } from "discord.js"; -import bot from ".."; +import { TextChannel } from 'discord.js'; +import bot from '..'; export default async (err: Error, message?: string) => { - bot.logger.error(message ? message + err : err); + bot.logger.error(message ? message + err : err); - if (bot.discord.isReady()) { - ((await bot.discord.channels.fetch(process.env.ERROR_CHANNEL_ID)) as TextChannel).send( - err.stack ?? `${err.name}: ${err.message}`, - ); - } + if (bot.discord.isReady()) { + ((await bot.discord.channels.fetch(process.env.ERROR_CHANNEL_ID)) as TextChannel).send( + err.stack ?? `${err.name}: ${err.message}` + ); + } }; diff --git a/src/util/recursiveWalkDir.ts b/src/util/recursiveWalkDir.ts index 768810b7..47890903 100644 --- a/src/util/recursiveWalkDir.ts +++ b/src/util/recursiveWalkDir.ts @@ -1,5 +1,6 @@ -import fs from "fs/promises"; -import path from "path"; +import fs from 'fs/promises'; +import path from 'path'; +import bot from '..'; /** * @@ -8,25 +9,26 @@ import path from "path"; * @param errMessage The error message to display if an error occurs during the process. */ async function recursiveWalkDir( - normalisedDirName: string, - callback: (currentDir: string, file: string) => Promise, - errMessage: string, + normalisedDirName: string, + callback: (currentDir: string, file: string) => Promise, + errMessage: string ) { - const files = await fs.readdir(normalisedDirName); + const files = await fs.readdir(normalisedDirName); + const stats = await Promise.all( + files.map((file) => fs.lstat(path.join(normalisedDirName, file))) + ); - for (const file of files) { - const stat = await fs.lstat(path.join(normalisedDirName, file)); + const promises = stats.map((stat, i) => + stat.isDirectory() + ? recursiveWalkDir(path.join(normalisedDirName, files[i]!), callback, errMessage) + : callback(normalisedDirName, files[i]!) + ); - if (stat.isDirectory()) { - await recursiveWalkDir(path.join(normalisedDirName, file), callback, errMessage); - } else { - try { - await callback(normalisedDirName, file); - } catch (e: unknown) { - console.warn(`${errMessage} ${(e as Error).message}`); - } - } - } + try { + await Promise.all(promises); + } catch (e: unknown) { + bot.logger.error(`${errMessage} ${(e as Error).message}`); + } } export default recursiveWalkDir; diff --git a/src/util/regex.ts b/src/util/regex.ts index 99129804..7d196b39 100644 --- a/src/util/regex.ts +++ b/src/util/regex.ts @@ -1,142 +1,145 @@ export default { - /** - * When a message is blocked for containing suspicious content - * - * Returns: - * - Comment blocked - * - Reason - */ - "chat:commentBlocked": - /^We blocked your comment "(.+)" as it is breaking our rules because (.+). https:\/\/www.hypixel.net\/rules\/$/, + /** + * When a message is blocked for containing suspicious content + * + * Returns: + * - Comment blocked + * - Reason + */ + 'chat:commentBlocked': + /^We blocked your comment "(.+)" as it is breaking our rules because (.+). https:\/\/www.hypixel.net\/rules\/$/, - /** - * When a message is sent in the guild chat - * - * Returns: - * - Channel (Guild / Officer) - * - Hypixel Rank - * - Player Name - * - Guild Rank - * - Message - */ - "chat:guildChat": /^(Guild|Officer) > (\[.*])?\s*(\w{2,17}).*?(\[.{1,15}])?: (.*)$/, + /** + * When a message is sent in the guild chat + * + * Returns: + * - Channel (Guild / Officer) + * - Hypixel Rank + * - Player Name + * - Guild Rank + * - Message + */ + 'chat:guildChat': /^(Guild|Officer) > (\[.*])?\s*(\w{2,17}).*?(\[.{1,15}])?: (.*)$/, - /** - * When the guild levels up - * - * Returns: - * - New Guild Level - */ - "chat:guildLevelUp": /^\s{19}The Guild has reached Level (\d*)!$/, + /** + * When the guild levels up + * + * Returns: + * - New Guild Level + */ + 'chat:guildLevelUp': /^\s{19}The Guild has reached Level (\d*)!$/, - /** - * When a member is muted/unmuted - * - * Returns: - * - Hypixel Rank - * - Player Name - * - muted / unmuted - * - Muter Hypixel Rank - * - Muter Player Name - * - Muter Player Name - * - Duration - */ - "chat:guildMuteUnmute": /^(\[.*])?\s*(\w{2,17}) has (muted|unmuted) (\[.*])?\s*(\w{2,17})(?: for (\d*[a-z]))?$/, + /** + * When a member is muted/unmuted + * + * Returns: + * - Hypixel Rank + * - Player Name + * - muted / unmuted + * - Muter Hypixel Rank + * - Muter Player Name + * - Muter Player Name + * - Duration + */ + 'chat:guildMuteUnmute': + /^(\[.*])?\s*(\w{2,17}) has (muted|unmuted) (\[.*])?\s*(\w{2,17})(?: for (\d*[a-z]))?$/, - /** - * When a member connects to or disconnects from Hypixel - * - * Returns: - * - Player Name - * - joined / left - */ - "chat:joinLeave": /^Guild > (\w{2,17}).*? (joined|left)\.$/, + /** + * When a member connects to or disconnects from Hypixel + * + * Returns: + * - Player Name + * - joined / left + */ + 'chat:joinLeave': /^Guild > (\w{2,17}).*? (joined|left)\.$/, - /** - * When the bot detects it is in Limbo - */ - "chat:joinLimbo": /^You were spawned in Limbo.$/, + /** + * When the bot detects it is in Limbo + */ + 'chat:joinLimbo': /^You were spawned in Limbo.$/, - /** - * When the bot detects its not in Limbo - */ - "chat:lobbyJoin": /^(?:\s>>>\s)?\[.*]\s[\w]{2,17} (?:joined|spooked into|slid into) the lobby!(?:\s<<<)?$/, + /** + * When the bot detects its not in Limbo + */ + 'chat:lobbyJoin': + /^(?:\s>>>\s)?\[.*]\s[\w]{2,17} (?:joined|spooked into|slid into) the lobby!(?:\s<<<)?$/, - /** - * When a player requests to join the guild - * - * Returns: - * - Player Name - */ - "chat:joinRequest": /^(?:\[.*])?\s*(\w{2,17}) has requested to join the Guild!$/, + /** + * When a player requests to join the guild + * + * Returns: + * - Player Name + */ + 'chat:joinRequest': /^(?:\[.*])?\s*(\w{2,17}) has requested to join the Guild!$/, - /** - * When "/g online" is typed, and the online and total member count is shown - * - * Returns: - * - Online / Total - * - Member Count - */ - "chat:memberCount": /^(Online|Total) Members: (\d+)$/, + /** + * When "/g online" is typed, and the online and total member count is shown + * + * Returns: + * - Online / Total + * - Member Count + */ + 'chat:memberCount': /^(Online|Total) Members: (\d+)$/, - /** - * When a player joins or leaves the guild - * - * Returns: - * - Hypixel Rank - * - Player Name - * - joined / left - */ - "chat:memberJoinLeave": /^(\[.*])?\s*(\w{2,17}).*? (joined|left) the guild!$/, + /** + * When a player joins or leaves the guild + * + * Returns: + * - Hypixel Rank + * - Player Name + * - joined / left + */ + 'chat:memberJoinLeave': /^(\[.*])?\s*(\w{2,17}).*? (joined|left) the guild!$/, - /** - * When a player is kicked from the guild - * - * Returns: - * - Hypixel Rank - * - Player Name - * - Kicker Hypixel Rank - * - Kicker Player Name - */ - "chat:memberKick": /^(\[.*])?\s*(\w{2,17}).*? was kicked from the guild by (\[.*])?\s*(\w{2,17}).*?!$/, + /** + * When a player is kicked from the guild + * + * Returns: + * - Hypixel Rank + * - Player Name + * - Kicker Hypixel Rank + * - Kicker Player Name + */ + 'chat:memberKick': + /^(\[.*])?\s*(\w{2,17}).*? was kicked from the guild by (\[.*])?\s*(\w{2,17}).*?!$/, - /** - * When a member is promoted or demoted - * - * Returns: - * - Hypixel Rank - * - Player Name - * - promoted / demoted - * - From Rank - * - To Rank - */ - "chat:promoteDemote": /^(\[.*])?\s*(\w{2,17}).*? was (promoted|demoted) from (.*) to (.*)$/, + /** + * When a member is promoted or demoted + * + * Returns: + * - Hypixel Rank + * - Player Name + * - promoted / demoted + * - From Rank + * - To Rank + */ + 'chat:promoteDemote': /^(\[.*])?\s*(\w{2,17}).*? was (promoted|demoted) from (.*) to (.*)$/, - /** - * When all guild quest tiers are complete - */ - "chat:questComplete": /^\s{17}GUILD QUEST COMPLETED!$/, + /** + * When all guild quest tiers are complete + */ + 'chat:questComplete': /^\s{17}GUILD QUEST COMPLETED!$/, - /** - * When a guild quest tier is complete - * - * Returns: - * - Tier Completed - */ - "chat:questTierComplete": /^\s{17}GUILD QUEST TIER (\d*) COMPLETED!$/, + /** + * When a guild quest tier is complete + * + * Returns: + * - Tier Completed + */ + 'chat:questTierComplete': /^\s{17}GUILD QUEST TIER (\d*) COMPLETED!$/, - /** - * When a message is sent repeatedly - */ - "chat:sameMessageTwice": /^You cannot say the same message twice!$/, + /** + * When a message is sent repeatedly + */ + 'chat:sameMessageTwice': /^You cannot say the same message twice!$/, - /** - * When a player whispers to the bot with "/msg" - * - * Returns: - * - Hypixel Rank - * - Player Name - * - Message - */ - "chat:whisper": /^From (?:\[.*])?\s*(\w{2,17}).*?: (.+)$/, + /** + * When a player whispers to the bot with "/msg" + * + * Returns: + * - Hypixel Rank + * - Player Name + * - Message + */ + 'chat:whisper': /^From (?:\[.*])?\s*(\w{2,17}).*?: (.+)$/, }; diff --git a/src/util/requests/FetchError.d.ts b/src/util/requests/FetchError.d.ts index 99a79e22..4312d92f 100644 --- a/src/util/requests/FetchError.d.ts +++ b/src/util/requests/FetchError.d.ts @@ -1,4 +1,4 @@ declare interface FetchError { - readonly status: number; - readonly statusText: string; + readonly status: number; + readonly statusText: string; } diff --git a/src/util/requests/fetchErrorEmbed.ts b/src/util/requests/fetchErrorEmbed.ts index af694d78..846c1c75 100644 --- a/src/util/requests/fetchErrorEmbed.ts +++ b/src/util/requests/fetchErrorEmbed.ts @@ -1,10 +1,9 @@ -import { EmbedBuilder } from "discord.js"; +import { EmbedBuilder } from 'discord.js'; -export default (requestError: FetchError) => { - return new EmbedBuilder() - .setColor("Red") - .setTitle("Error") - .setDescription( - `There was an error while attempting your request, a detailed log is below.\n\`\`\`Error: ${requestError.status}\nReason: ${requestError.statusText}\`\`\``, - ); -}; +export default (requestError: FetchError) => + new EmbedBuilder() + .setColor('Red') + .setTitle('Error') + .setDescription( + `There was an error while attempting your request, a detailed log is below.\n\`\`\`Error: ${requestError.status}\nReason: ${requestError.statusText}\`\`\`` + ); diff --git a/src/util/requests/fetchHypixelGuild.ts b/src/util/requests/fetchHypixelGuild.ts index 70dbcaeb..70d35152 100644 --- a/src/util/requests/fetchHypixelGuild.ts +++ b/src/util/requests/fetchHypixelGuild.ts @@ -1,46 +1,48 @@ export default async (uuid: string) => { - const response = await fetch(`https://api.hypixel.net/guild?key=${process.env.HYPIXEL_API_KEY}&player=${uuid}`); + const response = await fetch( + `https://api.hypixel.net/guild?key=${process.env.HYPIXEL_API_KEY}&player=${uuid}` + ); - return response.status === 200 - ? (((await response.json()) as any).guild as HypixelGuildResponse) // eslint-disable-line @typescript-eslint/no-explicit-any - : (response as FetchError); + return response.status === 200 + ? (((await response.json()) as any).guild as HypixelGuildResponse) + : (response as FetchError); }; /** * Source: https://github.com/unaussprechlich/hypixel-api-typescript/ */ interface HypixelGuildResponse { - _id: string; - name: string; - coins: number; - memberSizeLevel: number; - bankSizeLevel: number; - coinsEver: number; - created: number; - members: Member[]; - canParty: boolean; - canTag: boolean; - tag?: string; - banner?: Banner; - canMotd?: boolean; - vipCount?: number; - mvpCount?: number; - tagColor?: string; + _id: string; + name: string; + coins: number; + memberSizeLevel: number; + bankSizeLevel: number; + coinsEver: number; + created: number; + members: Member[]; + canParty: boolean; + canTag: boolean; + tag?: string; + banner?: Banner; + canMotd?: boolean; + vipCount?: number; + mvpCount?: number; + tagColor?: string; } interface Member { - uuid: string; - rank: string; - joined: number; - expHistory: { [key: number]: number }; + uuid: string; + rank: string; + joined: number; + expHistory: { [key: number]: number }; } interface Banner { - Base?: string; - Patterns?: Pattern[]; + Base?: string; + Patterns?: Pattern[]; } interface Pattern { - Pattern?: string; - Color?: string | number; + Pattern?: string; + Color?: string | number; } diff --git a/src/util/requests/fetchHypixelPlayerProfile.ts b/src/util/requests/fetchHypixelPlayerProfile.ts index 08f0b61d..83ef43dc 100644 --- a/src/util/requests/fetchHypixelPlayerProfile.ts +++ b/src/util/requests/fetchHypixelPlayerProfile.ts @@ -1,64 +1,66 @@ export default async (username: string) => { - const response = await fetch(`https://api.hypixel.net/player?key=${process.env.HYPIXEL_API_KEY}&name=${username}`); + const response = await fetch( + `https://api.hypixel.net/player?key=${process.env.HYPIXEL_API_KEY}&name=${username}` + ); - return response.status === 200 - ? (((await response.json()) as any).player as HypixelPlayerResponse) // eslint-disable-line @typescript-eslint/no-explicit-any - : (response as FetchError); + return response.status === 200 + ? (((await response.json()) as any).player as HypixelPlayerResponse) + : (response as FetchError); }; /** * Attenuated Version of Source: https://github.com/unaussprechlich/hypixel-api-typescript/ */ interface HypixelPlayerResponse { - id: string; - achievementsOneTime?: (string | null[] | null)[] | null; - channel?: string; - disguise?: string; - displayname: string; - eulaCoins?: boolean; - firstLogin?: number; - friendRequests?: null[] | null; - karma?: number; - knownAliases?: string[] | null; - knownAliasesLower?: string[] | null; - lastLogin?: number; - mainlobbytutorial?: boolean; - mostRecentMinecraftVersion?: number; - mostRecentlyThanked?: string; - mostRecentlyThankedUuid?: string; - mostRecentlyTipped?: string; - mostRecentlyTippedUuid?: string; - networkExp?: number; - newClock?: string; - notifications?: boolean; - packageRank?: string; - playername?: string; - pp?: string; - spectators_invisible?: boolean; - testPass?: boolean; - thanksSent?: number; - timePlaying?: number; - uuid?: string; - vanityTokens?: number; - wardrobe?: string; - websiteSet?: boolean; - gadget?: string; - friendRequestsUuid?: null[] | null; - lastEugeneMessage?: number; - last_survey?: number; - particleQuality?: string; - mcVersionRp?: string; + id: string; + achievementsOneTime?: (string | null[] | null)[] | null; + channel?: string; + disguise?: string; + displayname: string; + eulaCoins?: boolean; + firstLogin?: number; + friendRequests?: null[] | null; + karma?: number; + knownAliases?: string[] | null; + knownAliasesLower?: string[] | null; + lastLogin?: number; + mainlobbytutorial?: boolean; + mostRecentMinecraftVersion?: number; + mostRecentlyThanked?: string; + mostRecentlyThankedUuid?: string; + mostRecentlyTipped?: string; + mostRecentlyTippedUuid?: string; + networkExp?: number; + newClock?: string; + notifications?: boolean; + packageRank?: string; + playername?: string; + pp?: string; + spectators_invisible?: boolean; + testPass?: boolean; + thanksSent?: number; + timePlaying?: number; + uuid?: string; + vanityTokens?: number; + wardrobe?: string; + websiteSet?: boolean; + gadget?: string; + friendRequestsUuid?: null[] | null; + lastEugeneMessage?: number; + last_survey?: number; + particleQuality?: string; + mcVersionRp?: string; - rankPlusColor?: string; - lastAdsenseGenerateTime?: number; - lastClaimedReward?: number; - totalRewards?: number; - totalDailyRewards?: number; - rewardStreak?: number; - rewardScore?: number; - rewardHighScore?: number; - vanityConvertedBoxToday?: number; - vanityFirstConvertedBox?: number; - adsense_tokens?: number; - userLanguage?: string; + rankPlusColor?: string; + lastAdsenseGenerateTime?: number; + lastClaimedReward?: number; + totalRewards?: number; + totalDailyRewards?: number; + rewardStreak?: number; + rewardScore?: number; + rewardHighScore?: number; + vanityConvertedBoxToday?: number; + vanityFirstConvertedBox?: number; + adsense_tokens?: number; + userLanguage?: string; } diff --git a/src/util/requests/fetchMojangProfile.ts b/src/util/requests/fetchMojangProfile.ts index 5d5fa239..854aa469 100644 --- a/src/util/requests/fetchMojangProfile.ts +++ b/src/util/requests/fetchMojangProfile.ts @@ -1,10 +1,12 @@ export default async (username: string) => { - const response = await fetch(`https://api.mojang.com/users/profiles/minecraft/${username}`); + const response = await fetch(`https://api.mojang.com/users/profiles/minecraft/${username}`); - return response.status === 200 ? ((await response.json()) as MojangProfileResponse) : (response as FetchError); + return response.status === 200 + ? ((await response.json()) as MojangProfileResponse) + : (response as FetchError); }; interface MojangProfileResponse { - readonly id: string; - readonly name: string; + readonly id: string; + readonly name: string; } diff --git a/src/util/requests/isFetchError.ts b/src/util/requests/isFetchError.ts index 07576634..94f4875a 100644 --- a/src/util/requests/isFetchError.ts +++ b/src/util/requests/isFetchError.ts @@ -1,4 +1,2 @@ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export default (response: any | FetchError): response is FetchError => { - return !response || ("status" in response && "statusText" in response); -}; +export default (response: any | FetchError): response is FetchError => + !response || ('status' in response && 'statusText' in response); diff --git a/src/util/writeToJsonFile.ts b/src/util/writeToJsonFile.ts index 512c2096..6be14b92 100644 --- a/src/util/writeToJsonFile.ts +++ b/src/util/writeToJsonFile.ts @@ -1,6 +1,6 @@ -import { CommandInteraction, EmbedBuilder } from "discord.js"; -import logError from "./logError"; -import { writeFile } from "fs"; +import { CommandInteraction, EmbedBuilder } from 'discord.js'; +import { writeFile } from 'fs'; +import logError from './logError'; /** * @param path The path to the target file. Path must begin from the path root. @@ -9,25 +9,32 @@ import { writeFile } from "fs"; * @param successEmbed The embed to reply with if successful. */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export default (path: string, data: any, interaction: CommandInteraction, successEmbed: EmbedBuilder) => { - writeFile(path, JSON.stringify(data), async (err) => { - if (!err) { - if (interaction.replied || interaction.deferred) { - await interaction.editReply({ embeds: [successEmbed] }); - return; - } - await interaction.reply({ embeds: [successEmbed] }); - return; - } +export default ( + path: string, + data: any, + interaction: CommandInteraction, + successEmbed: EmbedBuilder +) => { + writeFile(path, JSON.stringify(data), async (err) => { + if (!err) { + if (interaction.replied || interaction.deferred) { + await interaction.editReply({ embeds: [successEmbed] }); + return; + } + await interaction.reply({ embeds: [successEmbed] }); + return; + } - logError(err, "Failed to write to file: "); - const embed = new EmbedBuilder().setColor("Red").setTitle("Error").setDescription("Failed to write to file!"); + logError(err, 'Failed to write to file: '); + const embed = new EmbedBuilder() + .setColor('Red') + .setTitle('Error') + .setDescription('Failed to write to file!'); - if (interaction.replied || interaction.deferred) { - await interaction.editReply({ embeds: [successEmbed] }); - return; - } - await interaction.reply({ embeds: [embed] }); - }); + if (interaction.replied || interaction.deferred) { + await interaction.editReply({ embeds: [successEmbed] }); + return; + } + await interaction.reply({ embeds: [embed] }); + }); }; diff --git a/tsconfig.json b/tsconfig.json index f224757f..8f3cb4a0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,23 +1,23 @@ { - "compilerOptions": { - "target": "ESNext", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "outDir": "./dist", - "resolveJsonModule": true, - "preserveConstEnums": true, - "strict": true, - "noUncheckedIndexedAccess": true, - "noImplicitReturns": true, - "allowUnreachableCode": false, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "allowJs": false, - "skipLibCheck": true, - "isolatedModules": true, - "paths": { - "@classes/*": ["./src/classes/*"], - "@util/*": ["./src/util/*"] - } - } + "compilerOptions": { + "target": "ESNext", + "module": "CommonJS", + "moduleResolution": "Node", + "outDir": "./dist", + "resolveJsonModule": true, + "preserveConstEnums": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "noImplicitReturns": true, + "allowUnreachableCode": false, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "allowJs": false, + "skipLibCheck": true, + "isolatedModules": true, + "paths": { + "@classes/*": ["./src/classes/*"], + "@util/*": ["./src/util/*"] + } + } } From 4c3c09002b26cc8b5f637c44543842f7e41b0f8d Mon Sep 17 00:00:00 2001 From: John Doe <69335633+Jejebecarte@users.noreply.github.com> Date: Fri, 12 Apr 2024 12:34:11 +1000 Subject: [PATCH 4/8] fix: copy old paths to new paths on file setup --- scripts/setup-files.js | 4 ++-- src/@types/Command.d.ts | 3 +-- src/commands/blacklist.ts | 7 +++---- src/commands/invite.ts | 2 +- src/commands/kick.ts | 4 ++-- src/commands/promoteDemote.ts | 4 ++-- src/commands/toggleMute.ts | 4 ++-- src/events/discord/interactionCreate.ts | 2 +- src/events/discord/message.ts | 1 - src/events/mineflayer/chat/joinRequest.ts | 1 - src/events/mineflayer/chat/whisper.ts | 2 +- 11 files changed, 15 insertions(+), 19 deletions(-) diff --git a/scripts/setup-files.js b/scripts/setup-files.js index 3a6c56cc..14276d17 100644 --- a/scripts/setup-files.js +++ b/scripts/setup-files.js @@ -5,7 +5,7 @@ const oldPaths = ['.env.template', 'src/util/blacklist/_blacklist.json.template' oldPaths.forEach((path) => { if (!fs.existsSync(path)) { console.warn( - `File ${path} does not exist. If you have NOT run this command before, you may need to repair your installation.` + `File '${path}' does not exist. If you have NOT run this command before, you may need to repair your installation.` ); return; @@ -15,6 +15,6 @@ oldPaths.forEach((path) => { if (fs.existsSync(newPath)) { console.warn(`File '${newPath}' already exists.`); } else { - fs.copyFileSync(newPath, path, fs.constants.COPYFILE_EXCL); + fs.copyFileSync(path, newPath, fs.constants.COPYFILE_EXCL); } }); diff --git a/src/@types/Command.d.ts b/src/@types/Command.d.ts index 4a61f96c..153ccdd0 100644 --- a/src/@types/Command.d.ts +++ b/src/@types/Command.d.ts @@ -7,6 +7,5 @@ declare interface Command { type ExecuteCommand = ( bot: import('@classes/Bot').default, interaction: import('discord.js').ChatInputCommandInteraction, - // TODO: use never[] below and force implementations to define types explicitly (use spread?) - args: any[] + args: unknown[] ) => Promise; diff --git a/src/commands/blacklist.ts b/src/commands/blacklist.ts index 6a0ac062..487f61da 100644 --- a/src/commands/blacklist.ts +++ b/src/commands/blacklist.ts @@ -52,7 +52,7 @@ export default { }, run: async (bot, interaction, args) => { const type = interaction.options.getSubcommand() as 'add' | 'remove'; - const mojangProfile = await fetchMojangProfile(args[0]); + const mojangProfile = await fetchMojangProfile(args[0] as string); const blacklist = _blacklist as BlacklistEntry[]; if (isFetchError(mojangProfile)) { @@ -75,8 +75,8 @@ export default { } if (type === 'add') { - const endDate = args[1]; - const reason = args[2]; + const endDate = args[1] as string; + const reason = args[2] as string; const embed = new EmbedBuilder() .setAuthor({ name: 'Blacklist', @@ -108,7 +108,6 @@ export default { messageId: blacklistMessage.id, }); } else { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const blacklistEntry = blacklist.find((user) => user.uuid === mojangProfile.id)!; blacklist.splice(blacklist.indexOf(blacklistEntry)); diff --git a/src/commands/invite.ts b/src/commands/invite.ts index dc0bfe9b..9f197702 100644 --- a/src/commands/invite.ts +++ b/src/commands/invite.ts @@ -14,7 +14,7 @@ export default { ], }, run: async (bot, interaction, args) => { - const user = args[0]; + const user = args[0] as string; const embed = new EmbedBuilder(); try { diff --git a/src/commands/kick.ts b/src/commands/kick.ts index fbb6fb26..008c2931 100644 --- a/src/commands/kick.ts +++ b/src/commands/kick.ts @@ -20,8 +20,8 @@ export default { ], }, run: async (bot, interaction, args) => { - const user: string = args[0]; - const reason: string = args[1]; + const user = args[0] as string; + const reason = args[1] as string; const embed = new EmbedBuilder(); try { diff --git a/src/commands/promoteDemote.ts b/src/commands/promoteDemote.ts index 805ae374..98b62580 100644 --- a/src/commands/promoteDemote.ts +++ b/src/commands/promoteDemote.ts @@ -31,8 +31,8 @@ export default { ], }, run: async (bot, interaction, args) => { - const type: string = args[0] as 'promote' | 'demote'; - const user: string = args[1]; + const type = args[0] as 'promote' | 'demote'; + const user = args[1] as string; const embed = new EmbedBuilder(); try { diff --git a/src/commands/toggleMute.ts b/src/commands/toggleMute.ts index 1f966f9b..f83b9a0f 100644 --- a/src/commands/toggleMute.ts +++ b/src/commands/toggleMute.ts @@ -42,8 +42,8 @@ export default { }, run: async (bot, interaction, args) => { const type = interaction.options.getSubcommand() as 'mute' | 'unmute'; - const user: string = args[0]; - const duration: string = args[1]; + const user = args[0] as string; + const duration = args[1] as string; const embed = new EmbedBuilder(); try { diff --git a/src/events/discord/interactionCreate.ts b/src/events/discord/interactionCreate.ts index 2e13b9b4..53fe0b34 100644 --- a/src/events/discord/interactionCreate.ts +++ b/src/events/discord/interactionCreate.ts @@ -28,7 +28,7 @@ export default { return; } - const args: any[] = []; + const args: unknown[] = []; interaction.options.data.forEach((option) => { if (option.value) args.push(option.value); diff --git a/src/events/discord/message.ts b/src/events/discord/message.ts index 54d49909..3833a81c 100644 --- a/src/events/discord/message.ts +++ b/src/events/discord/message.ts @@ -5,7 +5,6 @@ import emojis from '@util/emojis'; const whitelist = ['ass', 'bitch', 'cock', 'dick', 'fuck']; const dataset = new DataSet<{ originalWord: string }>() .addAll(englishDataset) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion .removePhrasesIf((phrase) => whitelist.includes(phrase.metadata!.originalWord)); const profanityMatcher = new RegExpMatcher({ diff --git a/src/events/mineflayer/chat/joinRequest.ts b/src/events/mineflayer/chat/joinRequest.ts index c03a9ca0..e1a64b0a 100644 --- a/src/events/mineflayer/chat/joinRequest.ts +++ b/src/events/mineflayer/chat/joinRequest.ts @@ -12,7 +12,6 @@ export default { const playerProfile = await fetchHypixelPlayerProfile(playerName); if (!isFetchError(playerProfile)) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const networkLevel = Math.sqrt(2 * playerProfile.networkExp! + 30625) / 50 - 2.5; if (networkLevel < parseFloat(process.env.MINIMUM_NETWORK_LEVEL)) { diff --git a/src/events/mineflayer/chat/whisper.ts b/src/events/mineflayer/chat/whisper.ts index dfbe1aa5..1b5b6aeb 100644 --- a/src/events/mineflayer/chat/whisper.ts +++ b/src/events/mineflayer/chat/whisper.ts @@ -27,10 +27,10 @@ export default { (guildMember) => guildMember.uuid === mojangProfile.id ); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const gexp = Object.values(member!.expHistory).reduce( (previous, current) => previous + current ); + bot.executeCommand( `/w ${playerName} ${target}'s total weekly gexp: ${gexp.toLocaleString()}` ); From 42a8cf960116fc0b384e7b376c710e44600902b0 Mon Sep 17 00:00:00 2001 From: John Doe <69335633+Jejebecarte@users.noreply.github.com> Date: Tue, 7 May 2024 17:20:26 +1000 Subject: [PATCH 5/8] fix: blacklist writing to incorrect file path --- src/commands/blacklist.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/commands/blacklist.ts b/src/commands/blacklist.ts index 487f61da..378e896b 100644 --- a/src/commands/blacklist.ts +++ b/src/commands/blacklist.ts @@ -78,13 +78,9 @@ export default { const endDate = args[1] as string; const reason = args[2] as string; const embed = new EmbedBuilder() - .setAuthor({ - name: 'Blacklist', - iconURL: - 'https://media.discordapp.net/attachments/522930879413092388/849317688517853294/misc.png', - }) + .setAuthor({ name: 'Blacklist' }) .setColor('Red') - .setFooter({ text: `UUID: ${mojangProfile.id}` }) + .setFooter({ text: mojangProfile.id }) .setThumbnail(`https://visage.surgeplay.com/full/${mojangProfile.id}.png`) .setTimestamp() .setTitle(mojangProfile.name) @@ -127,7 +123,12 @@ export default { } the blacklist!` ); - writeToJsonFile('./s@util/_blacklist.json', blacklist, interaction, successEmbed); + writeToJsonFile( + './src/util/blacklist/_blacklist.json', + blacklist, + interaction, + successEmbed + ); }, staffOnly: true, } as Command; From b3c432c93586129e28708b9419a8e79587df4bcb Mon Sep 17 00:00:00 2001 From: John Doe <69335633+Jejebecarte@users.noreply.github.com> Date: Tue, 7 May 2024 17:48:50 +1000 Subject: [PATCH 6/8] refactor: enforce lower-camel-case file names --- src/@types/Command.d.ts | 2 +- src/@types/Event.d.ts | 2 +- src/@types/{BlacklistEntry.d.ts => blacklist-entry.d.ts} | 0 src/classes/Bot.ts | 8 ++++---- src/commands/blacklist.ts | 8 ++++---- src/commands/{promoteDemote.ts => promote-demote.ts} | 2 +- src/commands/{toggleMute.ts => toggle-mute.ts} | 2 +- .../{interactionCreate.ts => interaction-create.ts} | 0 .../chat/{commentBlocked.ts => comment-blocked.ts} | 0 .../mineflayer/chat/{guildChat.ts => guild-chat.ts} | 2 +- .../chat/{guildLevelUp.ts => guild-level-up.ts} | 0 .../chat/{guildMuteUnmute.ts => guild-mute-unmute.ts} | 0 .../mineflayer/chat/{joinLeave.ts => join-leave.ts} | 0 .../mineflayer/chat/{joinLimbo.ts => join-limbo.ts} | 0 .../mineflayer/chat/{joinRequest.ts => join-request.ts} | 8 ++++---- .../mineflayer/chat/{lobbyJoin.ts => lobby-join.ts} | 0 .../mineflayer/chat/{memberCount.ts => member-count.ts} | 0 .../chat/{memberJoinLeave.ts => member-join-leave.ts} | 8 ++++---- .../mineflayer/chat/{memberKick.ts => member-kick.ts} | 0 .../chat/{promoteDemote.ts => promote-demote.ts} | 2 +- .../chat/{questComplete.ts => quest-complete.ts} | 0 .../chat/{questTierComplete.ts => quest-tier-complete.ts} | 0 .../chat/{sameMessageTwice.ts => same-message-twice.ts} | 0 src/events/mineflayer/chat/whisper.ts | 6 +++--- src/index.ts | 2 +- .../{isUserBlacklisted.ts => is-user-blacklisted.ts} | 0 src/util/{capitaliseString.ts => capitalise-string.ts} | 0 src/util/{getRankColor.ts => get-rank-color.ts} | 0 src/util/{isObjKey.ts => is-obj-key.ts} | 0 src/util/{logError.ts => log-error.ts} | 0 src/util/{recursiveWalkDir.ts => recursive-walk-dir.ts} | 0 .../requests/{fetchErrorEmbed.ts => fetch-error-embed.ts} | 0 src/util/requests/{FetchError.d.ts => fetch-error.d.ts} | 0 .../{fetchHypixelGuild.ts => fetch-hypixel-guild.ts} | 0 ...elPlayerProfile.ts => fetch-hypixel-player-profile.ts} | 0 .../{fetchMojangProfile.ts => fetch-mojan-profile.ts} | 0 src/util/requests/{isFetchError.ts => is-fetch-error.ts} | 0 src/util/{writeToJsonFile.ts => write-to-json-file.ts} | 2 +- 38 files changed, 27 insertions(+), 27 deletions(-) rename src/@types/{BlacklistEntry.d.ts => blacklist-entry.d.ts} (100%) rename src/commands/{promoteDemote.ts => promote-demote.ts} (96%) rename src/commands/{toggleMute.ts => toggle-mute.ts} (97%) rename src/events/discord/{interactionCreate.ts => interaction-create.ts} (100%) rename src/events/mineflayer/chat/{commentBlocked.ts => comment-blocked.ts} (100%) rename src/events/mineflayer/chat/{guildChat.ts => guild-chat.ts} (92%) rename src/events/mineflayer/chat/{guildLevelUp.ts => guild-level-up.ts} (100%) rename src/events/mineflayer/chat/{guildMuteUnmute.ts => guild-mute-unmute.ts} (100%) rename src/events/mineflayer/chat/{joinLeave.ts => join-leave.ts} (100%) rename src/events/mineflayer/chat/{joinLimbo.ts => join-limbo.ts} (100%) rename src/events/mineflayer/chat/{joinRequest.ts => join-request.ts} (77%) rename src/events/mineflayer/chat/{lobbyJoin.ts => lobby-join.ts} (100%) rename src/events/mineflayer/chat/{memberCount.ts => member-count.ts} (100%) rename src/events/mineflayer/chat/{memberJoinLeave.ts => member-join-leave.ts} (80%) rename src/events/mineflayer/chat/{memberKick.ts => member-kick.ts} (100%) rename src/events/mineflayer/chat/{promoteDemote.ts => promote-demote.ts} (93%) rename src/events/mineflayer/chat/{questComplete.ts => quest-complete.ts} (100%) rename src/events/mineflayer/chat/{questTierComplete.ts => quest-tier-complete.ts} (100%) rename src/events/mineflayer/chat/{sameMessageTwice.ts => same-message-twice.ts} (100%) rename src/util/blacklist/{isUserBlacklisted.ts => is-user-blacklisted.ts} (100%) rename src/util/{capitaliseString.ts => capitalise-string.ts} (100%) rename src/util/{getRankColor.ts => get-rank-color.ts} (100%) rename src/util/{isObjKey.ts => is-obj-key.ts} (100%) rename src/util/{logError.ts => log-error.ts} (100%) rename src/util/{recursiveWalkDir.ts => recursive-walk-dir.ts} (100%) rename src/util/requests/{fetchErrorEmbed.ts => fetch-error-embed.ts} (100%) rename src/util/requests/{FetchError.d.ts => fetch-error.d.ts} (100%) rename src/util/requests/{fetchHypixelGuild.ts => fetch-hypixel-guild.ts} (100%) rename src/util/requests/{fetchHypixelPlayerProfile.ts => fetch-hypixel-player-profile.ts} (100%) rename src/util/requests/{fetchMojangProfile.ts => fetch-mojan-profile.ts} (100%) rename src/util/requests/{isFetchError.ts => is-fetch-error.ts} (100%) rename src/util/{writeToJsonFile.ts => write-to-json-file.ts} (97%) diff --git a/src/@types/Command.d.ts b/src/@types/Command.d.ts index 153ccdd0..3d3d4fc5 100644 --- a/src/@types/Command.d.ts +++ b/src/@types/Command.d.ts @@ -5,7 +5,7 @@ declare interface Command { } type ExecuteCommand = ( - bot: import('@classes/Bot').default, + bot: import('@classes/bot').default, interaction: import('discord.js').ChatInputCommandInteraction, args: unknown[] ) => Promise; diff --git a/src/@types/Event.d.ts b/src/@types/Event.d.ts index 9e52eb2e..dd1ecae4 100644 --- a/src/@types/Event.d.ts +++ b/src/@types/Event.d.ts @@ -7,4 +7,4 @@ declare interface Event { run: Execute; } -type Execute = (bot: import('@classes/Bot').default, ...params: any[]) => Promise; +type Execute = (bot: import('@classes/bot').default, ...params: any[]) => Promise; diff --git a/src/@types/BlacklistEntry.d.ts b/src/@types/blacklist-entry.d.ts similarity index 100% rename from src/@types/BlacklistEntry.d.ts rename to src/@types/blacklist-entry.d.ts diff --git a/src/classes/Bot.ts b/src/classes/Bot.ts index 7f2a9b9f..3809ae90 100644 --- a/src/classes/Bot.ts +++ b/src/classes/Bot.ts @@ -8,12 +8,12 @@ import { import { BotEvents, createBot } from 'mineflayer'; import EventEmitter from 'events'; import consola from 'consola'; -import isObjKey from '@util/isObjKey'; -import logError from '@util/logError'; +import isObjKey from '@util/is-obj-key'; +import logError from '@util/log-error'; import path from 'path'; -import recursiveWalkDir from '@util/recursiveWalkDir'; +import recursiveWalkDir from '@util/recursive-walk-dir'; import regex from '@util/regex'; -import Discord from './Client'; +import Discord from './client'; class Bot { public readonly logger = consola; diff --git a/src/commands/blacklist.ts b/src/commands/blacklist.ts index 378e896b..cc300f6a 100644 --- a/src/commands/blacklist.ts +++ b/src/commands/blacklist.ts @@ -1,9 +1,9 @@ import { ApplicationCommandOptionType, EmbedBuilder, TextChannel } from 'discord.js'; import _blacklist from '@util/blacklist/_blacklist.json'; -import fetchErrorEmbed from '@util/requests/fetchErrorEmbed'; -import fetchMojangProfile from '@util/requests/fetchMojangProfile'; -import isFetchError from '@util/requests/isFetchError'; -import writeToJsonFile from '@util/writeToJsonFile'; +import fetchErrorEmbed from '@util/requests/fetch-error-embed'; +import fetchMojangProfile from '@util/requests/fetch-mojan-profile'; +import isFetchError from '@util/requests/is-fetch-error'; +import writeToJsonFile from '@util/write-to-json-file'; export default { data: { diff --git a/src/commands/promoteDemote.ts b/src/commands/promote-demote.ts similarity index 96% rename from src/commands/promoteDemote.ts rename to src/commands/promote-demote.ts index 98b62580..eba20e91 100644 --- a/src/commands/promoteDemote.ts +++ b/src/commands/promote-demote.ts @@ -1,5 +1,5 @@ import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; -import capitaliseString from '@util/capitaliseString'; +import capitaliseString from '@util/capitalise-string'; export default { data: { diff --git a/src/commands/toggleMute.ts b/src/commands/toggle-mute.ts similarity index 97% rename from src/commands/toggleMute.ts rename to src/commands/toggle-mute.ts index f83b9a0f..3663eb35 100644 --- a/src/commands/toggleMute.ts +++ b/src/commands/toggle-mute.ts @@ -1,5 +1,5 @@ import { ApplicationCommandOptionType, EmbedBuilder } from 'discord.js'; -import capitaliseString from '@util/capitaliseString'; +import capitaliseString from '@util/capitalise-string'; export default { data: { diff --git a/src/events/discord/interactionCreate.ts b/src/events/discord/interaction-create.ts similarity index 100% rename from src/events/discord/interactionCreate.ts rename to src/events/discord/interaction-create.ts diff --git a/src/events/mineflayer/chat/commentBlocked.ts b/src/events/mineflayer/chat/comment-blocked.ts similarity index 100% rename from src/events/mineflayer/chat/commentBlocked.ts rename to src/events/mineflayer/chat/comment-blocked.ts diff --git a/src/events/mineflayer/chat/guildChat.ts b/src/events/mineflayer/chat/guild-chat.ts similarity index 92% rename from src/events/mineflayer/chat/guildChat.ts rename to src/events/mineflayer/chat/guild-chat.ts index 04d192e6..241d5127 100644 --- a/src/events/mineflayer/chat/guildChat.ts +++ b/src/events/mineflayer/chat/guild-chat.ts @@ -1,5 +1,5 @@ import { escapeMarkdown } from 'discord.js'; -import getRankColor from '@util/getRankColor'; +import getRankColor from '@util/get-rank-color'; export default { name: 'chat:guildChat', diff --git a/src/events/mineflayer/chat/guildLevelUp.ts b/src/events/mineflayer/chat/guild-level-up.ts similarity index 100% rename from src/events/mineflayer/chat/guildLevelUp.ts rename to src/events/mineflayer/chat/guild-level-up.ts diff --git a/src/events/mineflayer/chat/guildMuteUnmute.ts b/src/events/mineflayer/chat/guild-mute-unmute.ts similarity index 100% rename from src/events/mineflayer/chat/guildMuteUnmute.ts rename to src/events/mineflayer/chat/guild-mute-unmute.ts diff --git a/src/events/mineflayer/chat/joinLeave.ts b/src/events/mineflayer/chat/join-leave.ts similarity index 100% rename from src/events/mineflayer/chat/joinLeave.ts rename to src/events/mineflayer/chat/join-leave.ts diff --git a/src/events/mineflayer/chat/joinLimbo.ts b/src/events/mineflayer/chat/join-limbo.ts similarity index 100% rename from src/events/mineflayer/chat/joinLimbo.ts rename to src/events/mineflayer/chat/join-limbo.ts diff --git a/src/events/mineflayer/chat/joinRequest.ts b/src/events/mineflayer/chat/join-request.ts similarity index 77% rename from src/events/mineflayer/chat/joinRequest.ts rename to src/events/mineflayer/chat/join-request.ts index e1a64b0a..d2d230c4 100644 --- a/src/events/mineflayer/chat/joinRequest.ts +++ b/src/events/mineflayer/chat/join-request.ts @@ -1,7 +1,7 @@ -import fetchHypixelPlayerProfile from '@util/requests/fetchHypixelPlayerProfile'; -import fetchMojangProfile from '@util/requests/fetchMojangProfile'; -import isFetchError from '@util/requests/isFetchError'; -import isUserBlacklisted from '@util/blacklist/isUserBlacklisted'; +import fetchHypixelPlayerProfile from '@util/requests/fetch-hypixel-player-profile'; +import fetchMojangProfile from '@util/requests/fetch-mojan-profile'; +import isFetchError from '@util/requests/is-fetch-error'; +import isUserBlacklisted from '@util/blacklist/is-user-blacklisted'; export default { name: 'chat:joinRequest', diff --git a/src/events/mineflayer/chat/lobbyJoin.ts b/src/events/mineflayer/chat/lobby-join.ts similarity index 100% rename from src/events/mineflayer/chat/lobbyJoin.ts rename to src/events/mineflayer/chat/lobby-join.ts diff --git a/src/events/mineflayer/chat/memberCount.ts b/src/events/mineflayer/chat/member-count.ts similarity index 100% rename from src/events/mineflayer/chat/memberCount.ts rename to src/events/mineflayer/chat/member-count.ts diff --git a/src/events/mineflayer/chat/memberJoinLeave.ts b/src/events/mineflayer/chat/member-join-leave.ts similarity index 80% rename from src/events/mineflayer/chat/memberJoinLeave.ts rename to src/events/mineflayer/chat/member-join-leave.ts index 20835bdd..041fa4b0 100644 --- a/src/events/mineflayer/chat/memberJoinLeave.ts +++ b/src/events/mineflayer/chat/member-join-leave.ts @@ -1,9 +1,9 @@ import Emojis from '@util/emojis'; import { escapeMarkdown } from 'discord.js'; -import fetchMojangProfile from '@util/requests/fetchMojangProfile'; -import isFetchError from '@util/requests/isFetchError'; -import isUserBlacklisted from '@util/blacklist/isUserBlacklisted'; -import getRankColor from '@util/getRankColor'; +import fetchMojangProfile from '@util/requests/fetch-mojan-profile'; +import isFetchError from '@util/requests/is-fetch-error'; +import isUserBlacklisted from '@util/blacklist/is-user-blacklisted'; +import getRankColor from '@util/get-rank-color'; export default { name: 'chat:memberJoinLeave', diff --git a/src/events/mineflayer/chat/memberKick.ts b/src/events/mineflayer/chat/member-kick.ts similarity index 100% rename from src/events/mineflayer/chat/memberKick.ts rename to src/events/mineflayer/chat/member-kick.ts diff --git a/src/events/mineflayer/chat/promoteDemote.ts b/src/events/mineflayer/chat/promote-demote.ts similarity index 93% rename from src/events/mineflayer/chat/promoteDemote.ts rename to src/events/mineflayer/chat/promote-demote.ts index af642037..637b7d80 100644 --- a/src/events/mineflayer/chat/promoteDemote.ts +++ b/src/events/mineflayer/chat/promote-demote.ts @@ -1,6 +1,6 @@ import { escapeMarkdown } from 'discord.js'; import Emojis from '@util/emojis'; -import getRankColor from '@util/getRankColor'; +import getRankColor from '@util/get-rank-color'; export default { name: 'chat:promoteDemote', diff --git a/src/events/mineflayer/chat/questComplete.ts b/src/events/mineflayer/chat/quest-complete.ts similarity index 100% rename from src/events/mineflayer/chat/questComplete.ts rename to src/events/mineflayer/chat/quest-complete.ts diff --git a/src/events/mineflayer/chat/questTierComplete.ts b/src/events/mineflayer/chat/quest-tier-complete.ts similarity index 100% rename from src/events/mineflayer/chat/questTierComplete.ts rename to src/events/mineflayer/chat/quest-tier-complete.ts diff --git a/src/events/mineflayer/chat/sameMessageTwice.ts b/src/events/mineflayer/chat/same-message-twice.ts similarity index 100% rename from src/events/mineflayer/chat/sameMessageTwice.ts rename to src/events/mineflayer/chat/same-message-twice.ts diff --git a/src/events/mineflayer/chat/whisper.ts b/src/events/mineflayer/chat/whisper.ts index 1b5b6aeb..8c75d2b6 100644 --- a/src/events/mineflayer/chat/whisper.ts +++ b/src/events/mineflayer/chat/whisper.ts @@ -1,6 +1,6 @@ -import fetchHypixelGuild from '@util/requests/fetchHypixelGuild'; -import fetchMojangProfile from '@util/requests/fetchMojangProfile'; -import isFetchError from '@util/requests/isFetchError'; +import fetchHypixelGuild from '@util/requests/fetch-hypixel-guild'; +import fetchMojangProfile from '@util/requests/fetch-mojan-profile'; +import isFetchError from '@util/requests/is-fetch-error'; export default { name: 'chat:whisper', diff --git a/src/index.ts b/src/index.ts index 1efd486c..774ac565 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import { config } from 'dotenv'; -import Bot from '@classes/Bot'; +import Bot from '@classes/bot'; config(); diff --git a/src/util/blacklist/isUserBlacklisted.ts b/src/util/blacklist/is-user-blacklisted.ts similarity index 100% rename from src/util/blacklist/isUserBlacklisted.ts rename to src/util/blacklist/is-user-blacklisted.ts diff --git a/src/util/capitaliseString.ts b/src/util/capitalise-string.ts similarity index 100% rename from src/util/capitaliseString.ts rename to src/util/capitalise-string.ts diff --git a/src/util/getRankColor.ts b/src/util/get-rank-color.ts similarity index 100% rename from src/util/getRankColor.ts rename to src/util/get-rank-color.ts diff --git a/src/util/isObjKey.ts b/src/util/is-obj-key.ts similarity index 100% rename from src/util/isObjKey.ts rename to src/util/is-obj-key.ts diff --git a/src/util/logError.ts b/src/util/log-error.ts similarity index 100% rename from src/util/logError.ts rename to src/util/log-error.ts diff --git a/src/util/recursiveWalkDir.ts b/src/util/recursive-walk-dir.ts similarity index 100% rename from src/util/recursiveWalkDir.ts rename to src/util/recursive-walk-dir.ts diff --git a/src/util/requests/fetchErrorEmbed.ts b/src/util/requests/fetch-error-embed.ts similarity index 100% rename from src/util/requests/fetchErrorEmbed.ts rename to src/util/requests/fetch-error-embed.ts diff --git a/src/util/requests/FetchError.d.ts b/src/util/requests/fetch-error.d.ts similarity index 100% rename from src/util/requests/FetchError.d.ts rename to src/util/requests/fetch-error.d.ts diff --git a/src/util/requests/fetchHypixelGuild.ts b/src/util/requests/fetch-hypixel-guild.ts similarity index 100% rename from src/util/requests/fetchHypixelGuild.ts rename to src/util/requests/fetch-hypixel-guild.ts diff --git a/src/util/requests/fetchHypixelPlayerProfile.ts b/src/util/requests/fetch-hypixel-player-profile.ts similarity index 100% rename from src/util/requests/fetchHypixelPlayerProfile.ts rename to src/util/requests/fetch-hypixel-player-profile.ts diff --git a/src/util/requests/fetchMojangProfile.ts b/src/util/requests/fetch-mojan-profile.ts similarity index 100% rename from src/util/requests/fetchMojangProfile.ts rename to src/util/requests/fetch-mojan-profile.ts diff --git a/src/util/requests/isFetchError.ts b/src/util/requests/is-fetch-error.ts similarity index 100% rename from src/util/requests/isFetchError.ts rename to src/util/requests/is-fetch-error.ts diff --git a/src/util/writeToJsonFile.ts b/src/util/write-to-json-file.ts similarity index 97% rename from src/util/writeToJsonFile.ts rename to src/util/write-to-json-file.ts index 6be14b92..69e5fd91 100644 --- a/src/util/writeToJsonFile.ts +++ b/src/util/write-to-json-file.ts @@ -1,6 +1,6 @@ import { CommandInteraction, EmbedBuilder } from 'discord.js'; import { writeFile } from 'fs'; -import logError from './logError'; +import logError from './log-error'; /** * @param path The path to the target file. Path must begin from the path root. From 3b608f01cafdc67263e7973153b8ac8afe6f0a06 Mon Sep 17 00:00:00 2001 From: John Doe <69335633+Jejebecarte@users.noreply.github.com> Date: Tue, 7 May 2024 17:58:55 +1000 Subject: [PATCH 7/8] fix: update git file casing of classes --- src/classes/{Bot.ts => bot.ts} | 0 src/classes/{Client.ts => client.ts} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/classes/{Bot.ts => bot.ts} (100%) rename src/classes/{Client.ts => client.ts} (100%) diff --git a/src/classes/Bot.ts b/src/classes/bot.ts similarity index 100% rename from src/classes/Bot.ts rename to src/classes/bot.ts diff --git a/src/classes/Client.ts b/src/classes/client.ts similarity index 100% rename from src/classes/Client.ts rename to src/classes/client.ts From a93a8fa3270f25e899bfbbcf033b2e38ce0e56dd Mon Sep 17 00:00:00 2001 From: John Doe <69335633+Jejebecarte@users.noreply.github.com> Date: Tue, 7 May 2024 18:32:56 +1000 Subject: [PATCH 8/8] style: format files --- src/classes/bot.ts | 408 +++++++++++++++++++++--------------------- src/classes/client.ts | 10 +- 2 files changed, 209 insertions(+), 209 deletions(-) diff --git a/src/classes/bot.ts b/src/classes/bot.ts index a787913e..3809ae90 100644 --- a/src/classes/bot.ts +++ b/src/classes/bot.ts @@ -1,204 +1,204 @@ -import { - ActivityType, - ColorResolvable, - EmbedBuilder, - IntentsBitField, - TextChannel, -} from 'discord.js'; -import { BotEvents, createBot } from 'mineflayer'; -import EventEmitter from 'events'; -import consola from 'consola'; -import isObjKey from '@util/is-obj-key'; -import logError from '@util/log-error'; -import path from 'path'; -import recursiveWalkDir from '@util/recursive-walk-dir'; -import regex from '@util/regex'; -import Discord from './client'; - -class Bot { - public readonly logger = consola; - - public memberChannel?: TextChannel; - public officerChannel?: TextChannel; - public readonly ignorePrefix = process.env.DISCORD_IGNORE_PREFIX ?? ')'; - public readonly chatSeparator = process.env.MINECRAFT_CHAT_SEPARATOR ?? '>'; - public readonly discord = new Discord({ - allowedMentions: { parse: ['users', 'roles'], repliedUser: true }, - intents: [ - IntentsBitField.Flags.Guilds, - IntentsBitField.Flags.GuildMessages, - IntentsBitField.Flags.MessageContent, - ], - }); - - public onlineCount = 0; - public totalCount = 125; - public readonly mineflayer = createBot({ - username: process.env.MINECRAFT_EMAIL, - password: process.env.MINECRAFT_PASSWORD, - host: 'mc.hypixel.net', - auth: 'microsoft', - version: '1.16.4', - logErrors: true, - hideErrors: true, - checkTimeoutInterval: 30000, - defaultChatPatterns: false, - }); - - constructor() { - try { - this.start(); - } catch (error) { - this.logger.error(error); - } - } - - public async sendToDiscord( - channel: 'gc' | 'oc', - content: string, - color: ColorResolvable = 0x36393f, - padMessage = false - ) { - const embed = new EmbedBuilder() - .setDescription( - padMessage ? `${'-'.repeat(54)}\n${content}\n${'-'.repeat(54)}` : content - ) - .setColor(color); - - if (channel === 'gc') { - await this.memberChannel?.send({ embeds: [embed] }); - } else { - await this.officerChannel?.send({ embeds: [embed] }); - } - } - - public sendGuildMessage(channel: 'gc' | 'oc', message: string) { - this.executeCommand(`/${channel} ${message}`); - } - - public executeCommand(message: string) { - this.mineflayer.chat(message); - } - - public async executeTask(task: string) { - let listener: BotEvents['message']; - - await new Promise((resolve, reject) => { - listener = (message) => { - const str = message.toString(); - const motd = message.toMotd(); - const matches = motd.match(/^(.+)§c(.+)§r$/) ?? motd.match(/^§c(.+)$/); - - if (matches?.length && !str.toLowerCase().includes('limbo')) { - reject(str); - } - }; - - this.mineflayer.chat(task); - this.mineflayer.on('message', listener); - - setTimeout(() => { - resolve(undefined); - }, 300); - }).finally(() => { - this.mineflayer.removeListener('message', listener); - }); - } - - public sendToLimbo() { - this.executeCommand('§'); - } - - public setStatus() { - const plural = this.onlineCount - 1 !== 1; - - if (this.discord.isReady()) { - this.discord.user.setActivity( - `${this.onlineCount - 1} online player${plural ? 's' : ''}`, - { - type: ActivityType.Watching, - } - ); - } - } - - private async loadCommands(dir: string) { - const callback = async (currentDir: string, file: string) => { - if (!(file.endsWith('.ts') || file.endsWith('.js')) || file.endsWith('.d.ts')) return; - - const command = (await import(path.join(currentDir, file))).default as Command; - - if (!command.data) { - this.logger.warn(`The command ${path.join(currentDir, file)} doesn't have a name!`); - return; - } - - if (!command.run) { - this.logger.warn( - `The command ${command.data.name} doesn't have an executable function!` - ); - return; - } - - this.discord.commands.set(command.data.name, command); - }; - - await recursiveWalkDir( - path.join(__dirname, dir), - callback, - 'Error while loading commands:' - ); - } - - private async loadEvents(dir: string, emitter: EventEmitter) { - const callback = async (currentDir: string, file: string) => { - if (!(file.endsWith('.ts') || file.endsWith('.js')) || file.endsWith('.d.ts')) return; - - const { name, runOnce, run } = (await import(path.join(currentDir, file))) - .default as Event; - - if (!name) { - this.logger.warn(`The event ${path.join(currentDir, file)} doesn't have a name!`); - return; - } - - if (!run) { - this.logger.warn(`The event ${name} doesn't have an executable function!`); - return; - } - - if (isObjKey(name, regex)) { - this.mineflayer.addChatPattern(name.replace('chat:', ''), regex[name], { - repeat: true, - parse: true, - }); - } - - if (runOnce) { - emitter.once(name, run.bind(null, this)); - return; - } - - emitter.on(name, (...args) => { - run(this, ...args.flat(2)); - }); - }; - - await recursiveWalkDir(path.join(__dirname, dir), callback, 'Error while loading events:'); - } - - private async start() { - this.mineflayer.setMaxListeners(20); - await Promise.all([ - this.loadCommands('../commands'), - this.loadEvents('../events/discord', this.discord), - this.loadEvents('../events/mineflayer', this.mineflayer), - ]); - - await this.discord.login(process.env.DISCORD_TOKEN); - } -} - -process.on('uncaughtException', logError).on('unhandledRejection', logError); - -export default Bot; +import { + ActivityType, + ColorResolvable, + EmbedBuilder, + IntentsBitField, + TextChannel, +} from 'discord.js'; +import { BotEvents, createBot } from 'mineflayer'; +import EventEmitter from 'events'; +import consola from 'consola'; +import isObjKey from '@util/is-obj-key'; +import logError from '@util/log-error'; +import path from 'path'; +import recursiveWalkDir from '@util/recursive-walk-dir'; +import regex from '@util/regex'; +import Discord from './client'; + +class Bot { + public readonly logger = consola; + + public memberChannel?: TextChannel; + public officerChannel?: TextChannel; + public readonly ignorePrefix = process.env.DISCORD_IGNORE_PREFIX ?? ')'; + public readonly chatSeparator = process.env.MINECRAFT_CHAT_SEPARATOR ?? '>'; + public readonly discord = new Discord({ + allowedMentions: { parse: ['users', 'roles'], repliedUser: true }, + intents: [ + IntentsBitField.Flags.Guilds, + IntentsBitField.Flags.GuildMessages, + IntentsBitField.Flags.MessageContent, + ], + }); + + public onlineCount = 0; + public totalCount = 125; + public readonly mineflayer = createBot({ + username: process.env.MINECRAFT_EMAIL, + password: process.env.MINECRAFT_PASSWORD, + host: 'mc.hypixel.net', + auth: 'microsoft', + version: '1.16.4', + logErrors: true, + hideErrors: true, + checkTimeoutInterval: 30000, + defaultChatPatterns: false, + }); + + constructor() { + try { + this.start(); + } catch (error) { + this.logger.error(error); + } + } + + public async sendToDiscord( + channel: 'gc' | 'oc', + content: string, + color: ColorResolvable = 0x36393f, + padMessage = false + ) { + const embed = new EmbedBuilder() + .setDescription( + padMessage ? `${'-'.repeat(54)}\n${content}\n${'-'.repeat(54)}` : content + ) + .setColor(color); + + if (channel === 'gc') { + await this.memberChannel?.send({ embeds: [embed] }); + } else { + await this.officerChannel?.send({ embeds: [embed] }); + } + } + + public sendGuildMessage(channel: 'gc' | 'oc', message: string) { + this.executeCommand(`/${channel} ${message}`); + } + + public executeCommand(message: string) { + this.mineflayer.chat(message); + } + + public async executeTask(task: string) { + let listener: BotEvents['message']; + + await new Promise((resolve, reject) => { + listener = (message) => { + const str = message.toString(); + const motd = message.toMotd(); + const matches = motd.match(/^(.+)§c(.+)§r$/) ?? motd.match(/^§c(.+)$/); + + if (matches?.length && !str.toLowerCase().includes('limbo')) { + reject(str); + } + }; + + this.mineflayer.chat(task); + this.mineflayer.on('message', listener); + + setTimeout(() => { + resolve(undefined); + }, 300); + }).finally(() => { + this.mineflayer.removeListener('message', listener); + }); + } + + public sendToLimbo() { + this.executeCommand('§'); + } + + public setStatus() { + const plural = this.onlineCount - 1 !== 1; + + if (this.discord.isReady()) { + this.discord.user.setActivity( + `${this.onlineCount - 1} online player${plural ? 's' : ''}`, + { + type: ActivityType.Watching, + } + ); + } + } + + private async loadCommands(dir: string) { + const callback = async (currentDir: string, file: string) => { + if (!(file.endsWith('.ts') || file.endsWith('.js')) || file.endsWith('.d.ts')) return; + + const command = (await import(path.join(currentDir, file))).default as Command; + + if (!command.data) { + this.logger.warn(`The command ${path.join(currentDir, file)} doesn't have a name!`); + return; + } + + if (!command.run) { + this.logger.warn( + `The command ${command.data.name} doesn't have an executable function!` + ); + return; + } + + this.discord.commands.set(command.data.name, command); + }; + + await recursiveWalkDir( + path.join(__dirname, dir), + callback, + 'Error while loading commands:' + ); + } + + private async loadEvents(dir: string, emitter: EventEmitter) { + const callback = async (currentDir: string, file: string) => { + if (!(file.endsWith('.ts') || file.endsWith('.js')) || file.endsWith('.d.ts')) return; + + const { name, runOnce, run } = (await import(path.join(currentDir, file))) + .default as Event; + + if (!name) { + this.logger.warn(`The event ${path.join(currentDir, file)} doesn't have a name!`); + return; + } + + if (!run) { + this.logger.warn(`The event ${name} doesn't have an executable function!`); + return; + } + + if (isObjKey(name, regex)) { + this.mineflayer.addChatPattern(name.replace('chat:', ''), regex[name], { + repeat: true, + parse: true, + }); + } + + if (runOnce) { + emitter.once(name, run.bind(null, this)); + return; + } + + emitter.on(name, (...args) => { + run(this, ...args.flat(2)); + }); + }; + + await recursiveWalkDir(path.join(__dirname, dir), callback, 'Error while loading events:'); + } + + private async start() { + this.mineflayer.setMaxListeners(20); + await Promise.all([ + this.loadCommands('../commands'), + this.loadEvents('../events/discord', this.discord), + this.loadEvents('../events/mineflayer', this.mineflayer), + ]); + + await this.discord.login(process.env.DISCORD_TOKEN); + } +} + +process.on('uncaughtException', logError).on('unhandledRejection', logError); + +export default Bot; diff --git a/src/classes/client.ts b/src/classes/client.ts index d3b11b52..5d396c19 100644 --- a/src/classes/client.ts +++ b/src/classes/client.ts @@ -1,5 +1,5 @@ -import { Client, Collection } from 'discord.js'; - -export default class Discord extends Client { - public readonly commands: Collection = new Collection(); -} +import { Client, Collection } from 'discord.js'; + +export default class Discord extends Client { + public readonly commands: Collection = new Collection(); +}