From b5eb89561118e862354eb6f6d8e98a5bc4e3ce61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Sun, 4 Jun 2023 03:37:40 +0300 Subject: [PATCH 01/44] Bumb Version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb6d4af..42bad5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "eximiabots-radiox", - "version": "0.4.4", + "version": "0.5.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "eximiabots-radiox", - "version": "0.4.4", + "version": "0.5.0", "license": "MIT", "dependencies": { "@discordjs/builders": "^1.6.3", diff --git a/package.json b/package.json index 097f5bd..fbedd5a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eximiabots-radiox", - "version": "0.4.4", + "version": "0.5.0", "description": "Internet Radio to your Discord guild", "main": "index.js", "scripts": { From e87d952b96f4a1696befcf06987d50db57fd1070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Sun, 4 Jun 2023 03:42:02 +0300 Subject: [PATCH 02/44] Add version 0.5.x to security.md --- SECURITY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SECURITY.md b/SECURITY.md index eaabe9a..1ff3d4f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,6 +4,7 @@ | Version | Supported | | ------- | ------------------ | +| 0.5.x | :white_check_mark: | | 0.4.x | :white_check_mark: | | 0.3.x | :x: | | 0.2.x | :x: | From 4d18468e96e14c642426ee695d7c07bb5a5ae5e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Sun, 4 Jun 2023 03:43:39 +0300 Subject: [PATCH 03/44] Remove messageCreate event --- src/client/events/messageCreate.js | 62 ------------------------------ 1 file changed, 62 deletions(-) delete mode 100644 src/client/events/messageCreate.js diff --git a/src/client/events/messageCreate.js b/src/client/events/messageCreate.js deleted file mode 100644 index 54459e4..0000000 --- a/src/client/events/messageCreate.js +++ /dev/null @@ -1,62 +0,0 @@ -import { EmbedBuilder, PermissionFlagsBits } from "discord.js"; - -module.exports = { - name: 'messageCreate', - async execute(client, message) { - - if (message.author.bot || !message.guild) return; - let prefix = "rx$"; - if(client.user.username == "RadioX"){ - prefix = "rx>"; - } else if (client.user.username == "RadioX Beta"){ - prefix = "rx-"; - } else if (client.user.username == "RadioX Dev"){ - prefix = "rx$"; - } else if(message.mentions.members.first() && message.mentions.members.first().user.id === client.user.id){ - prefix = "<@!" + client.user.id + "> "; - } else { - return; - } - - const args = message.content.slice(prefix.length).split(' '); - if (!message.content.startsWith(prefix)) return; - if (!args[0]) return; - const commandName = args[0].toLowerCase(); - if (commandName === 'none') return; - const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); - if (!command && message.content !== `${prefix}`) return; - const permissions = message.channel.permissionsFor(message.client.user); - if (!permissions.has(PermissionFlagsBits.EmbedLinks)) return message.channel.send(client.messages.noPermsEmbed); - try { - let newMessage = {}; - - newMessage.messageCommandsDeprecatedTitle = client.messages.messageCommandsDeprecatedTitle.replace("%client.user.username%", client.user.username); - - const embed = new EmbedBuilder() - .setTitle(newMessage.messageCommandsDeprecatedTitle) - .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor) - .setDescription(client.messages.messageCommandsDeprecatedDescription) - .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') - .setFooter({ - text: client.messages.footerText, - iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') - }); - - let msg = await message.channel.send({ embeds: [embed] }); - - setTimeout(async function() { - try { - await msg.delete(); - } catch (DiscordAPIError) { - } - }, 30000); - } catch (error) { - message.reply({ - content: client.messages.runningCommandFailed, - ephemeral: true - }); - console.error(error); - } - } -} From 56f0ab5a40971dfd0eafdedbb63fba450d9d564e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Sun, 4 Jun 2023 04:07:41 +0300 Subject: [PATCH 04/44] TypeScript Initial --- src/Client.ts | 36 +++++++++---------- .../classes/{Datastore.js => Datastore.ts} | 0 src/client/classes/{Radio.js => Radio.ts} | 0 .../classes/{Stations.js => Stations.ts} | 0 .../classes/{Statistics.js => Statistics.ts} | 0 .../classes/{Streamer.js => Streamer.ts} | 2 +- src/client/{commands.js => commands.ts} | 2 +- src/client/commands/{bug.js => bug.ts} | 0 src/client/commands/{help.js => help.ts} | 0 src/client/commands/{invite.js => invite.ts} | 0 src/client/commands/{list.js => list.ts} | 0 .../{maintenance.js => maintenance.ts} | 2 +- src/client/commands/{next.js => next.ts} | 0 .../commands/{nowplaying.js => nowplaying.ts} | 0 src/client/commands/{play.js => play.ts} | 0 src/client/commands/{prev.js => prev.ts} | 0 .../commands/{statistics.js => statistics.ts} | 0 src/client/commands/{status.js => status.ts} | 0 src/client/commands/{stop.js => stop.ts} | 0 src/client/{emojis.js => emojis.ts} | 0 src/client/events/{SIGINT.js => SIGINT.ts} | 0 src/client/events/{SIGTERM.js => SIGTERM.ts} | 0 ...eractionCreate.js => interactionCreate.ts} | 0 .../{messageDelete.js => messageDelete.ts} | 0 src/client/events/{ready.js => ready.ts} | 10 +++--- ...aughtException.js => uncaughtException.ts} | 0 ...oiceStateUpdate.js => voiceStateUpdate.ts} | 0 src/client/events/{warning.js => warning.ts} | 0 src/client/funcs/{check.js => check.ts} | 0 src/client/funcs/{isDev.js => isDev.ts} | 0 .../{listStations.js => listStations.ts} | 0 .../funcs/{loadState.js => loadState.ts} | 0 src/client/funcs/{logger.js => logger.ts} | 0 src/client/funcs/{msToTime.js => msToTime.ts} | 0 src/client/funcs/{play.js => play.ts} | 0 .../funcs/{saveState.js => saveState.ts} | 0 src/client/{messages.js => messages.ts} | 2 -- src/{config.js => config.ts} | 0 src/{index.js => index.ts} | 0 39 files changed, 24 insertions(+), 30 deletions(-) rename src/client/classes/{Datastore.js => Datastore.ts} (100%) rename src/client/classes/{Radio.js => Radio.ts} (100%) rename src/client/classes/{Stations.js => Stations.ts} (100%) rename src/client/classes/{Statistics.js => Statistics.ts} (100%) rename src/client/classes/{Streamer.js => Streamer.ts} (98%) rename src/client/{commands.js => commands.ts} (98%) rename src/client/commands/{bug.js => bug.ts} (100%) rename src/client/commands/{help.js => help.ts} (100%) rename src/client/commands/{invite.js => invite.ts} (100%) rename src/client/commands/{list.js => list.ts} (100%) rename src/client/commands/{maintenance.js => maintenance.ts} (99%) rename src/client/commands/{next.js => next.ts} (100%) rename src/client/commands/{nowplaying.js => nowplaying.ts} (100%) rename src/client/commands/{play.js => play.ts} (100%) rename src/client/commands/{prev.js => prev.ts} (100%) rename src/client/commands/{statistics.js => statistics.ts} (100%) rename src/client/commands/{status.js => status.ts} (100%) rename src/client/commands/{stop.js => stop.ts} (100%) rename src/client/{emojis.js => emojis.ts} (100%) rename src/client/events/{SIGINT.js => SIGINT.ts} (100%) rename src/client/events/{SIGTERM.js => SIGTERM.ts} (100%) rename src/client/events/{interactionCreate.js => interactionCreate.ts} (100%) rename src/client/events/{messageDelete.js => messageDelete.ts} (100%) rename src/client/events/{ready.js => ready.ts} (91%) rename src/client/events/{uncaughtException.js => uncaughtException.ts} (100%) rename src/client/events/{voiceStateUpdate.js => voiceStateUpdate.ts} (100%) rename src/client/events/{warning.js => warning.ts} (100%) rename src/client/funcs/{check.js => check.ts} (100%) rename src/client/funcs/{isDev.js => isDev.ts} (100%) rename src/client/funcs/{listStations.js => listStations.ts} (100%) rename src/client/funcs/{loadState.js => loadState.ts} (100%) rename src/client/funcs/{logger.js => logger.ts} (100%) rename src/client/funcs/{msToTime.js => msToTime.ts} (100%) rename src/client/funcs/{play.js => play.ts} (100%) rename src/client/funcs/{saveState.js => saveState.ts} (100%) rename src/client/{messages.js => messages.ts} (75%) rename src/{config.js => config.ts} (100%) rename src/{index.js => index.ts} (100%) diff --git a/src/Client.ts b/src/Client.ts index 18a83b5..b7240f9 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -1,13 +1,13 @@ import { Client, Collection, IntentsBitField } from "discord.js"; -import Datastore from "./client/classes/Datastore.js"; -import Radio from "./client/classes/Radio.js"; -import Stations from "./client/classes/Stations.js"; -import Streamer from "./client/classes/Streamer.js"; -import Statistics from "./client/classes/Statistics.js"; +import Datastore from "./client/classes/Datastore"; +import Radio from "./client/classes/Radio"; +import Stations from "./client/classes/Stations"; +import Streamer from "./client/classes/Streamer"; +import Statistics from "./client/classes/Statistics; import fs from "fs"; -import { command, radio } from "./client/utils/typings.js"; -import config from "./config.js"; -import messages from "./client/messages.js"; +import { command, radio } from "./client/utils/typings"; +import config from "./config"; +import messages from "./client/messages"; import path from "path"; const events = "./client/events/"; @@ -41,14 +41,14 @@ class RadioClient extends Client { this.radio = null; this.funcs = {}; - this.funcs.check = require("./client/funcs/check.js"); - this.funcs.isDev = require("./client/funcs/isDev.js"); - this.funcs.logger = require("./client/funcs/logger.js"); - this.funcs.msToTime = require("./client/funcs/msToTime.js"); - this.funcs.saveState = require("./client/funcs/saveState.js"); - this.funcs.loadState = require("./client/funcs/loadState.js"); - this.funcs.play = require("./client/funcs/play.js"); - this.funcs.listStations = require("./client/funcs/listStations.js"); + this.funcs.check = require("./client/funcs/check"); + this.funcs.isDev = require("./client/funcs/isDev"); + this.funcs.logger = require("./client/funcs/logger"); + this.funcs.msToTime = require("./client/funcs/msToTime"); + this.funcs.saveState = require("./client/funcs/saveState"); + this.funcs.loadState = require("./client/funcs/loadState"); + this.funcs.play = require("./client/funcs/play"); + this.funcs.listStations = require("./client/funcs/listStations"); console.log('RadioX ' + this.config.version); console.log('Internet Radio to your Discord guild'); @@ -64,10 +64,6 @@ class RadioClient extends Client { require(`${events}ready`).execute(this); }); - this.on("messageCreate", msg => { - require(`${events}messageCreate`).execute(this, msg); - }); - this.on("messageDelete", msg => { require(`${events}messageDelete`).execute(this, msg); }); diff --git a/src/client/classes/Datastore.js b/src/client/classes/Datastore.ts similarity index 100% rename from src/client/classes/Datastore.js rename to src/client/classes/Datastore.ts diff --git a/src/client/classes/Radio.js b/src/client/classes/Radio.ts similarity index 100% rename from src/client/classes/Radio.js rename to src/client/classes/Radio.ts diff --git a/src/client/classes/Stations.js b/src/client/classes/Stations.ts similarity index 100% rename from src/client/classes/Stations.js rename to src/client/classes/Stations.ts diff --git a/src/client/classes/Statistics.js b/src/client/classes/Statistics.ts similarity index 100% rename from src/client/classes/Statistics.js rename to src/client/classes/Statistics.ts diff --git a/src/client/classes/Streamer.js b/src/client/classes/Streamer.ts similarity index 98% rename from src/client/classes/Streamer.js rename to src/client/classes/Streamer.ts index 3ed27de..68a849a 100644 --- a/src/client/classes/Streamer.js +++ b/src/client/classes/Streamer.ts @@ -9,7 +9,7 @@ module.exports = class { constructor() { this.map = new Map(); this.mode = null; - this.logger = require("../funcs/logger.js"); + this.logger = require("../funcs/logger"); } init(client){ diff --git a/src/client/commands.js b/src/client/commands.ts similarity index 98% rename from src/client/commands.js rename to src/client/commands.ts index 4eb46d9..7d2bff0 100644 --- a/src/client/commands.js +++ b/src/client/commands.ts @@ -8,7 +8,7 @@ module.exports = { async execute(client) { const commands = []; - const commandFiles = fs.readdirSync(path.join("./src/client/commands")).filter(f => f.endsWith(".js")); + const commandFiles = fs.readdirSync(path.join("./src/client/commands")).filter(f => f.endsWith(".ts")); for (const file of commandFiles) { const command = require(`./commands/${file}`); diff --git a/src/client/commands/bug.js b/src/client/commands/bug.ts similarity index 100% rename from src/client/commands/bug.js rename to src/client/commands/bug.ts diff --git a/src/client/commands/help.js b/src/client/commands/help.ts similarity index 100% rename from src/client/commands/help.js rename to src/client/commands/help.ts diff --git a/src/client/commands/invite.js b/src/client/commands/invite.ts similarity index 100% rename from src/client/commands/invite.js rename to src/client/commands/invite.ts diff --git a/src/client/commands/list.js b/src/client/commands/list.ts similarity index 100% rename from src/client/commands/list.js rename to src/client/commands/list.ts diff --git a/src/client/commands/maintenance.js b/src/client/commands/maintenance.ts similarity index 99% rename from src/client/commands/maintenance.js rename to src/client/commands/maintenance.ts index 3098cc0..d84b083 100644 --- a/src/client/commands/maintenance.js +++ b/src/client/commands/maintenance.ts @@ -1,5 +1,5 @@ import { ActionRowBuilder, EmbedBuilder, StringSelectMenuBuilder } from "discord.js"; -import Streamer from "../classes/Streamer.js"; +import Streamer from "../classes/Streamer"; const _importDynamic = new Function('modulePath', 'return import(modulePath)'); const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); diff --git a/src/client/commands/next.js b/src/client/commands/next.ts similarity index 100% rename from src/client/commands/next.js rename to src/client/commands/next.ts diff --git a/src/client/commands/nowplaying.js b/src/client/commands/nowplaying.ts similarity index 100% rename from src/client/commands/nowplaying.js rename to src/client/commands/nowplaying.ts diff --git a/src/client/commands/play.js b/src/client/commands/play.ts similarity index 100% rename from src/client/commands/play.js rename to src/client/commands/play.ts diff --git a/src/client/commands/prev.js b/src/client/commands/prev.ts similarity index 100% rename from src/client/commands/prev.js rename to src/client/commands/prev.ts diff --git a/src/client/commands/statistics.js b/src/client/commands/statistics.ts similarity index 100% rename from src/client/commands/statistics.js rename to src/client/commands/statistics.ts diff --git a/src/client/commands/status.js b/src/client/commands/status.ts similarity index 100% rename from src/client/commands/status.js rename to src/client/commands/status.ts diff --git a/src/client/commands/stop.js b/src/client/commands/stop.ts similarity index 100% rename from src/client/commands/stop.js rename to src/client/commands/stop.ts diff --git a/src/client/emojis.js b/src/client/emojis.ts similarity index 100% rename from src/client/emojis.js rename to src/client/emojis.ts diff --git a/src/client/events/SIGINT.js b/src/client/events/SIGINT.ts similarity index 100% rename from src/client/events/SIGINT.js rename to src/client/events/SIGINT.ts diff --git a/src/client/events/SIGTERM.js b/src/client/events/SIGTERM.ts similarity index 100% rename from src/client/events/SIGTERM.js rename to src/client/events/SIGTERM.ts diff --git a/src/client/events/interactionCreate.js b/src/client/events/interactionCreate.ts similarity index 100% rename from src/client/events/interactionCreate.js rename to src/client/events/interactionCreate.ts diff --git a/src/client/events/messageDelete.js b/src/client/events/messageDelete.ts similarity index 100% rename from src/client/events/messageDelete.js rename to src/client/events/messageDelete.ts diff --git a/src/client/events/ready.js b/src/client/events/ready.ts similarity index 91% rename from src/client/events/ready.js rename to src/client/events/ready.ts index 1b58d91..d4a2d5b 100644 --- a/src/client/events/ready.js +++ b/src/client/events/ready.ts @@ -1,8 +1,8 @@ -import Datastore from "../classes/Datastore.js"; -import Radio from "../classes/Radio.js"; -import Stations from "../classes/Stations.js"; -import Streamer from "../classes/Streamer.js"; -import Statistics from "../classes/Statistics.js"; +import Datastore from "../classes/Datastore"; +import Radio from "../classes/Radio"; +import Stations from "../classes/Stations"; +import Streamer from "../classes/Streamer"; +import Statistics from "../classes/Statistics"; module.exports = { name: 'ready', diff --git a/src/client/events/uncaughtException.js b/src/client/events/uncaughtException.ts similarity index 100% rename from src/client/events/uncaughtException.js rename to src/client/events/uncaughtException.ts diff --git a/src/client/events/voiceStateUpdate.js b/src/client/events/voiceStateUpdate.ts similarity index 100% rename from src/client/events/voiceStateUpdate.js rename to src/client/events/voiceStateUpdate.ts diff --git a/src/client/events/warning.js b/src/client/events/warning.ts similarity index 100% rename from src/client/events/warning.js rename to src/client/events/warning.ts diff --git a/src/client/funcs/check.js b/src/client/funcs/check.ts similarity index 100% rename from src/client/funcs/check.js rename to src/client/funcs/check.ts diff --git a/src/client/funcs/isDev.js b/src/client/funcs/isDev.ts similarity index 100% rename from src/client/funcs/isDev.js rename to src/client/funcs/isDev.ts diff --git a/src/client/funcs/listStations.js b/src/client/funcs/listStations.ts similarity index 100% rename from src/client/funcs/listStations.js rename to src/client/funcs/listStations.ts diff --git a/src/client/funcs/loadState.js b/src/client/funcs/loadState.ts similarity index 100% rename from src/client/funcs/loadState.js rename to src/client/funcs/loadState.ts diff --git a/src/client/funcs/logger.js b/src/client/funcs/logger.ts similarity index 100% rename from src/client/funcs/logger.js rename to src/client/funcs/logger.ts diff --git a/src/client/funcs/msToTime.js b/src/client/funcs/msToTime.ts similarity index 100% rename from src/client/funcs/msToTime.js rename to src/client/funcs/msToTime.ts diff --git a/src/client/funcs/play.js b/src/client/funcs/play.ts similarity index 100% rename from src/client/funcs/play.js rename to src/client/funcs/play.ts diff --git a/src/client/funcs/saveState.js b/src/client/funcs/saveState.ts similarity index 100% rename from src/client/funcs/saveState.js rename to src/client/funcs/saveState.ts diff --git a/src/client/messages.js b/src/client/messages.ts similarity index 75% rename from src/client/messages.js rename to src/client/messages.ts index b50f160..7352e8e 100644 --- a/src/client/messages.js +++ b/src/client/messages.ts @@ -35,7 +35,5 @@ module.exports = { statusField4: ":hourglass: Latency", statusField5: ":globe_with_meridians: Hosted by", errorStationURL: "Station can't be URL", - messageCommandsDeprecatedTitle: "%client.user.username%", - messageCommandsDeprecatedDescription: "We recommend you to reauthorize our bot by clicking the invite link down below, because Discord is planning to remove message content from verified bots [Read More](https://support-dev.discord.com/hc/en-us/articles/4404772028055)" + "\n\n" + "**Invite Bot**" + "\n" + "https://wgi.fi/radiox_invite" + "\n\n" + "This bot now supports slash commands, you should start using them instead. Type / into the message box and select the bot you wish to use. Remember to be careful as there are a few bugs here and there on Discord." + "\n\n" + "We will remove this deprecation message in March of 2022 when RadioX 1.0.0 is released.", maintenance: "Shhhh... We are now sleeping and dreaming about new features to implement. Will be back soon." }; diff --git a/src/config.js b/src/config.ts similarity index 100% rename from src/config.js rename to src/config.ts diff --git a/src/index.js b/src/index.ts similarity index 100% rename from src/index.js rename to src/index.ts From 9303c4fcc969fa9feca59a051cf8954f1d9444ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Sun, 4 Jun 2023 04:29:42 +0300 Subject: [PATCH 05/44] Export modules in typescript --- src/Client.ts | 2 +- src/client/classes/Datastore.ts | 2 +- src/client/classes/Radio.ts | 2 +- src/client/classes/Stations.ts | 2 +- src/client/classes/Statistics.ts | 2 +- src/client/classes/Streamer.ts | 2 +- src/client/commands.ts | 2 +- src/client/commands/bug.ts | 2 +- src/client/commands/help.ts | 2 +- src/client/commands/invite.ts | 2 +- src/client/commands/list.ts | 2 +- src/client/commands/maintenance.ts | 2 +- src/client/commands/next.ts | 2 +- src/client/commands/nowplaying.ts | 2 +- src/client/commands/play.ts | 2 +- src/client/commands/prev.ts | 2 +- src/client/commands/statistics.ts | 2 +- src/client/commands/status.ts | 2 +- src/client/commands/stop.ts | 2 +- src/client/emojis.ts | 2 +- src/client/events/SIGINT.ts | 2 +- src/client/events/SIGTERM.ts | 2 +- src/client/events/interactionCreate.ts | 2 +- src/client/events/messageDelete.ts | 2 +- src/client/events/ready.ts | 2 +- src/client/events/uncaughtException.ts | 2 +- src/client/events/voiceStateUpdate.ts | 2 +- src/client/events/warning.ts | 2 +- src/client/funcs/check.ts | 2 +- src/client/funcs/isDev.ts | 2 +- src/client/funcs/listStations.ts | 2 +- src/client/funcs/loadState.ts | 2 +- src/client/funcs/logger.ts | 2 +- src/client/funcs/msToTime.ts | 2 +- src/client/funcs/play.ts | 2 +- src/client/funcs/saveState.ts | 2 +- src/client/messages.ts | 2 +- src/config.ts | 2 +- 38 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index b7240f9..cf4ad7c 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -3,7 +3,7 @@ import Datastore from "./client/classes/Datastore"; import Radio from "./client/classes/Radio"; import Stations from "./client/classes/Stations"; import Streamer from "./client/classes/Streamer"; -import Statistics from "./client/classes/Statistics; +import Statistics from "./client/classes/Statistics"; import fs from "fs"; import { command, radio } from "./client/utils/typings"; import config from "./config"; diff --git a/src/client/classes/Datastore.ts b/src/client/classes/Datastore.ts index bf0ce66..60fa3bc 100644 --- a/src/client/classes/Datastore.ts +++ b/src/client/classes/Datastore.ts @@ -1,7 +1,7 @@ const fs = require('fs'); const path = require('path'); -module.exports = class { +export default class { constructor() { this.map = new Map(); this.loadData(); diff --git a/src/client/classes/Radio.ts b/src/client/classes/Radio.ts index 7990782..e4f13d9 100644 --- a/src/client/classes/Radio.ts +++ b/src/client/classes/Radio.ts @@ -3,7 +3,7 @@ const { joinVoiceChannel } = require("@discordjs/voice"); -module.exports = class Radio extends Map { +export default class Radio extends Map { constructor() { super(); } diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index 67d67c5..11d402d 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -1,7 +1,7 @@ const _importDynamic = new Function('modulePath', 'return import(modulePath)'); const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); -module.exports = class Stations extends Array { +export default class Stations extends Array { constructor() { super(); this.logger = require("../funcs/logger.js"); diff --git a/src/client/classes/Statistics.ts b/src/client/classes/Statistics.ts index 78bfac5..d78cc9b 100644 --- a/src/client/classes/Statistics.ts +++ b/src/client/classes/Statistics.ts @@ -1,4 +1,4 @@ -module.exports = class { +export default class Statistics { constructor() { this.map = new Map(); } diff --git a/src/client/classes/Streamer.ts b/src/client/classes/Streamer.ts index 68a849a..f1b1971 100644 --- a/src/client/classes/Streamer.ts +++ b/src/client/classes/Streamer.ts @@ -5,7 +5,7 @@ const { NoSubscriberBehavior } = require("@discordjs/voice"); -module.exports = class { +export default class Streamer { constructor() { this.map = new Map(); this.mode = null; diff --git a/src/client/commands.ts b/src/client/commands.ts index 7d2bff0..9074d1b 100644 --- a/src/client/commands.ts +++ b/src/client/commands.ts @@ -4,7 +4,7 @@ const { Routes } = require('discord-api-types/v9'); const fs = require('fs'); const path = require ('path'); -module.exports = { +export default { async execute(client) { const commands = []; diff --git a/src/client/commands/bug.ts b/src/client/commands/bug.ts index 87bac4a..0fadce8 100644 --- a/src/client/commands/bug.ts +++ b/src/client/commands/bug.ts @@ -1,6 +1,6 @@ import { EmbedBuilder } from "discord.js"; -module.exports = { +export default { name: 'bug', description: 'Report a bug', category: 'info', diff --git a/src/client/commands/help.ts b/src/client/commands/help.ts index 8c96388..10c0f3d 100644 --- a/src/client/commands/help.ts +++ b/src/client/commands/help.ts @@ -1,6 +1,6 @@ import { EmbedBuilder } from "discord.js"; -module.exports = { +export default { name: 'help', description: 'Get help using bot', category: 'info', diff --git a/src/client/commands/invite.ts b/src/client/commands/invite.ts index d1bc453..5754dd7 100644 --- a/src/client/commands/invite.ts +++ b/src/client/commands/invite.ts @@ -1,6 +1,6 @@ import { EmbedBuilder } from "discord.js"; -module.exports = { +export default { name: 'invite', description: 'Invite Bot', category: 'info', diff --git a/src/client/commands/list.ts b/src/client/commands/list.ts index 50378c1..7a07c05 100644 --- a/src/client/commands/list.ts +++ b/src/client/commands/list.ts @@ -1,6 +1,6 @@ import { EmbedBuilder } from "discord.js"; -module.exports = { +export default { name: 'list', description: 'List radio stations', category: 'radio', diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index d84b083..b105ff4 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -3,7 +3,7 @@ import Streamer from "../classes/Streamer"; const _importDynamic = new Function('modulePath', 'return import(modulePath)'); const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); -module.exports = { +export default { name: 'maintenance', description: 'Bot Maintenance', category: 'info', diff --git a/src/client/commands/next.ts b/src/client/commands/next.ts index 268752a..173f6ba 100644 --- a/src/client/commands/next.ts +++ b/src/client/commands/next.ts @@ -1,4 +1,4 @@ -module.exports = { +export default { name: 'next', description: 'Next Station', category: 'radio', diff --git a/src/client/commands/nowplaying.ts b/src/client/commands/nowplaying.ts index 3b7b830..8b87161 100644 --- a/src/client/commands/nowplaying.ts +++ b/src/client/commands/nowplaying.ts @@ -1,6 +1,6 @@ import { EmbedBuilder } from "discord.js"; -module.exports = { +export default { name: 'nowplaying', description: 'Current Radio Station', category: 'radio', diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index b1e816b..8a0bf2e 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -4,7 +4,7 @@ const { joinVoiceChannel } = require("@discordjs/voice"); -module.exports = { +export default { name: "play", usage: "", description: "Play radio", diff --git a/src/client/commands/prev.ts b/src/client/commands/prev.ts index d73093f..bb150f0 100644 --- a/src/client/commands/prev.ts +++ b/src/client/commands/prev.ts @@ -1,4 +1,4 @@ -module.exports = { +export default { name: 'prev', description: 'Previous Station', category: 'radio', diff --git a/src/client/commands/statistics.ts b/src/client/commands/statistics.ts index 00d3876..6fa7a2b 100644 --- a/src/client/commands/statistics.ts +++ b/src/client/commands/statistics.ts @@ -1,7 +1,7 @@ import { EmbedBuilder } from "discord.js"; -module.exports = { +export default { name: 'statistics', description: 'Show statistics', category: 'info', diff --git a/src/client/commands/status.ts b/src/client/commands/status.ts index 67e0ac6..ed81280 100644 --- a/src/client/commands/status.ts +++ b/src/client/commands/status.ts @@ -1,6 +1,6 @@ import { EmbedBuilder } from "discord.js"; -module.exports = { +export default { name: 'status', description: 'Bot Status', category: 'info', diff --git a/src/client/commands/stop.ts b/src/client/commands/stop.ts index 83516f0..5744bff 100644 --- a/src/client/commands/stop.ts +++ b/src/client/commands/stop.ts @@ -1,6 +1,6 @@ import { EmbedBuilder } from "discord.js"; -module.exports = { +export default { name: 'stop', description: 'Stop radio', category: 'radio', diff --git a/src/client/emojis.ts b/src/client/emojis.ts index 61af51a..1afa068 100644 --- a/src/client/emojis.ts +++ b/src/client/emojis.ts @@ -1,4 +1,4 @@ -module.exports = { +export default { name: 'emojis', async execute(client) { let customEmojis = { diff --git a/src/client/events/SIGINT.ts b/src/client/events/SIGINT.ts index b7f11f1..aa61eae 100644 --- a/src/client/events/SIGINT.ts +++ b/src/client/events/SIGINT.ts @@ -1,4 +1,4 @@ -module.exports = { +export default { name: 'SIGINT', execute(client) { client.user.setStatus('dnd'); diff --git a/src/client/events/SIGTERM.ts b/src/client/events/SIGTERM.ts index 62c4830..110e121 100644 --- a/src/client/events/SIGTERM.ts +++ b/src/client/events/SIGTERM.ts @@ -1,4 +1,4 @@ -module.exports = { +export default { name: 'SIGTERM', execute(client) { process.emit('SIGINT'); diff --git a/src/client/events/interactionCreate.ts b/src/client/events/interactionCreate.ts index b368e5f..a120811 100644 --- a/src/client/events/interactionCreate.ts +++ b/src/client/events/interactionCreate.ts @@ -1,6 +1,6 @@ import { PermissionFlagsBits } from "discord.js"; -module.exports = { +export default { name: 'interactionCreate', async execute(client, interaction) { diff --git a/src/client/events/messageDelete.ts b/src/client/events/messageDelete.ts index 01d3431..2837404 100644 --- a/src/client/events/messageDelete.ts +++ b/src/client/events/messageDelete.ts @@ -1,4 +1,4 @@ -module.exports = { +export default { name: 'messageDelete', async execute(client, msg) { if(!msg.author.bot || !msg.guild) return; diff --git a/src/client/events/ready.ts b/src/client/events/ready.ts index d4a2d5b..7666385 100644 --- a/src/client/events/ready.ts +++ b/src/client/events/ready.ts @@ -4,7 +4,7 @@ import Stations from "../classes/Stations"; import Streamer from "../classes/Streamer"; import Statistics from "../classes/Statistics"; -module.exports = { +export default { name: 'ready', async execute(client) { diff --git a/src/client/events/uncaughtException.ts b/src/client/events/uncaughtException.ts index e3c27e2..7d80b89 100644 --- a/src/client/events/uncaughtException.ts +++ b/src/client/events/uncaughtException.ts @@ -1,4 +1,4 @@ -module.exports = { +export default { name: 'uncaughtException', execute(client, error) { client.funcs.logger("Error"); diff --git a/src/client/events/voiceStateUpdate.ts b/src/client/events/voiceStateUpdate.ts index 09d7dc4..a301c27 100644 --- a/src/client/events/voiceStateUpdate.ts +++ b/src/client/events/voiceStateUpdate.ts @@ -4,7 +4,7 @@ const { joinVoiceChannel } = require("@discordjs/voice"); -module.exports = { +export default { name: "voiceStateUpdate", async execute(client, oldState, newState) { if (oldState.channel === null) return; diff --git a/src/client/events/warning.ts b/src/client/events/warning.ts index 537c089..93031ca 100644 --- a/src/client/events/warning.ts +++ b/src/client/events/warning.ts @@ -1,4 +1,4 @@ -module.exports = { +export default { name: 'warning', execute(client, warning) { if(warning.name == "ExperimentalWarning" && warning.message.startsWith("stream/web")) return; diff --git a/src/client/funcs/check.ts b/src/client/funcs/check.ts index 8a7c153..ff6429b 100644 --- a/src/client/funcs/check.ts +++ b/src/client/funcs/check.ts @@ -1,4 +1,4 @@ -module.exports = function check(client, interaction, command) { +export default function check(client, interaction, command) { let message = {}; const radio = client.radio.get(interaction.guild.id); if(client.config.maintenanceMode){ diff --git a/src/client/funcs/isDev.ts b/src/client/funcs/isDev.ts index 8be3ac9..8106d65 100644 --- a/src/client/funcs/isDev.ts +++ b/src/client/funcs/isDev.ts @@ -1,4 +1,4 @@ -module.exports = function isDev(devList, authorID){ +export default function isDev(devList, authorID){ let response = false; Object.keys(devList).forEach(function(oneDev) { let devID = devList[oneDev]; diff --git a/src/client/funcs/listStations.ts b/src/client/funcs/listStations.ts index 94a5e94..829abf9 100644 --- a/src/client/funcs/listStations.ts +++ b/src/client/funcs/listStations.ts @@ -1,6 +1,6 @@ import { ActionRowBuilder, StringSelectMenuBuilder } from "discord.js"; -module.exports = function listStations(client, interaction){ +export default function listStations(client, interaction){ let stations = new Array(); let options = new Array(); diff --git a/src/client/funcs/loadState.ts b/src/client/funcs/loadState.ts index d56c275..2967d77 100644 --- a/src/client/funcs/loadState.ts +++ b/src/client/funcs/loadState.ts @@ -1,4 +1,4 @@ -module.exports = function loadState(client, guild){ +export default function loadState(client, guild){ let data = client.datastore.getEntry(guild.id); if(!data) return; let state; diff --git a/src/client/funcs/logger.ts b/src/client/funcs/logger.ts index ec39d1a..ec4b450 100644 --- a/src/client/funcs/logger.ts +++ b/src/client/funcs/logger.ts @@ -1,4 +1,4 @@ -module.exports = function logger(area, text){ +export default function logger(area, text){ let date = new Date(); console.log('[' + area + '] – ' + date.toISOString()); if(text) console.log(text + '\n'); diff --git a/src/client/funcs/msToTime.ts b/src/client/funcs/msToTime.ts index 07fdb9a..442ee95 100644 --- a/src/client/funcs/msToTime.ts +++ b/src/client/funcs/msToTime.ts @@ -1,4 +1,4 @@ -module.exports = function msToTime(duration) { +export default function msToTime(duration) { let seconds = Math.floor((duration / 1000) % 60), minutes = Math.floor((duration / (1000 * 60)) % 60), hours = Math.floor((duration / (1000 * 60 * 60)) % 24), diff --git a/src/client/funcs/play.ts b/src/client/funcs/play.ts index 83fc28a..f69596a 100644 --- a/src/client/funcs/play.ts +++ b/src/client/funcs/play.ts @@ -1,6 +1,6 @@ import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"; -module.exports = async function play(client, interaction, guild, station) { +export default async function play(client, interaction, guild, station) { let message = {}; const radio = client.radio.get(guild.id); const audioPlayer = client.streamer.listen(station); diff --git a/src/client/funcs/saveState.ts b/src/client/funcs/saveState.ts index 6ef476a..9814b55 100644 --- a/src/client/funcs/saveState.ts +++ b/src/client/funcs/saveState.ts @@ -1,4 +1,4 @@ -module.exports = function saveState(client, guild, radio){ +export default function saveState(client, guild, radio){ client.datastore.checkEntry(guild.id); let date = new Date(); diff --git a/src/client/messages.ts b/src/client/messages.ts index 7352e8e..979038e 100644 --- a/src/client/messages.ts +++ b/src/client/messages.ts @@ -1,4 +1,4 @@ -module.exports = { +export default { wrongVoiceChannel: "You need to be in the same voice channel as RadioX to use this command!", noPerms: "You need the %command.permission% permission to use this command!", notPlaying: "There is nothing playing!", diff --git a/src/config.ts b/src/config.ts index 668ae51..2bdc4ed 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,6 +1,6 @@ require('dotenv/config'); -module.exports = { +export default { //credentials token: process.env.DISCORD_TOKEN, From 3fc7337d0f67d8209641363f9ae696ba06d5d152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Sun, 4 Jun 2023 05:48:42 +0300 Subject: [PATCH 06/44] TypeScript types --- src/Client.ts | 8 ++------ src/client/classes/Datastore.ts | 19 +++++++++--------- src/client/classes/Radio.ts | 9 +++++---- src/client/classes/Stations.ts | 20 ++++++++++--------- src/client/classes/Statistics.ts | 12 ++++++++---- src/client/classes/Streamer.ts | 27 ++++++++++++++------------ src/client/commands.ts | 14 ++++++------- src/client/commands/bug.ts | 4 ++-- src/client/commands/help.ts | 8 ++++---- src/client/commands/invite.ts | 4 ++-- src/client/commands/list.ts | 6 +++--- src/client/commands/maintenance.ts | 16 +++++++-------- src/client/commands/next.ts | 4 ++-- src/client/commands/nowplaying.ts | 4 ++-- src/client/commands/play.ts | 7 ++++--- src/client/commands/prev.ts | 4 ++-- src/client/commands/statistics.ts | 4 ++-- src/client/commands/status.ts | 4 ++-- src/client/commands/stop.ts | 2 +- src/client/emojis.ts | 6 +++--- src/client/events/SIGINT.ts | 2 +- src/client/events/SIGTERM.ts | 2 +- src/client/events/interactionCreate.ts | 2 +- src/client/events/messageDelete.ts | 4 +++- src/client/events/ready.ts | 8 ++++---- src/client/events/uncaughtException.ts | 2 +- src/client/events/voiceStateUpdate.ts | 16 +++++++-------- src/client/events/warning.ts | 2 +- src/client/funcs/check.ts | 4 ++-- src/client/funcs/isDev.ts | 2 +- src/client/funcs/listStations.ts | 10 +++++----- src/client/funcs/loadState.ts | 4 +++- src/client/funcs/logger.ts | 2 +- src/client/funcs/msToTime.ts | 2 +- src/client/funcs/play.ts | 4 ++-- src/client/funcs/saveState.ts | 2 +- 36 files changed, 131 insertions(+), 119 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index cf4ad7c..7b5a4e1 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -4,11 +4,9 @@ import Radio from "./client/classes/Radio"; import Stations from "./client/classes/Stations"; import Streamer from "./client/classes/Streamer"; import Statistics from "./client/classes/Statistics"; -import fs from "fs"; -import { command, radio } from "./client/utils/typings"; +import { command } from "./client/utils/typings"; import config from "./config"; import messages from "./client/messages"; -import path from "path"; const events = "./client/events/"; @@ -19,7 +17,7 @@ GatewayIntents.add( 1 << 9 // GUILD_MESSAGES ); -class RadioClient extends Client { +export default class RadioClient extends Client { readonly commands: Collection; public funcs: any; readonly config = config; @@ -109,5 +107,3 @@ class RadioClient extends Client { }); } } - -export default RadioClient diff --git a/src/client/classes/Datastore.ts b/src/client/classes/Datastore.ts index 60fa3bc..490e099 100644 --- a/src/client/classes/Datastore.ts +++ b/src/client/classes/Datastore.ts @@ -2,6 +2,7 @@ const fs = require('fs'); const path = require('path'); export default class { + map: Map; constructor() { this.map = new Map(); this.loadData(); @@ -27,7 +28,7 @@ export default class { //console.log(""); } - checkEntry(id){ + checkEntry(id: string){ this.loadEntry(id); if(!this.map.has(id)){ this.createEntry(id); @@ -37,8 +38,8 @@ export default class { } } - createEntry(id){ - let newData = {}; + createEntry(id: string){ + let newData: any = {}; newData.guild = {}; newData.guild.id = id; newData.statistics = {}; @@ -47,7 +48,7 @@ export default class { this.saveEntry(id, newData); } - loadEntry(id){ + loadEntry(id: any){ try { const json = require(`../../../datastore/` + id + '.json'); this.map.set(id, json); @@ -55,11 +56,11 @@ export default class { } } - getEntry(id){ + getEntry(id: string){ return this.map.get(id); } - updateEntry(guild, newData) { + updateEntry(guild: any, newData: any) { newData.guild.name = guild.name; let date = new Date(); @@ -70,7 +71,7 @@ export default class { //this.showEntry(this.getEntry(guild.id)); } - showEntry(data){ + showEntry(data : any){ console.log(data); } @@ -94,10 +95,10 @@ export default class { this.updateEntry(newData.guild, newData); } - saveEntry(file, data) { + saveEntry(file: string, data: any) { data = JSON.stringify(data, null, 4); - fs.writeFile(path.join(path.dirname(__dirname), '../../datastore') + "/" + file + ".json", data, 'utf8', function(err) { + fs.writeFile(path.join(path.dirname(__dirname), '../../datastore') + "/" + file + ".json", data, 'utf8', function(err: any) { if (err) { //console.log(err); } diff --git a/src/client/classes/Radio.ts b/src/client/classes/Radio.ts index e4f13d9..4004fd3 100644 --- a/src/client/classes/Radio.ts +++ b/src/client/classes/Radio.ts @@ -4,11 +4,12 @@ const { } = require("@discordjs/voice"); export default class Radio extends Map { + constructor() { super(); } - save(client) { + save(client: any) { let currentRadios = this.keys(); let radio = currentRadios.next(); @@ -29,16 +30,16 @@ export default class Radio extends Map { } } - restore(client, guilds) { + restore(client: any, guilds: any) { if(!client.stations) return; - guilds.forEach(async guild => { + guilds.forEach(async (guild: { id: any; }) => { let state = client.funcs.loadState(client, guild); if(!state) return; if(!state.station || !state.channels.voice || !state.channels.text) return; let voiceChannel = client.channels.cache.get(state.channels.voice); if(!voiceChannel) return; - if(voiceChannel.members.filter(member => !member.user.bot).size === 0) return; + if(voiceChannel.members.filter((member: { user: { bot: any; }; }) => !member.user.bot).size === 0) return; const sstation = await client.stations.search(state.station.name, "direct"); diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index 11d402d..e91343f 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -1,22 +1,24 @@ const _importDynamic = new Function('modulePath', 'return import(modulePath)'); -const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); +const fetch = (...args: any) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); export default class Stations extends Array { + logger: any; + constructor() { super(); this.logger = require("../funcs/logger.js"); } - async fetch(options){ + async fetch(options: any){ try { this.logger('Stations', 'Started fetching list – ' + options.url); let list = await fetch(options.url) .then(this.checkFetchStatus) - .then(response => response.json()); + .then((response: { json: () => any; }) => response.json()); if(list){ this.length = 0; - list.forEach(station => { + list.forEach((station: any) => { try { this.push(station); } catch (error) { @@ -25,12 +27,12 @@ export default class Stations extends Array { }); if(options.show){ - list.forEach(station => { + list.forEach((station: { name: any; }) => { this.logger('Stations', station.name); }); } - list.forEach(async station => { + list.forEach(async (station: { stream: { [x: string]: any; default: string | number; }; }) => { try { let stationTest = await fetch(station.stream[station.stream.default]); if(stationTest.ok === true) return; @@ -50,7 +52,7 @@ export default class Stations extends Array { } } - checkFetchStatus(response) { + checkFetchStatus(response: any) { if (response.ok) { // res.status >= 200 && res.status < 300 return response; } else { @@ -58,7 +60,7 @@ export default class Stations extends Array { } } - search(key, type) { + search(key: string, type: string) { if (this === null) return false; if (!key) return false; if (!type) return false; @@ -73,7 +75,7 @@ export default class Stations extends Array { return foundStation; } else { - let foundStations = []; + let foundStations : any[] = []; if (key == "radio") return false; this diff --git a/src/client/classes/Statistics.ts b/src/client/classes/Statistics.ts index d78cc9b..25e264c 100644 --- a/src/client/classes/Statistics.ts +++ b/src/client/classes/Statistics.ts @@ -1,9 +1,13 @@ +import { Guild } from "discord.js"; + export default class Statistics { + map: any; + constructor() { this.map = new Map(); } - update(client, guild, radio) { + update(client: any, guild: Guild, radio: any) { client.datastore.checkEntry(guild.id); @@ -26,13 +30,13 @@ export default class Statistics { this.calculateGlobal(client); } - calculateGlobal(client){ + calculateGlobal(client: any){ if(!client.stations) return; if(!client.datastore.map) return; let guilds = client.datastore.map.keys(); let stations = client.stations; - let statistics = {}; + let statistics : any = {}; if(!client.stations) return; @@ -59,7 +63,7 @@ export default class Statistics { calculation = guilds.next(); } - let newData = {}; + let newData : any = {}; newData.guild = {}; newData.guild.id = "global"; newData.guild.name = "global"; diff --git a/src/client/classes/Streamer.ts b/src/client/classes/Streamer.ts index f1b1971..4e5055a 100644 --- a/src/client/classes/Streamer.ts +++ b/src/client/classes/Streamer.ts @@ -1,18 +1,21 @@ const { createAudioPlayer, createAudioResource, - AudioPlayerStatus, NoSubscriberBehavior } = require("@discordjs/voice"); export default class Streamer { + map: any; + mode: any | null; + logger: any; + constructor() { this.map = new Map(); this.mode = null; this.logger = require("../funcs/logger"); } - init(client){ + init(client: any){ if(!client.config.streamerMode) return; switch(client.config.streamerMode){ @@ -29,24 +32,24 @@ export default class Streamer { if(this.mode == "auto"){ if(!client.stations) return; - client.stations.forEach(station => { + client.stations.forEach((station: any) => { this.play(station); }); } } - refresh(client){ + refresh(client: any){ this.init(client); let streamers = this.map.keys(); - streamers.forEach(streamer => { - if(client.stations.findIndex(station => station.name == streamer) == -1){ + streamers.forEach((streamer: any) => { + if(client.stations.findIndex((station: { name: any; }) => station.name == streamer) == -1){ this.stop(streamer); } }); } - play(station) { + play(station: any) { let audioPlayer = this.map.get(station.name); if(!audioPlayer) { if(this.mode == "auto"){ @@ -89,13 +92,13 @@ export default class Streamer { .on('autopaused', () => { this.logger('Streamer', station.name + " / " + "AutoPaused"); }) - .on('error', error => { + .on('error', (error: string) => { this.logger('Streamer', station.name + " / " + "Error" + "\n" + error); }); return audioPlayer; } - stop(station){ + stop(station: any){ let audioPlayer = this.map.get(station.name); if(audioPlayer){ this.logger('Streamer', station.name + " / " + "Stop"); @@ -105,15 +108,15 @@ export default class Streamer { this.map.delete(station.name); } - listen(station) { + listen(station: any) { let audioPlayer = this.map.get(station.name); if(!audioPlayer || this.mode == "manual" && audioPlayer.subscribers.length == 0) audioPlayer = this.play(station); return audioPlayer; } - leave(client) { + leave(client: any) { if(!client.stations) return; - client.stations.forEach(station => { + client.stations.forEach((station: any) => { this.stop(station); }); } diff --git a/src/client/commands.ts b/src/client/commands.ts index 9074d1b..fb7b4f8 100644 --- a/src/client/commands.ts +++ b/src/client/commands.ts @@ -5,10 +5,10 @@ const fs = require('fs'); const path = require ('path'); export default { - async execute(client) { + async execute(client: any) { - const commands = []; - const commandFiles = fs.readdirSync(path.join("./src/client/commands")).filter(f => f.endsWith(".ts")); + const commands : any[] = []; + const commandFiles = fs.readdirSync(path.join("./src/client/commands")).filter((f: string) => f.endsWith(".ts")); for (const file of commandFiles) { const command = require(`./commands/${file}`); @@ -20,7 +20,7 @@ export default { command.data = command.data.toJSON(); if(command.options) { - command.options.forEach(function(option) { + command.options.forEach(function(option: { type: string | number; }) { if(option.type == "STRING") option.type = 3; if(option.type == "NUMBER") option.type = 10; command.data.options.push(option); @@ -43,14 +43,14 @@ export default { ); let guilds = await client.guilds.fetch(); - guilds.forEach(async guild => { + guilds.forEach(async (guild: { id: string; name: string; }) => { try { await rest.put( Routes.applicationGuildCommands(client.user.id, guild.id), { body: commands } ); client.funcs.logger('Slash Commands', 'Guild Applications – Successful' + "\n" + guild.id + " / " + guild.name); - } catch (DiscordAPIError) { + } catch (DiscordAPIError: any) { client.funcs.logger('Slash Commands', 'Guild Applications – Failed' + "\n" + guild.id + " / " + guild.name); if(DiscordAPIError.name != "DiscordAPIError[50001]") console.error(DiscordAPIError.message + "\n\n"); } @@ -62,7 +62,7 @@ export default { ); let guilds = await client.guilds.fetch(); - guilds.forEach(async guild => { + guilds.forEach(async (guild: { id: any; }) => { try { await rest.put( Routes.applicationGuildCommands(client.user.id, guild.id), diff --git a/src/client/commands/bug.ts b/src/client/commands/bug.ts index 0fadce8..598f94b 100644 --- a/src/client/commands/bug.ts +++ b/src/client/commands/bug.ts @@ -4,8 +4,8 @@ export default { name: 'bug', description: 'Report a bug', category: 'info', - async execute(interaction, client) { - let message = {}; + async execute(interaction: any, client: any) { + let message : any = {}; message.bugTitle = client.messages.bugTitle.replace("%client.user.username%", client.user.username); message.bugDescription = client.messages.bugDescription.replace("%client.config.supportGuild%", client.config.supportGuild); diff --git a/src/client/commands/help.ts b/src/client/commands/help.ts index 10c0f3d..3db2606 100644 --- a/src/client/commands/help.ts +++ b/src/client/commands/help.ts @@ -4,16 +4,16 @@ export default { name: 'help', description: 'Get help using bot', category: 'info', - execute(interaction, client) { - let message = {}; + execute(interaction: any, client: any) { + let message: any = {}; - const categories = []; + const categories : any= []; for (let i = 0; i < client.commands.size; i++) { if (!categories.includes([...client.commands.values()][i].category)) categories.push([...client.commands.values()][i].category); } let commands = ''; for (let i = 0; i < categories.length; i++) { - commands += `**» ${categories[i].toUpperCase()}**\n${client.commands.filter(x => x.category === categories[i] && !x.omitFromHelp).map(x => `\`${x.name}\``).join(', ')}\n`; + commands += `**» ${categories[i].toUpperCase()}**\n${client.commands.filter(x => x.category === categories[i] && !x.omitFromHelp).map((x: { name: any; }) => `\`${x.name}\``).join(', ')}\n`; } message.helpTitle = client.messages.helpTitle.replace("%client.user.username%", client.user.username); diff --git a/src/client/commands/invite.ts b/src/client/commands/invite.ts index 5754dd7..dc3b847 100644 --- a/src/client/commands/invite.ts +++ b/src/client/commands/invite.ts @@ -4,8 +4,8 @@ export default { name: 'invite', description: 'Invite Bot', category: 'info', - execute(interaction, client) { - let message = {}; + execute(interaction: any, client: any) { + let message: any = {}; message.inviteTitle = client.messages.inviteTitle.replace("%client.user.username%", client.user.username); const embed = new EmbedBuilder() .setTitle(message.inviteTitle) diff --git a/src/client/commands/list.ts b/src/client/commands/list.ts index 7a07c05..ea31a02 100644 --- a/src/client/commands/list.ts +++ b/src/client/commands/list.ts @@ -4,8 +4,8 @@ export default { name: 'list', description: 'List radio stations', category: 'radio', - execute(interaction, client) { - let message = {}; + execute(interaction: any, client: any) { + let message: any = {}; if(!client.stations) { message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); @@ -20,7 +20,7 @@ export default { if(radio && !client.config.maintenanceMode){ client.funcs.listStations(client, interaction); } else { - let stations = `${client.stations.map(s => `**#** ${s.name}`).join('\n')}` + let stations = `${client.stations.map((s: { name: any; }) => `**#** ${s.name}`).join('\n')}` const hashs = stations.split('**#**').length; for (let i = 0; i < hashs; i++) { stations = stations.replace('**#**', `**${i + 1}.**`); diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index b105ff4..03ac808 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -1,21 +1,21 @@ import { ActionRowBuilder, EmbedBuilder, StringSelectMenuBuilder } from "discord.js"; import Streamer from "../classes/Streamer"; const _importDynamic = new Function('modulePath', 'return import(modulePath)'); -const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); +const fetch = (...args: any) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); export default { name: 'maintenance', description: 'Bot Maintenance', category: 'info', - async execute(interaction, client) { - let message = {}; + async execute(interaction: any, client: any) { + let message: any = {}; if(!client.funcs.isDev(client.config.devId, interaction.user.id)) return interaction.reply({ content: client.messageEmojis["error"] + client.messages.notAllowed, ephemeral: true }); let action = interaction.options?.getNumber("action") ?? interaction.values?.[0]; - const options = new Array( + const options: any = new Array( { emoji: "🌀", label: "Restart Bot", @@ -79,12 +79,12 @@ export default { }); } - client.funcs.logger('Maintenance', options.find(option => option.value == action).label); + client.funcs.logger('Maintenance', options.find((option: { value: any; }) => option.value == action).label); const embed = new EmbedBuilder() .setTitle(client.messages.maintenanceTitle) .setColor(client.config.embedColor) - .setDescription(options.find(option => option.value == action).label) + .setDescription(options.find((option: { value: any; }) => option.value == action).label) .setFooter({ text: client.messages.footerText, iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') @@ -163,7 +163,7 @@ export default { } if(!client.config.maintenanceMode){ - clearInterval(); + clearInterval(undefined); } }, 500); @@ -187,7 +187,7 @@ export default { } if(!client.config.maintenanceMode){ - clearInterval(); + clearInterval(undefined); } }, 500); diff --git a/src/client/commands/next.ts b/src/client/commands/next.ts index 173f6ba..a4f8662 100644 --- a/src/client/commands/next.ts +++ b/src/client/commands/next.ts @@ -2,11 +2,11 @@ export default { name: 'next', description: 'Next Station', category: 'radio', - async execute(interaction, client, command) { + async execute(interaction: any, client: any, command: any) { if (client.funcs.check(client, interaction, command)) { const radio = client.radio.get(interaction.guild.id); - let index = client.stations.findIndex(station => station.name == radio.station.name) + 1; + let index = client.stations.findIndex((station: { name: any; }) => station.name == radio.station.name) + 1; if(index == client.stations.length) index = 0; let station = client.stations[index]; diff --git a/src/client/commands/nowplaying.ts b/src/client/commands/nowplaying.ts index 8b87161..354ee03 100644 --- a/src/client/commands/nowplaying.ts +++ b/src/client/commands/nowplaying.ts @@ -4,9 +4,9 @@ export default { name: 'nowplaying', description: 'Current Radio Station', category: 'radio', - async execute(interaction, client, command) { + async execute(interaction: any, client: any, command: any) { if (client.funcs.check(client, interaction, command)) { - let message = {}; + let message: any = {}; const radio = client.radio.get(interaction.guild.id); let date = new Date(); diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index 8a0bf2e..7f23ee0 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -12,8 +12,8 @@ export default { { type: "STRING", name: "query", description: "Select station", required: false} ], category: "radio", - async execute(interaction, client) { - let message = {}; + async execute(interaction: any, client: any) { + let message: any = {}; if(client.config.maintenanceMode){ return interaction.reply({ @@ -119,7 +119,8 @@ export default { voiceChannel: voiceChannel, connection: null, message: null, - station: station + station: station, + startTime: number }; client.radio.set(interaction.guild.id, construct); diff --git a/src/client/commands/prev.ts b/src/client/commands/prev.ts index bb150f0..351854b 100644 --- a/src/client/commands/prev.ts +++ b/src/client/commands/prev.ts @@ -2,11 +2,11 @@ export default { name: 'prev', description: 'Previous Station', category: 'radio', - async execute(interaction, client, command) { + async execute(interaction: any, client: any, command: any) { if (client.funcs.check(client, interaction, command)) { const radio = client.radio.get(interaction.guild.id); - let index = client.stations.findIndex(station => station.name == radio.station.name) - 1; + let index = client.stations.findIndex((station: { name: any; }) => station.name == radio.station.name) - 1; if(index == -1) index = client.stations.length - 1; let station = client.stations[index]; diff --git a/src/client/commands/statistics.ts b/src/client/commands/statistics.ts index 6fa7a2b..1fe9090 100644 --- a/src/client/commands/statistics.ts +++ b/src/client/commands/statistics.ts @@ -5,8 +5,8 @@ export default { name: 'statistics', description: 'Show statistics', category: 'info', - execute(interaction, client) { - let message = {}; + execute(interaction: any, client: any) { + let message: any = {}; let stations = client.stations; let currentGuild = client.datastore.getEntry(interaction.guild.id); let global = client.datastore.getEntry("global"); diff --git a/src/client/commands/status.ts b/src/client/commands/status.ts index ed81280..6bdf562 100644 --- a/src/client/commands/status.ts +++ b/src/client/commands/status.ts @@ -4,8 +4,8 @@ export default { name: 'status', description: 'Bot Status', category: 'info', - async execute(interaction, client) { - let message = {}; + async execute(interaction: any, client: any) { + let message: any = {}; message.statusTitle = client.messages.statusTitle.replace("%client.user.username%", client.user.username); let uptime = client.funcs.msToTime(client.uptime); diff --git a/src/client/commands/stop.ts b/src/client/commands/stop.ts index 5744bff..a85e1d7 100644 --- a/src/client/commands/stop.ts +++ b/src/client/commands/stop.ts @@ -4,7 +4,7 @@ export default { name: 'stop', description: 'Stop radio', category: 'radio', - async execute(interaction, client, command) { + async execute(interaction: any, client: any, command: any) { if (client.funcs.check(client, interaction, command)) { const radio = client.radio.get(interaction.guild.id); client.statistics.update(client, interaction.guild, radio); diff --git a/src/client/emojis.ts b/src/client/emojis.ts index 1afa068..df5f0a0 100644 --- a/src/client/emojis.ts +++ b/src/client/emojis.ts @@ -1,7 +1,7 @@ export default { name: 'emojis', - async execute(client) { - let customEmojis = { + async execute(client: any): Promise { + let customEmojis: any = { logo: "<:RadioX:688765708808487072>", eximiabots: "<:EximiaBots:693277919929303132>", list: "<:RadioXList:688541155519889482>", @@ -14,7 +14,7 @@ export default { next: "<:RadioXNext:882153637474893834>" }; - let fallbackEmojis = { + let fallbackEmojis: any = { logo: "RadioX", eximiabots: "EximiaBots", list: "📜", diff --git a/src/client/events/SIGINT.ts b/src/client/events/SIGINT.ts index aa61eae..27ee4a3 100644 --- a/src/client/events/SIGINT.ts +++ b/src/client/events/SIGINT.ts @@ -1,6 +1,6 @@ export default { name: 'SIGINT', - execute(client) { + execute(client: any) { client.user.setStatus('dnd'); client.streamer.leave(client); diff --git a/src/client/events/SIGTERM.ts b/src/client/events/SIGTERM.ts index 110e121..911daf8 100644 --- a/src/client/events/SIGTERM.ts +++ b/src/client/events/SIGTERM.ts @@ -1,6 +1,6 @@ export default { name: 'SIGTERM', - execute(client) { + execute(client: any) { process.emit('SIGINT'); } } diff --git a/src/client/events/interactionCreate.ts b/src/client/events/interactionCreate.ts index a120811..ae15bbc 100644 --- a/src/client/events/interactionCreate.ts +++ b/src/client/events/interactionCreate.ts @@ -2,7 +2,7 @@ import { PermissionFlagsBits } from "discord.js"; export default { name: 'interactionCreate', - async execute(client, interaction) { + async execute(client: any, interaction: any) { const permissions = interaction.channel.permissionsFor(interaction.client.user); if (!permissions.has(PermissionFlagsBits.ViewChannel)) return; diff --git a/src/client/events/messageDelete.ts b/src/client/events/messageDelete.ts index 2837404..2b1b5b1 100644 --- a/src/client/events/messageDelete.ts +++ b/src/client/events/messageDelete.ts @@ -1,6 +1,8 @@ +import { Message } from "discord.js"; + export default { name: 'messageDelete', - async execute(client, msg) { + async execute(client: any, msg: Message) { if(!msg.author.bot || !msg.guild) return; const radio = client.radio.get(msg.guild.id); if(!radio) return; diff --git a/src/client/events/ready.ts b/src/client/events/ready.ts index 7666385..403ff64 100644 --- a/src/client/events/ready.ts +++ b/src/client/events/ready.ts @@ -6,7 +6,7 @@ import Statistics from "../classes/Statistics"; export default { name: 'ready', - async execute(client) { + async execute(client: any) { client.funcs.logger("Bot", "Ready"); @@ -14,7 +14,7 @@ export default { client.funcs.logger('Datastore', 'Initialize'); client.datastore = new Datastore(); - client.datastore.map.forEach(datastore => { + client.datastore.map.forEach((datastore: { guild: { id: string; name: string; }; }) => { client.funcs.logger('Datastore', datastore.guild.id + " / " + datastore.guild.name); }); @@ -22,7 +22,7 @@ export default { /*DEVELOPERS*/ client.developers = ""; - let user = ""; + let user : any= ""; for (let i = 0; i < client.config.devId.length; i++) { user = await client.users.fetch(client.config.devId[i]); client.funcs.logger('Developers', user.tag); @@ -59,7 +59,7 @@ export default { client.funcs.logger('Guilds', 'Started fetching list'); let guilds = await client.guilds.fetch(); - guilds.forEach(guild => { + guilds.forEach((guild: { id: string; name: string; }) => { client.funcs.logger('Guilds', guild.id + " / " + guild.name); }); diff --git a/src/client/events/uncaughtException.ts b/src/client/events/uncaughtException.ts index 7d80b89..2153077 100644 --- a/src/client/events/uncaughtException.ts +++ b/src/client/events/uncaughtException.ts @@ -1,6 +1,6 @@ export default { name: 'uncaughtException', - execute(client, error) { + execute(client: any, error: any) { client.funcs.logger("Error"); console.log(error.stack); console.log(''); diff --git a/src/client/events/voiceStateUpdate.ts b/src/client/events/voiceStateUpdate.ts index a301c27..4c4729a 100644 --- a/src/client/events/voiceStateUpdate.ts +++ b/src/client/events/voiceStateUpdate.ts @@ -1,4 +1,4 @@ -import { PermissionFlagsBits } from "discord.js"; +import { PermissionFlagsBits, VoiceState } from "discord.js"; const { getVoiceConnection, joinVoiceChannel @@ -6,13 +6,13 @@ const { export default { name: "voiceStateUpdate", - async execute(client, oldState, newState) { + async execute(client: any, oldState: VoiceState, newState: VoiceState) { if (oldState.channel === null) return; let change = false; const radio = client.radio?.get(newState.guild.id); if (!radio) return; - if (newState.member.id === client.user.id && oldState.member.id === client.user.id) { + if (newState.member?.id === client.user.id && oldState.member?.id === client.user.id) { if (newState.channel === null) { client.statistics.update(client, newState.guild, radio); @@ -23,14 +23,14 @@ export default { } const newPermissions = newState.channel.permissionsFor(newState.client.user); - if (!newPermissions.has(PermissionFlagsBits.Connect) || !newPermissions.has(PermissionFlagsBits.Speak) || !newPermissions.has(PermissionFlagsBits.ViewChannel)) { + if (!newPermissions?.has(PermissionFlagsBits.Connect) || !newPermissions?.has(PermissionFlagsBits.Speak) || !newPermissions?.has(PermissionFlagsBits.ViewChannel)) { try { setTimeout( async () => ( radio.connection = joinVoiceChannel({ - channelId: oldState.channel.id, - guildId: oldState.channel.guild.id, - adapterCreator: oldState.channel.guild.voiceAdapterCreator + channelId: oldState.channel?.id, + guildId: oldState.channel?.guild.id, + adapterCreator: oldState.channel?.guild.voiceAdapterCreator }) //radio.connection = await oldState.channel.join() ), @@ -55,7 +55,7 @@ export default { if ((oldState.channel.members.filter(member => !member.user.bot).size === 0 && oldState.channel === radio.voiceChannel) || change) { setTimeout(() => { if (!radio || !radio.connection || !radio.connection === null) return; - if (radio.voiceChannel.members.filter(member => !member.user.bot).size === 0) { + if (radio.voiceChannel.members.filter((member: { user: { bot: any; }; }) => !member.user.bot).size === 0) { client.statistics.update(client, newState.guild, radio); radio.connection?.destroy(); radio.message?.delete(); diff --git a/src/client/events/warning.ts b/src/client/events/warning.ts index 93031ca..a831895 100644 --- a/src/client/events/warning.ts +++ b/src/client/events/warning.ts @@ -1,6 +1,6 @@ export default { name: 'warning', - execute(client, warning) { + execute(client: any, warning: any) { if(warning.name == "ExperimentalWarning" && warning.message.startsWith("stream/web")) return; client.funcs.logger("Warning"); diff --git a/src/client/funcs/check.ts b/src/client/funcs/check.ts index ff6429b..c832d7f 100644 --- a/src/client/funcs/check.ts +++ b/src/client/funcs/check.ts @@ -1,5 +1,5 @@ -export default function check(client, interaction, command) { - let message = {}; +export default function check(client: any, interaction: any, command: any) { + let message: any = {}; const radio = client.radio.get(interaction.guild.id); if(client.config.maintenanceMode){ interaction.reply({ diff --git a/src/client/funcs/isDev.ts b/src/client/funcs/isDev.ts index 8106d65..5d54e06 100644 --- a/src/client/funcs/isDev.ts +++ b/src/client/funcs/isDev.ts @@ -1,4 +1,4 @@ -export default function isDev(devList, authorID){ +export default function isDev(devList : any, authorID : any){ let response = false; Object.keys(devList).forEach(function(oneDev) { let devID = devList[oneDev]; diff --git a/src/client/funcs/listStations.ts b/src/client/funcs/listStations.ts index 829abf9..0a51045 100644 --- a/src/client/funcs/listStations.ts +++ b/src/client/funcs/listStations.ts @@ -1,10 +1,10 @@ -import { ActionRowBuilder, StringSelectMenuBuilder } from "discord.js"; +import { ActionRowBuilder, Interaction, StringSelectMenuBuilder } from "discord.js"; -export default function listStations(client, interaction){ - let stations = new Array(); - let options = new Array(); +export default function listStations(client: any, interaction: any){ + let stations: any = new Array(); + let options: any = new Array(); - stations = client.stations.forEach(station => { + stations = client.stations.forEach((station: { name?: any; owner?: any; label?: any; description?: any; value?: any; }) => { if(station.name == "GrooveFM") return; station = { label: station.name, diff --git a/src/client/funcs/loadState.ts b/src/client/funcs/loadState.ts index 2967d77..9428bb8 100644 --- a/src/client/funcs/loadState.ts +++ b/src/client/funcs/loadState.ts @@ -1,4 +1,6 @@ -export default function loadState(client, guild){ +import { Guild } from "discord.js"; + +export default function loadState(client: any, guild: Guild){ let data = client.datastore.getEntry(guild.id); if(!data) return; let state; diff --git a/src/client/funcs/logger.ts b/src/client/funcs/logger.ts index ec4b450..17d8680 100644 --- a/src/client/funcs/logger.ts +++ b/src/client/funcs/logger.ts @@ -1,4 +1,4 @@ -export default function logger(area, text){ +export default function logger(area : string, text: string){ let date = new Date(); console.log('[' + area + '] – ' + date.toISOString()); if(text) console.log(text + '\n'); diff --git a/src/client/funcs/msToTime.ts b/src/client/funcs/msToTime.ts index 442ee95..fdb10b9 100644 --- a/src/client/funcs/msToTime.ts +++ b/src/client/funcs/msToTime.ts @@ -1,4 +1,4 @@ -export default function msToTime(duration) { +export default function msToTime(duration : number) { let seconds = Math.floor((duration / 1000) % 60), minutes = Math.floor((duration / (1000 * 60)) % 60), hours = Math.floor((duration / (1000 * 60 * 60)) % 24), diff --git a/src/client/funcs/play.ts b/src/client/funcs/play.ts index f69596a..899075e 100644 --- a/src/client/funcs/play.ts +++ b/src/client/funcs/play.ts @@ -1,7 +1,7 @@ import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"; -export default async function play(client, interaction, guild, station) { - let message = {}; +export default async function play(client: any, interaction: any, guild: any, station: any) { + let message: any = {}; const radio = client.radio.get(guild.id); const audioPlayer = client.streamer.listen(station); radio.connection.subscribe(audioPlayer); diff --git a/src/client/funcs/saveState.ts b/src/client/funcs/saveState.ts index 9814b55..4940866 100644 --- a/src/client/funcs/saveState.ts +++ b/src/client/funcs/saveState.ts @@ -1,4 +1,4 @@ -export default function saveState(client, guild, radio){ +export default function saveState(client: any, guild: any, radio: any){ client.datastore.checkEntry(guild.id); let date = new Date(); From fb36a8f8900bfb4369a23bae653a73bb2bf6560c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Sun, 4 Jun 2023 06:20:37 +0300 Subject: [PATCH 07/44] Typescript Continue --- src/client/classes/Datastore.ts | 2 +- src/client/classes/Radio.ts | 2 +- src/client/classes/Stations.ts | 3 ++- src/client/commands/help.ts | 2 +- src/client/commands/maintenance.ts | 3 ++- src/client/commands/play.ts | 15 ++++++--------- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/client/classes/Datastore.ts b/src/client/classes/Datastore.ts index 490e099..d7f2637 100644 --- a/src/client/classes/Datastore.ts +++ b/src/client/classes/Datastore.ts @@ -14,7 +14,7 @@ export default class { fs.mkdirSync(dir); } //console.log(""); - const dataFiles = fs.readdirSync(path.join(path.dirname(__dirname), '../../datastore')).filter(f => f.endsWith('.json')); + const dataFiles = fs.readdirSync(path.join(path.dirname(__dirname), '../../datastore')).filter((f: string) => f.endsWith('.json')); for (const file of dataFiles) { try { const json = require(`../../../datastore/${file}`); diff --git a/src/client/classes/Radio.ts b/src/client/classes/Radio.ts index 4004fd3..b215237 100644 --- a/src/client/classes/Radio.ts +++ b/src/client/classes/Radio.ts @@ -47,7 +47,7 @@ export default class Radio extends Map { if(!station) return; - const construct = { + const construct: any = { textChannel: client.channels.cache.get(state.channels.text), voiceChannel: client.channels.cache.get(state.channels.voice), connection: null, diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index e91343f..a9379df 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -1,5 +1,6 @@ const _importDynamic = new Function('modulePath', 'return import(modulePath)'); -const fetch = (...args: any) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); +// @ts-ignore +const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); export default class Stations extends Array { logger: any; diff --git a/src/client/commands/help.ts b/src/client/commands/help.ts index 3db2606..d9af02b 100644 --- a/src/client/commands/help.ts +++ b/src/client/commands/help.ts @@ -13,7 +13,7 @@ export default { } let commands = ''; for (let i = 0; i < categories.length; i++) { - commands += `**» ${categories[i].toUpperCase()}**\n${client.commands.filter(x => x.category === categories[i] && !x.omitFromHelp).map((x: { name: any; }) => `\`${x.name}\``).join(', ')}\n`; + commands += `**» ${categories[i].toUpperCase()}**\n${client.commands.filter((x: { category: any; omitFromHelp: any; }) => x.category === categories[i] && !x.omitFromHelp).map((x: { name: any; }) => `\`${x.name}\``).join(', ')}\n`; } message.helpTitle = client.messages.helpTitle.replace("%client.user.username%", client.user.username); diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index 03ac808..abdbb18 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -1,7 +1,8 @@ import { ActionRowBuilder, EmbedBuilder, StringSelectMenuBuilder } from "discord.js"; import Streamer from "../classes/Streamer"; const _importDynamic = new Function('modulePath', 'return import(modulePath)'); -const fetch = (...args: any) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); +// @ts-ignore +const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); export default { name: 'maintenance', diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index 7f23ee0..270364d 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -34,7 +34,7 @@ export default { if(!query){ return client.funcs.listStations(client, interaction); } - let url = query ? query.replace(/<(.+)>/g, "$1") : ""; + const radio = client.radio.get(interaction.guild.id); const voiceChannel = interaction.member.voice.channel; if (!voiceChannel) return interaction.reply({ @@ -65,13 +65,9 @@ export default { }); } let station; - const number = parseInt(query - 1); - if (url.startsWith("http")) { - return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.errorStationURL, - ephemeral: true - }); - } else if (!isNaN(number)) { + + if (!isNaN(query)) { + const number = parseInt((query - 1) as unknown as string); if (number > client.stations.length - 1) { return interaction.reply({ content: client.messageEmojis["error"] + client.messages.wrongStationNumber, @@ -114,13 +110,14 @@ export default { return; } + let date = new Date(); const construct = { textChannel: interaction.channel, voiceChannel: voiceChannel, connection: null, message: null, station: station, - startTime: number + startTime: date.getTime() }; client.radio.set(interaction.guild.id, construct); From 2d0b326721e91a01677cc6dec0c2b6235e24346c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Sun, 4 Jun 2023 07:15:30 +0300 Subject: [PATCH 08/44] Update --- src/client/classes/Stations.ts | 3 +-- src/client/commands.ts | 9 +++++++-- src/index.ts | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index a9379df..e91343f 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -1,6 +1,5 @@ const _importDynamic = new Function('modulePath', 'return import(modulePath)'); -// @ts-ignore -const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); +const fetch = (...args: any) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); export default class Stations extends Array { logger: any; diff --git a/src/client/commands.ts b/src/client/commands.ts index fb7b4f8..b7a79f2 100644 --- a/src/client/commands.ts +++ b/src/client/commands.ts @@ -1,3 +1,4 @@ +import { Snowflake } from "discord.js"; const { SlashCommandBuilder } = require('@discordjs/builders'); const { REST } = require('@discordjs/rest'); const { Routes } = require('discord-api-types/v9'); @@ -7,7 +8,7 @@ const path = require ('path'); export default { async execute(client: any) { - const commands : any[] = []; + const commands : any = []; const commandFiles = fs.readdirSync(path.join("./src/client/commands")).filter((f: string) => f.endsWith(".ts")); for (const file of commandFiles) { @@ -30,6 +31,8 @@ export default { commands.push(command.data); } + console.log(commands); +/* const rest = new REST({ version: '9' }).setToken(client.config.token); (async () => { @@ -62,7 +65,7 @@ export default { ); let guilds = await client.guilds.fetch(); - guilds.forEach(async (guild: { id: any; }) => { + guilds.forEach(async (guild: { id: Snowflake; }) => { try { await rest.put( Routes.applicationGuildCommands(client.user.id, guild.id), @@ -79,5 +82,7 @@ export default { console.error(error); } })(); +*/ + } } diff --git a/src/index.ts b/src/index.ts index ef051ed..a27b1ee 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ -const { default: RadioClient } = require("./Client"); +import RadioClient from "./Client"; const client = new RadioClient(); From 0e62861e331c53d5a80ba525301dc52ecd0ee81e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Sun, 4 Jun 2023 22:35:07 +0300 Subject: [PATCH 09/44] Typescript rework continue --- src/Client.ts | 33 ++++---- src/client/classes/Datastore.ts | 4 +- src/client/classes/Radio.ts | 5 +- src/client/classes/Stations.ts | 4 +- src/client/classes/Streamer.ts | 9 +-- src/client/commands.ts | 120 +++++++++++------------------ src/client/commands/maintenance.ts | 3 +- src/client/commands/play.ts | 11 +-- src/client/events.ts | 12 +++ src/client/events/ready.ts | 13 +--- src/client/funcs.ts | 12 +++ src/client/funcs/listStations.ts | 2 +- src/config.ts | 2 - src/index.ts | 2 +- 14 files changed, 103 insertions(+), 129 deletions(-) create mode 100644 src/client/events.ts create mode 100644 src/client/funcs.ts diff --git a/src/Client.ts b/src/Client.ts index 7b5a4e1..4208f17 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -7,8 +7,8 @@ import Statistics from "./client/classes/Statistics"; import { command } from "./client/utils/typings"; import config from "./config"; import messages from "./client/messages"; - -const events = "./client/events/"; +import events from "./client/events" +import funcs from "./client/funcs"; const GatewayIntents = new IntentsBitField(); GatewayIntents.add( @@ -19,6 +19,7 @@ GatewayIntents.add( export default class RadioClient extends Client { readonly commands: Collection; + public events: any; public funcs: any; readonly config = config; readonly messages = messages; @@ -27,6 +28,7 @@ export default class RadioClient extends Client { public streamer: Streamer | null; public statistics: Statistics | null; public radio: Radio | null; + constructor() { super({ intents: GatewayIntents @@ -38,15 +40,8 @@ export default class RadioClient extends Client { this.statistics = null; this.radio = null; - this.funcs = {}; - this.funcs.check = require("./client/funcs/check"); - this.funcs.isDev = require("./client/funcs/isDev"); - this.funcs.logger = require("./client/funcs/logger"); - this.funcs.msToTime = require("./client/funcs/msToTime"); - this.funcs.saveState = require("./client/funcs/saveState"); - this.funcs.loadState = require("./client/funcs/loadState"); - this.funcs.play = require("./client/funcs/play"); - this.funcs.listStations = require("./client/funcs/listStations"); + this.events = events; + this.funcs = funcs; console.log('RadioX ' + this.config.version); console.log('Internet Radio to your Discord guild'); @@ -59,19 +54,19 @@ export default class RadioClient extends Client { this.config.maintenanceMode = true; this.on("ready", () => { - require(`${events}ready`).execute(this); + this.events.ready.execute(this); }); this.on("messageDelete", msg => { - require(`${events}messageDelete`).execute(this, msg); + this.events.messageDelete.execute(this, msg); }); this.on("interactionCreate", interaction => { - require(`${events}interactionCreate`).execute(this, interaction); + this.events.interactionCreate.execute(this, interaction); }); this.on("voiceStateUpdate", (oldState, newState) => { - require(`${events}voiceStateUpdate`).execute(this, oldState, newState); + this.events.voiceStateUpdate.execute(this, oldState, newState); }); this.on("error", error => { @@ -81,15 +76,15 @@ export default class RadioClient extends Client { }); process.on('SIGINT', () => { - require(`${events}SIGINT`).execute(this); + this.events.SIGINT.execute(this); }); process.on('SIGTERM', () => { - require(`${events}SIGTERM`).execute(this); + this.events.SIGTERM.execute(this); }); process.on('uncaughtException', (error) => { - require(`${events}uncaughtException`).execute(this, error); + this.events.uncaughtException.execute(this, error); }); process.on('exit', () => { @@ -97,7 +92,7 @@ export default class RadioClient extends Client { }); process.on('warning', (warning) => { - require(`${events}warning`).execute(this, warning); + this.events.warning.execute(this, warning); }); this.login(this.config.token).catch((err) => { diff --git a/src/client/classes/Datastore.ts b/src/client/classes/Datastore.ts index d7f2637..c8e0bbe 100644 --- a/src/client/classes/Datastore.ts +++ b/src/client/classes/Datastore.ts @@ -1,5 +1,5 @@ -const fs = require('fs'); -const path = require('path'); +import fs from 'fs'; +import path from 'path'; export default class { map: Map; diff --git a/src/client/classes/Radio.ts b/src/client/classes/Radio.ts index b215237..21d7f4d 100644 --- a/src/client/classes/Radio.ts +++ b/src/client/classes/Radio.ts @@ -1,7 +1,4 @@ -const { - getVoiceConnection, - joinVoiceChannel -} = require("@discordjs/voice"); +import { getVoiceConnection, joinVoiceChannel } from "@discordjs/voice"; export default class Radio extends Map { diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index e91343f..a827eed 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -1,12 +1,14 @@ const _importDynamic = new Function('modulePath', 'return import(modulePath)'); +// @ts-ignore const fetch = (...args: any) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); +import logger from "../funcs/logger"; export default class Stations extends Array { logger: any; constructor() { super(); - this.logger = require("../funcs/logger.js"); + this.logger = logger; } async fetch(options: any){ diff --git a/src/client/classes/Streamer.ts b/src/client/classes/Streamer.ts index 4e5055a..a5b2896 100644 --- a/src/client/classes/Streamer.ts +++ b/src/client/classes/Streamer.ts @@ -1,8 +1,5 @@ -const { - createAudioPlayer, - createAudioResource, - NoSubscriberBehavior -} = require("@discordjs/voice"); +import logger from "../funcs/logger"; +import { createAudioPlayer, createAudioResource, NoSubscriberBehavior } from "@discordjs/voice"; export default class Streamer { map: any; @@ -12,7 +9,7 @@ export default class Streamer { constructor() { this.map = new Map(); this.mode = null; - this.logger = require("../funcs/logger"); + this.logger = logger; } init(client: any){ diff --git a/src/client/commands.ts b/src/client/commands.ts index b7a79f2..f53ba00 100644 --- a/src/client/commands.ts +++ b/src/client/commands.ts @@ -1,88 +1,56 @@ import { Snowflake } from "discord.js"; -const { SlashCommandBuilder } = require('@discordjs/builders'); -const { REST } = require('@discordjs/rest'); -const { Routes } = require('discord-api-types/v9'); -const fs = require('fs'); -const path = require ('path'); +import bug from "./commands/bug"; +import help from "./commands/help"; +import invite from "./commands/invite"; +import list from "./commands/list"; +import maintenance from "./commands/maintenance"; +import next from "./commands/next"; +import nowplaying from "./commands/nowplaying"; +import play from "./commands/play"; +import prev from "./commands/prev"; +import statistics from "./commands/statistics"; +import status from "./commands/status"; +import stop from "./commands/stop"; export default { async execute(client: any) { + const commands : any = [ bug, help, invite, list, maintenance, next, nowplaying, play, prev, statistics, status, stop ]; - const commands : any = []; - const commandFiles = fs.readdirSync(path.join("./src/client/commands")).filter((f: string) => f.endsWith(".ts")); - - for (const file of commandFiles) { - const command = require(`./commands/${file}`); + for(const command of commands){ client.commands.set(command.name, command); - - command.data = new SlashCommandBuilder() - .setName(command.name) - .setDescription(command.description); - - command.data = command.data.toJSON(); - if(command.options) { - command.options.forEach(function(option: { type: string | number; }) { - if(option.type == "STRING") option.type = 3; - if(option.type == "NUMBER") option.type = 10; - command.data.options.push(option); - }); - } - - commands.push(command.data); } - console.log(commands); -/* - const rest = new REST({ version: '9' }).setToken(client.config.token); - - (async () => { - try { - client.funcs.logger('Slash Commands', 'Started refreshing application (/) commands.'); - - if(client.config.devMode){ - await rest.put( - Routes.applicationCommands(client.user.id), - { body: [] }, - ); - - let guilds = await client.guilds.fetch(); - guilds.forEach(async (guild: { id: string; name: string; }) => { - try { - await rest.put( - Routes.applicationGuildCommands(client.user.id, guild.id), - { body: commands } - ); - client.funcs.logger('Slash Commands', 'Guild Applications – Successful' + "\n" + guild.id + " / " + guild.name); - } catch (DiscordAPIError: any) { - client.funcs.logger('Slash Commands', 'Guild Applications – Failed' + "\n" + guild.id + " / " + guild.name); - if(DiscordAPIError.name != "DiscordAPIError[50001]") console.error(DiscordAPIError.message + "\n\n"); - } - }); - } else { - await rest.put( - Routes.applicationCommands(client.user.id), - { body: commands } - ); - - let guilds = await client.guilds.fetch(); - guilds.forEach(async (guild: { id: Snowflake; }) => { - try { - await rest.put( - Routes.applicationGuildCommands(client.user.id, guild.id), - { body: [] } - ); - } catch (DiscordAPIError) { - } - }); - } - - client.funcs.logger('Slash Commands', 'Successfully reloaded application (/) commands.' + "\n"); - } catch (error) { - client.funcs.logger('Slash Commands', 'Reloading application (/) commands failed.' + "\n"); - console.error(error); + client.funcs.logger('Application Commands', 'Started refreshing application (/) commands.'); + if(client.config.devMode){ + client.application.commands.set([]); + for(const command of commands){ + let guilds = await client.guilds.fetch(); + guilds.forEach(async (guild: { id: Snowflake; name: string; }) => { + client.application.commands.create({ + name: command.name, + description: command.description, + options: command.options || [] + }, guild.id); + client.funcs.logger('Application Commands', 'Guild: ' + guild.id + " (" + guild.name + ") \n" + 'Command: ' + command.name); + }); } - })(); -*/ + } else { + for(const command of commands){ + client.application.commands.create({ + name: command.name, + description: command.description, + options: command.options || [] + }); + + client.funcs.logger('Application Commands', 'Command: ' + command.name); + } + + let guilds = await client.guilds.fetch(); + guilds.forEach(async (guild: { id: Snowflake; }) => { + client.application.commands.set([], guild.id); + }); + } + client.funcs.logger('Application Commands', 'Successfully reloaded application (/) commands.' + "\n"); } } diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index abdbb18..7d325c5 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -1,5 +1,6 @@ import { ActionRowBuilder, EmbedBuilder, StringSelectMenuBuilder } from "discord.js"; import Streamer from "../classes/Streamer"; +import commands from "../commands"; const _importDynamic = new Function('modulePath', 'return import(modulePath)'); // @ts-ignore const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); @@ -120,7 +121,7 @@ export default { case "6": client.config.maintenanceMode = true; client.user.setStatus('idle'); - require(`../commands.js`).execute(client); + commands.execute(client); client.user.setStatus('online'); client.config.maintenanceMode = false; break; diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index 270364d..c56e98b 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -1,15 +1,12 @@ -import { PermissionFlagsBits } from "discord.js"; -const { - getVoiceConnection, - joinVoiceChannel -} = require("@discordjs/voice"); +import { ApplicationCommandOptionType, PermissionFlagsBits } from "discord.js"; +import { getVoiceConnection, joinVoiceChannel } from "@discordjs/voice"; export default { name: "play", usage: "", description: "Play radio", options: [ - { type: "STRING", name: "query", description: "Select station", required: false} + { type: ApplicationCommandOptionType.String, name: "query", description: "Select station", required: false} ], category: "radio", async execute(interaction: any, client: any) { @@ -111,7 +108,7 @@ export default { } let date = new Date(); - const construct = { + const construct: any = { textChannel: interaction.channel, voiceChannel: voiceChannel, connection: null, diff --git a/src/client/events.ts b/src/client/events.ts new file mode 100644 index 0000000..dc32b06 --- /dev/null +++ b/src/client/events.ts @@ -0,0 +1,12 @@ +import interactionCreate from "./events/interactionCreate" +import messageDelete from "./events/messageDelete" +import ready from "./events/ready" +import SIGINT from "./events/SIGINT" +import SIGTERM from "./events/SIGTERM" +import uncaughtException from "./events/uncaughtException" +import voiceStateUpdate from "./events/voiceStateUpdate" +import warning from "./events/warning" + +export default { + interactionCreate, messageDelete, ready, SIGINT, SIGTERM, uncaughtException, voiceStateUpdate, warning +} diff --git a/src/client/events/ready.ts b/src/client/events/ready.ts index 403ff64..e42e21a 100644 --- a/src/client/events/ready.ts +++ b/src/client/events/ready.ts @@ -3,6 +3,8 @@ import Radio from "../classes/Radio"; import Stations from "../classes/Stations"; import Streamer from "../classes/Streamer"; import Statistics from "../classes/Statistics"; +import emojis from "../emojis" +import commands from "../commands"; export default { name: 'ready', @@ -41,13 +43,6 @@ export default { show: true }); - /*setInterval(async () => { - await client.stations.fetch({ - url: client.config.stationslistUrl, - show: false - }); - }, 3600000);*/ - client.streamer = new Streamer(); client.streamer.init(client); @@ -70,10 +65,10 @@ export default { client.statistics.calculateGlobal(client); /*EMOJIS*/ - require(`../emojis.js`).execute(client); + emojis.execute(client); /*COMMANDS*/ - require(`../commands.js`).execute(client); + commands.execute(client); /*RADIO*/ client.radio = new Radio(); diff --git a/src/client/funcs.ts b/src/client/funcs.ts new file mode 100644 index 0000000..5a2c7ae --- /dev/null +++ b/src/client/funcs.ts @@ -0,0 +1,12 @@ +import check from "./funcs/check"; +import isDev from "./funcs/isDev"; +import listStations from "./funcs/listStations"; +import loadState from "./funcs/loadState"; +import logger from "./funcs/logger"; +import msToTime from "./funcs/msToTime"; +import play from "./funcs/play"; +import saveState from "./funcs/saveState"; + +export default { + check, isDev, listStations, loadState, logger, msToTime, play, saveState +} diff --git a/src/client/funcs/listStations.ts b/src/client/funcs/listStations.ts index 0a51045..e873b19 100644 --- a/src/client/funcs/listStations.ts +++ b/src/client/funcs/listStations.ts @@ -1,4 +1,4 @@ -import { ActionRowBuilder, Interaction, StringSelectMenuBuilder } from "discord.js"; +import { ActionRowBuilder, StringSelectMenuBuilder } from "discord.js"; export default function listStations(client: any, interaction: any){ let stations: any = new Array(); diff --git a/src/config.ts b/src/config.ts index 2bdc4ed..a00e8e9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,3 @@ -require('dotenv/config'); - export default { //credentials diff --git a/src/index.ts b/src/index.ts index a27b1ee..87b8477 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ import RadioClient from "./Client"; -const client = new RadioClient(); +new RadioClient(); From c584e3632e2ab1cb6cfb1a8012bed4a8e6374ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Mon, 5 Jun 2023 00:13:15 +0300 Subject: [PATCH 10/44] Typescript Continuum --- src/Client.ts | 5 ++++- src/client/classes/Radio.ts | 14 ++++++++------ src/client/classes/Statistics.ts | 15 ++++++++------- src/client/classes/Streamer.ts | 9 +++++---- src/client/commands.ts | 16 ++++++++++++++-- src/client/commands/bug.ts | 7 ++++--- src/client/commands/help.ts | 7 ++++--- src/client/commands/invite.ts | 7 ++++--- src/client/commands/list.ts | 9 +++++---- src/client/commands/maintenance.ts | 11 ++++++----- src/client/commands/next.ts | 5 ++++- src/client/commands/nowplaying.ts | 9 +++++---- src/client/commands/play.ts | 5 +++-- src/client/commands/prev.ts | 6 +++++- src/client/commands/statistics.ts | 11 ++++++----- src/client/commands/status.ts | 7 ++++--- src/client/commands/stop.ts | 13 +++++++------ src/client/emojis.ts | 4 +++- src/client/events/SIGINT.ts | 10 ++++++---- src/client/events/SIGTERM.ts | 4 +++- src/client/events/interactionCreate.ts | 3 ++- src/client/events/messageDelete.ts | 5 +++-- src/client/events/ready.ts | 3 ++- src/client/events/uncaughtException.ts | 4 +++- src/client/events/voiceStateUpdate.ts | 15 ++++++++------- src/client/events/warning.ts | 4 +++- src/client/funcs/check.ts | 6 ++++-- src/client/funcs/listStations.ts | 7 +++++-- src/client/funcs/loadState.ts | 4 +++- src/client/funcs/logger.ts | 2 +- src/client/funcs/play.ts | 11 ++++++----- src/client/funcs/saveState.ts | 5 ++++- src/client/utils/typings.ts | 3 --- 33 files changed, 152 insertions(+), 94 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 4208f17..29840f9 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -4,7 +4,7 @@ import Radio from "./client/classes/Radio"; import Stations from "./client/classes/Stations"; import Streamer from "./client/classes/Streamer"; import Statistics from "./client/classes/Statistics"; -import { command } from "./client/utils/typings"; +import { command } from "./client/commands"; import config from "./config"; import messages from "./client/messages"; import events from "./client/events" @@ -28,6 +28,8 @@ export default class RadioClient extends Client { public streamer: Streamer | null; public statistics: Statistics | null; public radio: Radio | null; + public messageEmojis: any | null; + public developers: string | undefined; constructor() { super({ @@ -39,6 +41,7 @@ export default class RadioClient extends Client { this.streamer = null; this.statistics = null; this.radio = null; + this.messageEmojis = null; this.events = events; this.funcs = funcs; diff --git a/src/client/classes/Radio.ts b/src/client/classes/Radio.ts index 21d7f4d..690979d 100644 --- a/src/client/classes/Radio.ts +++ b/src/client/classes/Radio.ts @@ -1,4 +1,6 @@ import { getVoiceConnection, joinVoiceChannel } from "@discordjs/voice"; +import { VoiceChannel } from "discord.js"; +import RadioClient from "../../Client"; export default class Radio extends Map { @@ -6,7 +8,7 @@ export default class Radio extends Map { super(); } - save(client: any) { + save(client: RadioClient) { let currentRadios = this.keys(); let radio = currentRadios.next(); @@ -14,9 +16,9 @@ export default class Radio extends Map { let currentRadio = this.get(radio.value); if (currentRadio) { - currentRadio.guild = client.datastore.getEntry(radio.value).guild; + currentRadio.guild = client.datastore?.getEntry(radio.value).guild; - client.statistics.update(client, currentRadio.guild, currentRadio); + client.statistics?.update(client, currentRadio.guild, currentRadio); client.funcs.saveState(client, currentRadio.guild, currentRadio); currentRadio.connection?.destroy(); currentRadio.message?.delete(); @@ -27,7 +29,7 @@ export default class Radio extends Map { } } - restore(client: any, guilds: any) { + restore(client: RadioClient, guilds: any) { if(!client.stations) return; guilds.forEach(async (guild: { id: any; }) => { @@ -39,7 +41,7 @@ export default class Radio extends Map { if(voiceChannel.members.filter((member: { user: { bot: any; }; }) => !member.user.bot).size === 0) return; - const sstation = await client.stations.search(state.station.name, "direct"); + const sstation = await client.stations?.search(state.station.name, "direct"); let station = sstation; if(!station) return; @@ -65,7 +67,7 @@ export default class Radio extends Map { construct.connection = connection; let date = new Date(); construct.startTime = date.getTime(); - client.datastore.checkEntry(guild.id); + client.datastore?.checkEntry(guild.id); client.funcs.play(client, null, guild, station); } catch (error) { console.log(error); diff --git a/src/client/classes/Statistics.ts b/src/client/classes/Statistics.ts index 25e264c..d2dc52f 100644 --- a/src/client/classes/Statistics.ts +++ b/src/client/classes/Statistics.ts @@ -1,4 +1,5 @@ import { Guild } from "discord.js"; +import RadioClient from "../../Client"; export default class Statistics { map: any; @@ -7,17 +8,17 @@ export default class Statistics { this.map = new Map(); } - update(client: any, guild: Guild, radio: any) { + update(client: RadioClient, guild: Guild, radio: any) { - client.datastore.checkEntry(guild.id); + client.datastore?.checkEntry(guild.id); - radio.datastore = client.datastore.getEntry(guild.id); + radio.datastore = client.datastore?.getEntry(guild.id); if(!radio.datastore.statistics[radio.station.name]){ radio.datastore.statistics[radio.station.name] = {}; radio.datastore.statistics[radio.station.name].time = 0; radio.datastore.statistics[radio.station.name].used = 0; - client.datastore.updateEntry(guild, radio.datastore); + client.datastore?.updateEntry(guild, radio.datastore); } let date = new Date(); @@ -26,13 +27,13 @@ export default class Statistics { radio.datastore.statistics[radio.station.name].time = parseInt(radio.datastore.statistics[radio.station.name].time)+parseInt(radio.playTime); radio.datastore.statistics[radio.station.name].used = parseInt(radio.datastore.statistics[radio.station.name].used)+1; - client.datastore.updateEntry(guild, radio.datastore); + client.datastore?.updateEntry(guild, radio.datastore); this.calculateGlobal(client); } - calculateGlobal(client: any){ + calculateGlobal(client: RadioClient){ if(!client.stations) return; - if(!client.datastore.map) return; + if(!client.datastore?.map) return; let guilds = client.datastore.map.keys(); let stations = client.stations; diff --git a/src/client/classes/Streamer.ts b/src/client/classes/Streamer.ts index a5b2896..14c0da2 100644 --- a/src/client/classes/Streamer.ts +++ b/src/client/classes/Streamer.ts @@ -1,5 +1,6 @@ import logger from "../funcs/logger"; import { createAudioPlayer, createAudioResource, NoSubscriberBehavior } from "@discordjs/voice"; +import RadioClient from "../../Client"; export default class Streamer { map: any; @@ -12,7 +13,7 @@ export default class Streamer { this.logger = logger; } - init(client: any){ + init(client: RadioClient){ if(!client.config.streamerMode) return; switch(client.config.streamerMode){ @@ -35,12 +36,12 @@ export default class Streamer { } } - refresh(client: any){ + refresh(client: RadioClient){ this.init(client); let streamers = this.map.keys(); streamers.forEach((streamer: any) => { - if(client.stations.findIndex((station: { name: any; }) => station.name == streamer) == -1){ + if(client.stations?.findIndex((station: { name: any; }) => station.name == streamer) == -1){ this.stop(streamer); } }); @@ -111,7 +112,7 @@ export default class Streamer { return audioPlayer; } - leave(client: any) { + leave(client: RadioClient) { if(!client.stations) return; client.stations.forEach((station: any) => { this.stop(station); diff --git a/src/client/commands.ts b/src/client/commands.ts index f53ba00..997c7da 100644 --- a/src/client/commands.ts +++ b/src/client/commands.ts @@ -1,4 +1,5 @@ import { Snowflake } from "discord.js"; +import RadioClient from "../Client"; import bug from "./commands/bug"; import help from "./commands/help"; import invite from "./commands/invite"; @@ -12,20 +13,30 @@ import statistics from "./commands/statistics"; import status from "./commands/status"; import stop from "./commands/stop"; +export interface command { + name: string, + description: string, + category: string, + options?: [], + execute: any +} + export default { - async execute(client: any) { - const commands : any = [ bug, help, invite, list, maintenance, next, nowplaying, play, prev, statistics, status, stop ]; + async execute(client: RadioClient) { + const commands : command[] = [ bug, help, invite, list, maintenance, next, nowplaying, play, prev, statistics, status, stop ]; for(const command of commands){ client.commands.set(command.name, command); } + if(!client.application) return; client.funcs.logger('Application Commands', 'Started refreshing application (/) commands.'); if(client.config.devMode){ client.application.commands.set([]); for(const command of commands){ let guilds = await client.guilds.fetch(); guilds.forEach(async (guild: { id: Snowflake; name: string; }) => { + if(!client.application) return; client.application.commands.create({ name: command.name, description: command.description, @@ -47,6 +58,7 @@ export default { let guilds = await client.guilds.fetch(); guilds.forEach(async (guild: { id: Snowflake; }) => { + if(!client.application) return; client.application.commands.set([], guild.id); }); } diff --git a/src/client/commands/bug.ts b/src/client/commands/bug.ts index 598f94b..2819fc5 100644 --- a/src/client/commands/bug.ts +++ b/src/client/commands/bug.ts @@ -1,10 +1,11 @@ -import { EmbedBuilder } from "discord.js"; +import { ChatInputCommandInteraction, ColorResolvable, EmbedBuilder } from "discord.js"; +import RadioClient from "../../Client"; export default { name: 'bug', description: 'Report a bug', category: 'info', - async execute(interaction: any, client: any) { + async execute(interaction: ChatInputCommandInteraction, client: RadioClient) { let message : any = {}; message.bugTitle = client.messages.bugTitle.replace("%client.user.username%", client.user.username); @@ -13,7 +14,7 @@ export default { const embed = new EmbedBuilder() .setTitle(message.bugTitle) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor) + .setColor(client.config.embedColor as ColorResolvable) .setDescription(message.bugDescription) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ diff --git a/src/client/commands/help.ts b/src/client/commands/help.ts index d9af02b..8541041 100644 --- a/src/client/commands/help.ts +++ b/src/client/commands/help.ts @@ -1,10 +1,11 @@ -import { EmbedBuilder } from "discord.js"; +import { ChatInputCommandInteraction, ColorResolvable, EmbedBuilder } from "discord.js"; +import RadioClient from "../../Client"; export default { name: 'help', description: 'Get help using bot', category: 'info', - execute(interaction: any, client: any) { + execute(interaction: ChatInputCommandInteraction, client: RadioClient) { let message: any = {}; const categories : any= []; @@ -22,7 +23,7 @@ export default { const embed = new EmbedBuilder() .setTitle(message.helpTitle) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor) + .setColor(client.config.embedColor as ColorResolvable) .setDescription(message.helpDescription) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ diff --git a/src/client/commands/invite.ts b/src/client/commands/invite.ts index dc3b847..a879e8e 100644 --- a/src/client/commands/invite.ts +++ b/src/client/commands/invite.ts @@ -1,15 +1,16 @@ -import { EmbedBuilder } from "discord.js"; +import { ChatInputCommandInteraction, ColorResolvable, EmbedBuilder } from "discord.js"; +import RadioClient from "../../Client"; export default { name: 'invite', description: 'Invite Bot', category: 'info', - execute(interaction: any, client: any) { + execute(interaction: ChatInputCommandInteraction, client: RadioClient) { let message: any = {}; message.inviteTitle = client.messages.inviteTitle.replace("%client.user.username%", client.user.username); const embed = new EmbedBuilder() .setTitle(message.inviteTitle) - .setColor(client.config.embedColor) + .setColor(client.config.embedColor as ColorResolvable) .setURL("https://discord.com/api/oauth2/authorize?client_id=" + client.user.id + "&permissions=2184465408&scope=applications.commands%20bot") //View Channels, Send Messages, Embed Links, Use External Emojis, Use Slash Commands, Connect, Speak, Use Voice Activity .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ diff --git a/src/client/commands/list.ts b/src/client/commands/list.ts index ea31a02..e90066b 100644 --- a/src/client/commands/list.ts +++ b/src/client/commands/list.ts @@ -1,10 +1,11 @@ -import { EmbedBuilder } from "discord.js"; +import { ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; +import RadioClient from "../../Client"; export default { name: 'list', description: 'List radio stations', category: 'radio', - execute(interaction: any, client: any) { + execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { let message: any = {}; if(!client.stations) { @@ -15,7 +16,7 @@ export default { }); } - const radio = client.radio.get(interaction.guild.id); + const radio = client.radio?.get(interaction.guild.id); if(radio && !client.config.maintenanceMode){ client.funcs.listStations(client, interaction); @@ -29,7 +30,7 @@ export default { let embed = new EmbedBuilder() .setTitle(client.messages.listTitle) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["list"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor) + .setColor(client.config.embedColor as ColorResolvable) .setDescription(stations) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index 7d325c5..da61e74 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -1,4 +1,5 @@ -import { ActionRowBuilder, EmbedBuilder, StringSelectMenuBuilder } from "discord.js"; +import { ActionRowBuilder, ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js"; +import RadioClient from "../../Client"; import Streamer from "../classes/Streamer"; import commands from "../commands"; const _importDynamic = new Function('modulePath', 'return import(modulePath)'); @@ -9,7 +10,7 @@ export default { name: 'maintenance', description: 'Bot Maintenance', category: 'info', - async execute(interaction: any, client: any) { + async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { let message: any = {}; if(!client.funcs.isDev(client.config.devId, interaction.user.id)) return interaction.reply({ @@ -55,12 +56,12 @@ export default { }, { emoji: "💤", - label: "Streamer Mode – Manual", + label: "Streamer Mode - Manual", value: "10" }, { emoji: "📡", - label: "Streamer Mode – Auto", + label: "Streamer Mode - Auto", value: "11" } ); @@ -85,7 +86,7 @@ export default { const embed = new EmbedBuilder() .setTitle(client.messages.maintenanceTitle) - .setColor(client.config.embedColor) + .setColor(client.config.embedColor as ColorResolvable) .setDescription(options.find((option: { value: any; }) => option.value == action).label) .setFooter({ text: client.messages.footerText, diff --git a/src/client/commands/next.ts b/src/client/commands/next.ts index a4f8662..ec5d00f 100644 --- a/src/client/commands/next.ts +++ b/src/client/commands/next.ts @@ -1,8 +1,11 @@ +import { ButtonInteraction, ChatInputCommandInteraction, StringSelectMenuInteraction } from "discord.js"; +import RadioClient from "../../Client"; + export default { name: 'next', description: 'Next Station', category: 'radio', - async execute(interaction: any, client: any, command: any) { + async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: any) { if (client.funcs.check(client, interaction, command)) { const radio = client.radio.get(interaction.guild.id); diff --git a/src/client/commands/nowplaying.ts b/src/client/commands/nowplaying.ts index 354ee03..c991951 100644 --- a/src/client/commands/nowplaying.ts +++ b/src/client/commands/nowplaying.ts @@ -1,13 +1,14 @@ -import { EmbedBuilder } from "discord.js"; +import { ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; +import RadioClient from "../../Client"; export default { name: 'nowplaying', description: 'Current Radio Station', category: 'radio', - async execute(interaction: any, client: any, command: any) { + async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: any) { if (client.funcs.check(client, interaction, command)) { let message: any = {}; - const radio = client.radio.get(interaction.guild.id); + const radio = client.radio?.get(interaction.guild.id); let date = new Date(); radio.currentTime = date.getTime(); @@ -21,7 +22,7 @@ export default { const embed = new EmbedBuilder() .setTitle(client.messages.nowplayingTitle) .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, ''))) - .setColor(client.config.embedColor) + .setColor(client.config.embedColor as ColorResolvable) .setDescription(message.nowplayingDescription) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index c56e98b..9e6e1b0 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -1,5 +1,6 @@ -import { ApplicationCommandOptionType, PermissionFlagsBits } from "discord.js"; +import { ApplicationCommandOptionType, ButtonInteraction, ChatInputCommandInteraction, PermissionFlagsBits, StringSelectMenuInteraction } from "discord.js"; import { getVoiceConnection, joinVoiceChannel } from "@discordjs/voice"; +import RadioClient from "../../Client"; export default { name: "play", @@ -9,7 +10,7 @@ export default { { type: ApplicationCommandOptionType.String, name: "query", description: "Select station", required: false} ], category: "radio", - async execute(interaction: any, client: any) { + async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { let message: any = {}; if(client.config.maintenanceMode){ diff --git a/src/client/commands/prev.ts b/src/client/commands/prev.ts index 351854b..55e1030 100644 --- a/src/client/commands/prev.ts +++ b/src/client/commands/prev.ts @@ -1,8 +1,12 @@ +import { ButtonInteraction, ChatInputCommandInteraction, StringSelectMenuInteraction } from "discord.js"; +import RadioClient from "../../Client"; +import { command } from "../commands"; + export default { name: 'prev', description: 'Previous Station', category: 'radio', - async execute(interaction: any, client: any, command: any) { + async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: command) { if (client.funcs.check(client, interaction, command)) { const radio = client.radio.get(interaction.guild.id); diff --git a/src/client/commands/statistics.ts b/src/client/commands/statistics.ts index 1fe9090..85eba3a 100644 --- a/src/client/commands/statistics.ts +++ b/src/client/commands/statistics.ts @@ -1,15 +1,16 @@ -import { EmbedBuilder } from "discord.js"; +import { ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; +import RadioClient from "../../Client"; export default { name: 'statistics', description: 'Show statistics', category: 'info', - execute(interaction: any, client: any) { + execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { let message: any = {}; let stations = client.stations; - let currentGuild = client.datastore.getEntry(interaction.guild.id); - let global = client.datastore.getEntry("global"); + let currentGuild = client.datastore?.getEntry(interaction.guild.id); + let global = client.datastore?.getEntry("global"); let statistics = ""; if(!client.stations) { @@ -29,7 +30,7 @@ export default { const embed = new EmbedBuilder() .setTitle(client.messages.statisticsTitle) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["statistics"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor) + .setColor(client.config.embedColor as ColorResolvable) .setDescription(statistics) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ diff --git a/src/client/commands/status.ts b/src/client/commands/status.ts index 6bdf562..1516221 100644 --- a/src/client/commands/status.ts +++ b/src/client/commands/status.ts @@ -1,10 +1,11 @@ -import { EmbedBuilder } from "discord.js"; +import { ColorResolvable, EmbedBuilder } from "discord.js"; +import RadioClient from "../../Client"; export default { name: 'status', description: 'Bot Status', category: 'info', - async execute(interaction: any, client: any) { + async execute(interaction: any, client: RadioClient) { let message: any = {}; message.statusTitle = client.messages.statusTitle.replace("%client.user.username%", client.user.username); @@ -13,7 +14,7 @@ export default { const embed = new EmbedBuilder() .setTitle(message.statusTitle) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor) + .setColor(client.config.embedColor as ColorResolvable) .addFields( { name: client.messages.statusField1, value: uptime }, { name: client.messages.statusField2, value: client.config.version }, diff --git a/src/client/commands/stop.ts b/src/client/commands/stop.ts index a85e1d7..6e2a223 100644 --- a/src/client/commands/stop.ts +++ b/src/client/commands/stop.ts @@ -1,20 +1,21 @@ -import { EmbedBuilder } from "discord.js"; +import { ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; +import RadioClient from "../../Client"; export default { name: 'stop', description: 'Stop radio', category: 'radio', - async execute(interaction: any, client: any, command: any) { + async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: any) { if (client.funcs.check(client, interaction, command)) { - const radio = client.radio.get(interaction.guild.id); - client.statistics.update(client, interaction.guild, radio); + const radio = client.radio?.get(interaction.guild.id); + client.statistics?.update(client, interaction.guild, radio); radio.connection?.destroy(); client.funcs.logger('Radio', interaction.guild.id + " / " + 'Stop'); const embed = new EmbedBuilder() .setTitle(client.user.username) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["stop"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor) + .setColor(client.config.embedColor as ColorResolvable) .addFields({ name: client.messages.nowplayingTitle, value: "-" @@ -39,7 +40,7 @@ export default { await radio.message?.delete(); }, 5000); - client.radio.delete(interaction.guild.id); + client.radio?.delete(interaction.guild.id); interaction.reply({ content: client.messageEmojis["stop"] + client.messages.stop, diff --git a/src/client/emojis.ts b/src/client/emojis.ts index df5f0a0..119f2bb 100644 --- a/src/client/emojis.ts +++ b/src/client/emojis.ts @@ -1,6 +1,8 @@ +import RadioClient from "../Client"; + export default { name: 'emojis', - async execute(client: any): Promise { + async execute(client: RadioClient): Promise { let customEmojis: any = { logo: "<:RadioX:688765708808487072>", eximiabots: "<:EximiaBots:693277919929303132>", diff --git a/src/client/events/SIGINT.ts b/src/client/events/SIGINT.ts index 27ee4a3..97828cc 100644 --- a/src/client/events/SIGINT.ts +++ b/src/client/events/SIGINT.ts @@ -1,13 +1,15 @@ +import RadioClient from "../../Client"; + export default { name: 'SIGINT', - execute(client: any) { + execute(client: RadioClient) { client.user.setStatus('dnd'); - client.streamer.leave(client); - client.radio.save(client); + client.streamer?.leave(client); + client.radio?.save(client); setInterval(() => { - if(client.radio.size == 0){ + if(client.radio?.size == 0){ process.exit(); } }, 500); diff --git a/src/client/events/SIGTERM.ts b/src/client/events/SIGTERM.ts index 911daf8..7e03abb 100644 --- a/src/client/events/SIGTERM.ts +++ b/src/client/events/SIGTERM.ts @@ -1,6 +1,8 @@ +import RadioClient from "../../Client"; + export default { name: 'SIGTERM', - execute(client: any) { + execute(client: RadioClient) { process.emit('SIGINT'); } } diff --git a/src/client/events/interactionCreate.ts b/src/client/events/interactionCreate.ts index ae15bbc..b396b68 100644 --- a/src/client/events/interactionCreate.ts +++ b/src/client/events/interactionCreate.ts @@ -1,8 +1,9 @@ import { PermissionFlagsBits } from "discord.js"; +import RadioClient from "../../Client"; export default { name: 'interactionCreate', - async execute(client: any, interaction: any) { + async execute(client: RadioClient, interaction: any) { const permissions = interaction.channel.permissionsFor(interaction.client.user); if (!permissions.has(PermissionFlagsBits.ViewChannel)) return; diff --git a/src/client/events/messageDelete.ts b/src/client/events/messageDelete.ts index 2b1b5b1..99a2b73 100644 --- a/src/client/events/messageDelete.ts +++ b/src/client/events/messageDelete.ts @@ -1,10 +1,11 @@ import { Message } from "discord.js"; +import RadioClient from "../../Client"; export default { name: 'messageDelete', - async execute(client: any, msg: Message) { + async execute(client: RadioClient, msg: Message) { if(!msg.author.bot || !msg.guild) return; - const radio = client.radio.get(msg.guild.id); + const radio = client.radio?.get(msg.guild.id); if(!radio) return; if(!radio.message) return; if(msg.id != radio.message.id) return; diff --git a/src/client/events/ready.ts b/src/client/events/ready.ts index e42e21a..e080aa7 100644 --- a/src/client/events/ready.ts +++ b/src/client/events/ready.ts @@ -1,3 +1,4 @@ +import RadioClient from "../../Client"; import Datastore from "../classes/Datastore"; import Radio from "../classes/Radio"; import Stations from "../classes/Stations"; @@ -8,7 +9,7 @@ import commands from "../commands"; export default { name: 'ready', - async execute(client: any) { + async execute(client: RadioClient) { client.funcs.logger("Bot", "Ready"); diff --git a/src/client/events/uncaughtException.ts b/src/client/events/uncaughtException.ts index 2153077..3f22396 100644 --- a/src/client/events/uncaughtException.ts +++ b/src/client/events/uncaughtException.ts @@ -1,6 +1,8 @@ +import RadioClient from "../../Client"; + export default { name: 'uncaughtException', - execute(client: any, error: any) { + execute(client: RadioClient, error: any) { client.funcs.logger("Error"); console.log(error.stack); console.log(''); diff --git a/src/client/events/voiceStateUpdate.ts b/src/client/events/voiceStateUpdate.ts index 4c4729a..caee4ef 100644 --- a/src/client/events/voiceStateUpdate.ts +++ b/src/client/events/voiceStateUpdate.ts @@ -1,4 +1,5 @@ import { PermissionFlagsBits, VoiceState } from "discord.js"; +import RadioClient from "../../Client"; const { getVoiceConnection, joinVoiceChannel @@ -6,7 +7,7 @@ const { export default { name: "voiceStateUpdate", - async execute(client: any, oldState: VoiceState, newState: VoiceState) { + async execute(client: RadioClient, oldState: VoiceState, newState: VoiceState) { if (oldState.channel === null) return; let change = false; const radio = client.radio?.get(newState.guild.id); @@ -15,11 +16,11 @@ export default { if (newState.member?.id === client.user.id && oldState.member?.id === client.user.id) { if (newState.channel === null) { - client.statistics.update(client, newState.guild, radio); + client.statistics?.update(client, newState.guild, radio); radio.connection?.destroy(); radio.message?.delete(); client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop'); - return client.radio.delete(newState.guild.id); + return client.radio?.delete(newState.guild.id); } const newPermissions = newState.channel.permissionsFor(newState.client.user); @@ -37,11 +38,11 @@ export default { 1000 ); } catch (error) { - client.statistics.update(client, newState.guild, radio); + client.statistics?.update(client, newState.guild, radio); radio.connection?.destroy(); radio.message?.delete(); client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop'); - client.radio.delete(oldState.guild.id); + client.radio?.delete(oldState.guild.id); } return; } @@ -56,11 +57,11 @@ export default { setTimeout(() => { if (!radio || !radio.connection || !radio.connection === null) return; if (radio.voiceChannel.members.filter((member: { user: { bot: any; }; }) => !member.user.bot).size === 0) { - client.statistics.update(client, newState.guild, radio); + client.statistics?.update(client, newState.guild, radio); radio.connection?.destroy(); radio.message?.delete(); client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop'); - client.radio.delete(newState.guild.id); + client.radio?.delete(newState.guild.id); } }, 5000); } diff --git a/src/client/events/warning.ts b/src/client/events/warning.ts index a831895..4b8dd8e 100644 --- a/src/client/events/warning.ts +++ b/src/client/events/warning.ts @@ -1,6 +1,8 @@ +import RadioClient from "../../Client"; + export default { name: 'warning', - execute(client: any, warning: any) { + execute(client: RadioClient, warning: Error) { if(warning.name == "ExperimentalWarning" && warning.message.startsWith("stream/web")) return; client.funcs.logger("Warning"); diff --git a/src/client/funcs/check.ts b/src/client/funcs/check.ts index c832d7f..434848e 100644 --- a/src/client/funcs/check.ts +++ b/src/client/funcs/check.ts @@ -1,6 +1,8 @@ -export default function check(client: any, interaction: any, command: any) { +import RadioClient from "../../Client"; + +export default function check(client: RadioClient, interaction: any, command: any) { let message: any = {}; - const radio = client.radio.get(interaction.guild.id); + const radio = client.radio?.get(interaction.guild.id); if(client.config.maintenanceMode){ interaction.reply({ content: client.messageEmojis["error"] + client.messages.maintenance, diff --git a/src/client/funcs/listStations.ts b/src/client/funcs/listStations.ts index e873b19..35bffc4 100644 --- a/src/client/funcs/listStations.ts +++ b/src/client/funcs/listStations.ts @@ -1,9 +1,12 @@ import { ActionRowBuilder, StringSelectMenuBuilder } from "discord.js"; +import RadioClient from "../../Client"; -export default function listStations(client: any, interaction: any){ - let stations: any = new Array(); +export default function listStations(client: RadioClient, interaction: any){ + let stations: any = new Array(); let options: any = new Array(); + if(!client.stations) return; + stations = client.stations.forEach((station: { name?: any; owner?: any; label?: any; description?: any; value?: any; }) => { if(station.name == "GrooveFM") return; station = { diff --git a/src/client/funcs/loadState.ts b/src/client/funcs/loadState.ts index 9428bb8..cc69fd6 100644 --- a/src/client/funcs/loadState.ts +++ b/src/client/funcs/loadState.ts @@ -1,6 +1,8 @@ import { Guild } from "discord.js"; +import RadioClient from "../../Client"; -export default function loadState(client: any, guild: Guild){ +export default function loadState(client: RadioClient, guild: Guild){ + if(!client.datastore) return; let data = client.datastore.getEntry(guild.id); if(!data) return; let state; diff --git a/src/client/funcs/logger.ts b/src/client/funcs/logger.ts index 17d8680..830999d 100644 --- a/src/client/funcs/logger.ts +++ b/src/client/funcs/logger.ts @@ -1,5 +1,5 @@ export default function logger(area : string, text: string){ let date = new Date(); - console.log('[' + area + '] – ' + date.toISOString()); + console.log('[' + area + '] - ' + date.toISOString()); if(text) console.log(text + '\n'); } diff --git a/src/client/funcs/play.ts b/src/client/funcs/play.ts index 899075e..e717934 100644 --- a/src/client/funcs/play.ts +++ b/src/client/funcs/play.ts @@ -1,9 +1,10 @@ -import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"; +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ColorResolvable, EmbedBuilder } from "discord.js"; +import RadioClient from "../../Client"; -export default async function play(client: any, interaction: any, guild: any, station: any) { +export default async function play(client: RadioClient, interaction: any, guild: any, station: any) { let message: any = {}; - const radio = client.radio.get(guild.id); - const audioPlayer = client.streamer.listen(station); + const radio = client.radio?.get(guild.id); + const audioPlayer = client.streamer?.listen(station); radio.connection.subscribe(audioPlayer); client.funcs.logger('Radio', guild.id + " / " + "Play" + " / " + radio.station.name); @@ -16,7 +17,7 @@ export default async function play(client: any, interaction: any, guild: any, st const embed = new EmbedBuilder() .setTitle(client.user.username) .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, ''))) - .setColor(client.config.embedColor) + .setColor(client.config.embedColor as ColorResolvable) .addFields({ name: client.messages.nowplayingTitle, value: message.nowplayingDescription diff --git a/src/client/funcs/saveState.ts b/src/client/funcs/saveState.ts index 4940866..0bba27a 100644 --- a/src/client/funcs/saveState.ts +++ b/src/client/funcs/saveState.ts @@ -1,4 +1,7 @@ -export default function saveState(client: any, guild: any, radio: any){ +import RadioClient from "../../Client"; + +export default function saveState(client: RadioClient, guild: any, radio: any){ + if(!client.datastore) return; client.datastore.checkEntry(guild.id); let date = new Date(); diff --git a/src/client/utils/typings.ts b/src/client/utils/typings.ts index 1e5d860..e69de29 100644 --- a/src/client/utils/typings.ts +++ b/src/client/utils/typings.ts @@ -1,3 +0,0 @@ -export interface command { } - -export interface radio {} From 5be3b29300fc3d8943ff6ae68616114c1f04f76f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Mon, 5 Jun 2023 00:15:06 +0300 Subject: [PATCH 11/44] Change em dash to dash in Stations class --- src/client/classes/Stations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index a827eed..610c676 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -13,7 +13,7 @@ export default class Stations extends Array { async fetch(options: any){ try { - this.logger('Stations', 'Started fetching list – ' + options.url); + this.logger('Stations', 'Started fetching list - ' + options.url); let list = await fetch(options.url) .then(this.checkFetchStatus) .then((response: { json: () => any; }) => response.json()); From 7acabe411b031e46ddf6245230c34bc1ab94f069 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 08:56:47 +0000 Subject: [PATCH 12/44] Bump dotenv from 16.1.3 to 16.1.4 Bumps [dotenv](https://github.com/motdotla/dotenv) from 16.1.3 to 16.1.4. - [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md) - [Commits](https://github.com/motdotla/dotenv/compare/v16.1.3...v16.1.4) --- updated-dependencies: - dependency-name: dotenv dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 42bad5f..ff6f7dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@discordjs/voice": "^0.16.0", "discord-api-types": "^0.37.43", "discord.js": "^14.11.0", - "dotenv": "^16.1.3", + "dotenv": "^16.1.4", "libsodium-wrappers": "^0.7.11", "node-fetch": "^3.3.1", "path": "^0.12.7" @@ -1094,9 +1094,9 @@ } }, "node_modules/dotenv": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.3.tgz", - "integrity": "sha512-FYssxsmCTtKL72fGBSvb1K9dRz0/VZeWqFme/vSb7r7323x4CRaHu4LvQ5JG3+s6yt2YPbBrkpiEODktfyjI9A==", + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.4.tgz", + "integrity": "sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==", "engines": { "node": ">=12" }, @@ -3994,9 +3994,9 @@ } }, "dotenv": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.3.tgz", - "integrity": "sha512-FYssxsmCTtKL72fGBSvb1K9dRz0/VZeWqFme/vSb7r7323x4CRaHu4LvQ5JG3+s6yt2YPbBrkpiEODktfyjI9A==" + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.4.tgz", + "integrity": "sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==" }, "duplexer": { "version": "0.1.2", diff --git a/package.json b/package.json index fbedd5a..5d29fc1 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@discordjs/voice": "^0.16.0", "discord-api-types": "^0.37.43", "discord.js": "^14.11.0", - "dotenv": "^16.1.3", + "dotenv": "^16.1.4", "libsodium-wrappers": "^0.7.11", "node-fetch": "^3.3.1", "path": "^0.12.7" From 2d17c33d21734384119c7da71952f2d2613bb9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 01:39:35 +0300 Subject: [PATCH 13/44] Typescript Continue --- src/Client.ts | 17 ++-- src/client/classes/Datastore.ts | 3 +- src/client/classes/Radio.ts | 8 +- src/client/classes/Stations.ts | 16 +++- src/client/classes/Statistics.ts | 21 +++-- src/client/classes/Streamer.ts | 15 ++- src/client/commands/bug.ts | 5 + src/client/commands/help.ts | 10 +- src/client/commands/invite.ts | 6 ++ src/client/commands/list.ts | 2 +- src/client/commands/maintenance.ts | 121 ++++++++++++++++--------- src/client/commands/next.ts | 14 ++- src/client/commands/nowplaying.ts | 4 +- src/client/commands/play.ts | 54 ++++++----- src/client/commands/prev.ts | 12 ++- src/client/commands/statistics.ts | 6 ++ src/client/commands/status.ts | 11 ++- src/client/commands/stop.ts | 8 +- src/client/emojis.ts | 2 +- src/client/events.ts | 2 +- src/client/events/SIGINT.ts | 2 +- src/client/events/interactionCreate.ts | 7 ++ src/client/events/messageDelete.ts | 6 +- src/client/events/ready.ts | 6 +- src/client/events/voiceStateUpdate.ts | 2 +- src/client/funcs.ts | 2 +- src/client/funcs/check.ts | 10 +- src/client/funcs/logger.ts | 4 +- src/client/funcs/play.ts | 2 +- src/client/messages.ts | 2 +- src/client/utils/typings.ts | 0 src/config.ts | 2 +- 32 files changed, 233 insertions(+), 149 deletions(-) delete mode 100644 src/client/utils/typings.ts diff --git a/src/Client.ts b/src/Client.ts index 29840f9..1a85951 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -6,9 +6,9 @@ import Streamer from "./client/classes/Streamer"; import Statistics from "./client/classes/Statistics"; import { command } from "./client/commands"; import config from "./config"; -import messages from "./client/messages"; -import events from "./client/events" -import funcs from "./client/funcs"; +import { messages } from "./client/messages"; +import { events } from "./client/events" +import { funcs } from "./client/funcs"; const GatewayIntents = new IntentsBitField(); GatewayIntents.add( @@ -19,8 +19,8 @@ GatewayIntents.add( export default class RadioClient extends Client { readonly commands: Collection; - public events: any; - public funcs: any; + readonly events = events; + readonly funcs = funcs; readonly config = config; readonly messages = messages; public datastore: Datastore | null; @@ -43,9 +43,6 @@ export default class RadioClient extends Client { this.radio = null; this.messageEmojis = null; - this.events = events; - this.funcs = funcs; - console.log('RadioX ' + this.config.version); console.log('Internet Radio to your Discord guild'); console.log('(c)2020-2022 EximiaBots by Warén Group'); @@ -73,7 +70,7 @@ export default class RadioClient extends Client { }); this.on("error", error => { - this.funcs.logger("Discord Client / Error"); + this.funcs.logger("Discord Client", "Error"); console.error(error); console.log(''); }); @@ -99,7 +96,7 @@ export default class RadioClient extends Client { }); this.login(this.config.token).catch((err) => { - this.funcs.logger("Discord Client / Error"); + this.funcs.logger("Discord Client", "Login Error"); console.log(err); console.log(''); }); diff --git a/src/client/classes/Datastore.ts b/src/client/classes/Datastore.ts index c8e0bbe..cc7fa2a 100644 --- a/src/client/classes/Datastore.ts +++ b/src/client/classes/Datastore.ts @@ -28,7 +28,8 @@ export default class { //console.log(""); } - checkEntry(id: string){ + checkEntry(id: string | undefined){ + if(!id) return; this.loadEntry(id); if(!this.map.has(id)){ this.createEntry(id); diff --git a/src/client/classes/Radio.ts b/src/client/classes/Radio.ts index 690979d..ca9de72 100644 --- a/src/client/classes/Radio.ts +++ b/src/client/classes/Radio.ts @@ -1,5 +1,5 @@ import { getVoiceConnection, joinVoiceChannel } from "@discordjs/voice"; -import { VoiceChannel } from "discord.js"; +import { Guild, GuildMember, VoiceChannel } from "discord.js"; import RadioClient from "../../Client"; export default class Radio extends Map { @@ -32,13 +32,13 @@ export default class Radio extends Map { restore(client: RadioClient, guilds: any) { if(!client.stations) return; - guilds.forEach(async (guild: { id: any; }) => { + guilds.forEach(async (guild: Guild) => { let state = client.funcs.loadState(client, guild); if(!state) return; if(!state.station || !state.channels.voice || !state.channels.text) return; let voiceChannel = client.channels.cache.get(state.channels.voice); - if(!voiceChannel) return; - if(voiceChannel.members.filter((member: { user: { bot: any; }; }) => !member.user.bot).size === 0) return; + if(!voiceChannel || !(voiceChannel instanceof VoiceChannel)) return; + if(voiceChannel.members.filter((member: GuildMember) => !member.user.bot).size === 0) return; const sstation = await client.stations?.search(state.station.name, "direct"); diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index 610c676..5f555ce 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -3,17 +3,23 @@ const _importDynamic = new Function('modulePath', 'return import(modulePath)'); const fetch = (...args: any) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); import logger from "../funcs/logger"; +export interface station { + name: string, + owner: string, + logo: string, + stream: [] +} + export default class Stations extends Array { logger: any; constructor() { super(); - this.logger = logger; } async fetch(options: any){ try { - this.logger('Stations', 'Started fetching list - ' + options.url); + logger('Stations', 'Started fetching list - ' + options.url); let list = await fetch(options.url) .then(this.checkFetchStatus) .then((response: { json: () => any; }) => response.json()); @@ -30,7 +36,7 @@ export default class Stations extends Array { if(options.show){ list.forEach((station: { name: any; }) => { - this.logger('Stations', station.name); + logger('Stations', station.name); }); } @@ -45,9 +51,9 @@ export default class Stations extends Array { }); } - this.logger('Stations', 'Successfully fetched list'); + logger('Stations', 'Successfully fetched list'); } catch (error) { - this.logger('Stations', 'Fetching list failed'); + logger('Stations', 'Fetching list failed'); console.error(error + "\n"); if(this.length == 0) this.fetch(options); diff --git a/src/client/classes/Statistics.ts b/src/client/classes/Statistics.ts index d2dc52f..7f21fb0 100644 --- a/src/client/classes/Statistics.ts +++ b/src/client/classes/Statistics.ts @@ -8,7 +8,8 @@ export default class Statistics { this.map = new Map(); } - update(client: RadioClient, guild: Guild, radio: any) { + update(client: RadioClient, guild: Guild | null, radio: any) { + if(!guild) return; client.datastore?.checkEntry(guild.id); @@ -47,18 +48,18 @@ export default class Statistics { let currentGuild = client.datastore.getEntry(calculation.value); if(calculation.value != 'global'){ if(stations){ - Object.keys(stations).forEach(function(station) { - if(currentGuild.statistics[stations[station].name] && currentGuild.statistics[stations[station].name].time && parseInt(currentGuild.statistics[stations[station].name].time) != 0 && currentGuild.statistics[stations[station].name].used && parseInt(currentGuild.statistics[stations[station].name].used) != 0){ - if(!statistics[stations[station].name]){ - statistics[stations[station].name] = {}; - statistics[stations[station].name].time = 0; - statistics[stations[station].name].used = 0; + for(const station of stations) { + if(currentGuild.statistics[station.name] && currentGuild.statistics[station.name].time && parseInt(currentGuild.statistics[station.name].time) != 0 && currentGuild.statistics[station.name].used && parseInt(currentGuild.statistics[station.name].used) != 0){ + if(!statistics[station.name]){ + statistics[station.name] = {}; + statistics[station.name].time = 0; + statistics[station.name].used = 0; } - statistics[stations[station].name].time = parseInt(statistics[stations[station].name].time)+parseInt(currentGuild.statistics[stations[station].name].time); - statistics[stations[station].name].used = parseInt(statistics[stations[station].name].used)+parseInt(currentGuild.statistics[stations[station].name].used); + statistics[station.name].time = parseInt(statistics[station.name].time)+parseInt(currentGuild.statistics[station.name].time); + statistics[station.name].used = parseInt(statistics[station.name].used)+parseInt(currentGuild.statistics[station.name].used); } - }); + } } } calculation = guilds.next(); diff --git a/src/client/classes/Streamer.ts b/src/client/classes/Streamer.ts index 14c0da2..5b6cce2 100644 --- a/src/client/classes/Streamer.ts +++ b/src/client/classes/Streamer.ts @@ -10,7 +10,6 @@ export default class Streamer { constructor() { this.map = new Map(); this.mode = null; - this.logger = logger; } init(client: RadioClient){ @@ -73,25 +72,25 @@ export default class Streamer { audioPlayer.play(resource); audioPlayer .on('playing', () => { - this.logger('Streamer', station.name + " / " + "Playing"); + logger('Streamer', station.name + " / " + "Playing"); }) .on('idle', () => { - this.logger('Streamer', station.name + " / " + "Idle"); + logger('Streamer', station.name + " / " + "Idle"); audioPlayer.removeAllListeners(); if(this.mode == "manual" && audioPlayer.subscribers.length == 0) return; this.play(station); }) .on('paused', () => { - this.logger('Streamer', station.name + " / " + "Paused"); + logger('Streamer', station.name + " / " + "Paused"); }) .on('buffering', () => { - this.logger('Streamer', station.name + " / " + "Buffering"); + logger('Streamer', station.name + " / " + "Buffering"); }) .on('autopaused', () => { - this.logger('Streamer', station.name + " / " + "AutoPaused"); + logger('Streamer', station.name + " / " + "AutoPaused"); }) .on('error', (error: string) => { - this.logger('Streamer', station.name + " / " + "Error" + "\n" + error); + logger('Streamer', station.name + " / " + "Error" + "\n" + error); }); return audioPlayer; } @@ -99,7 +98,7 @@ export default class Streamer { stop(station: any){ let audioPlayer = this.map.get(station.name); if(audioPlayer){ - this.logger('Streamer', station.name + " / " + "Stop"); + logger('Streamer', station.name + " / " + "Stop"); audioPlayer.removeAllListeners(); audioPlayer.stop(); } diff --git a/src/client/commands/bug.ts b/src/client/commands/bug.ts index 2819fc5..f3a4b18 100644 --- a/src/client/commands/bug.ts +++ b/src/client/commands/bug.ts @@ -6,6 +6,11 @@ export default { description: 'Report a bug', category: 'info', async execute(interaction: ChatInputCommandInteraction, client: RadioClient) { + if(!client.user) return interaction.reply({ + content: client.messageEmojis["error"] + client.messages.maintenance, + ephemeral: true + }); + let message : any = {}; message.bugTitle = client.messages.bugTitle.replace("%client.user.username%", client.user.username); diff --git a/src/client/commands/help.ts b/src/client/commands/help.ts index 8541041..8078419 100644 --- a/src/client/commands/help.ts +++ b/src/client/commands/help.ts @@ -6,6 +6,12 @@ export default { description: 'Get help using bot', category: 'info', execute(interaction: ChatInputCommandInteraction, client: RadioClient) { + + if(!client.user) return interaction.reply({ + content: client.messageEmojis["error"] + client.messages.maintenance, + ephemeral: true + }); + let message: any = {}; const categories : any= []; @@ -14,10 +20,10 @@ export default { } let commands = ''; for (let i = 0; i < categories.length; i++) { - commands += `**» ${categories[i].toUpperCase()}**\n${client.commands.filter((x: { category: any; omitFromHelp: any; }) => x.category === categories[i] && !x.omitFromHelp).map((x: { name: any; }) => `\`${x.name}\``).join(', ')}\n`; + commands += `**» ${categories[i].toUpperCase()}**\n${client.commands.filter(x => x.category === categories[i]).map((x: { name: any; }) => `\`${x.name}\``).join(', ')}\n`; } - message.helpTitle = client.messages.helpTitle.replace("%client.user.username%", client.user.username); + message.helpTitle = client.messages.helpTitle.replace("%client.user.username%", client.user?.username || "-"); message.helpDescription = client.messages.helpDescription.replace("%commands%", commands); const embed = new EmbedBuilder() diff --git a/src/client/commands/invite.ts b/src/client/commands/invite.ts index a879e8e..a8fc1e7 100644 --- a/src/client/commands/invite.ts +++ b/src/client/commands/invite.ts @@ -6,6 +6,12 @@ export default { description: 'Invite Bot', category: 'info', execute(interaction: ChatInputCommandInteraction, client: RadioClient) { + + if(!client.user) return interaction.reply({ + content: client.messageEmojis["error"] + client.messages.maintenance, + ephemeral: true + }); + let message: any = {}; message.inviteTitle = client.messages.inviteTitle.replace("%client.user.username%", client.user.username); const embed = new EmbedBuilder() diff --git a/src/client/commands/list.ts b/src/client/commands/list.ts index e90066b..beac6e5 100644 --- a/src/client/commands/list.ts +++ b/src/client/commands/list.ts @@ -16,7 +16,7 @@ export default { }); } - const radio = client.radio?.get(interaction.guild.id); + const radio = client.radio?.get(interaction.guild?.id); if(radio && !client.config.maintenanceMode){ client.funcs.listStations(client, interaction); diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index da61e74..42fcc2a 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -1,4 +1,4 @@ -import { ActionRowBuilder, ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js"; +import { ActionRowBuilder, AnyComponentBuilder, APIActionRowComponent, APISelectMenuOption, ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import Streamer from "../classes/Streamer"; import commands from "../commands"; @@ -17,62 +17,95 @@ export default { content: client.messageEmojis["error"] + client.messages.notAllowed, ephemeral: true }); - let action = interaction.options?.getNumber("action") ?? interaction.values?.[0]; - const options: any = new Array( + + let action : number | string | null = null; + + if(interaction.isChatInputCommand()){ + action = interaction.options?.getNumber("action"); + } + + if(interaction.isStringSelectMenu()){ + action = interaction.values?.[0]; + } + + const options: APISelectMenuOption[] = new Array( { - emoji: "🌀", + emoji: { + "name": "🌀", + }, label: "Restart Bot", value: "0" }, { - emoji: "<:RadioXStop:688541155377414168>", + emoji: { + id: "688541155377414168", + name: "RadioXStop", + }, label: "Save Radios", value: "4" }, { - emoji: "<:RadioXPlay:688541155712827458>", + emoji: { + id: "688541155712827458", + name: "RadioXPlay", + }, label: "Restore Radios", value: "5" }, { - emoji: "#️⃣", + emoji: { + name: "#️⃣", + }, label: "Reload Commands", value: "6" }, { - emoji: "<:RadioXList:688541155519889482>", + emoji: { + id: "688541155519889482", + name: "RadioXList", + }, label: "Reload Stations", value: "7" }, { - emoji: "<:dnd:746069698139127831>", + emoji: { + id: "746069698139127831", + name: "dnd", + }, label: "Enable Maintenance Mode", value: "8" }, { - emoji: "<:online:746069731836035098>", + emoji: { + id: "746069731836035098", + name: "online", + }, label: "Disable Maintenance Mode", value: "9" }, { - emoji: "💤", + emoji: { + name: "💤", + }, label: "Streamer Mode - Manual", value: "10" }, { - emoji: "📡", + emoji: { + name: "📡", + }, label: "Streamer Mode - Auto", value: "11" } ); - const menu = new ActionRowBuilder() - .addComponents( - new StringSelectMenuBuilder() - .setCustomId('maintenance') - .setPlaceholder('Select action') - .addOptions(options) - ); + const menu : ActionRowBuilder = new ActionRowBuilder() + .addComponents( + new StringSelectMenuBuilder() + .setCustomId('maintenance') + .setPlaceholder('Select action') + .addOptions(options) + ); if(!action){ return interaction.reply({ @@ -82,12 +115,12 @@ export default { }); } - client.funcs.logger('Maintenance', options.find((option: { value: any; }) => option.value == action).label); + client.funcs.logger('Maintenance', options.find((option: APISelectMenuOption) => option.value == action)?.label); const embed = new EmbedBuilder() .setTitle(client.messages.maintenanceTitle) .setColor(client.config.embedColor as ColorResolvable) - .setDescription(options.find((option: { value: any; }) => option.value == action).label) + .setDescription(options.find((option: APISelectMenuOption) => option.value == action)?.label || "-") .setFooter({ text: client.messages.footerText, iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') @@ -107,43 +140,43 @@ export default { break; case "4": client.config.maintenanceMode = true; - client.user.setStatus('idle'); - client.radio.save(client); - client.user.setStatus('online'); + client.user?.setStatus('idle'); + client.radio?.save(client); + client.user?.setStatus('online'); client.config.maintenanceMode = false; break; case "5": client.config.maintenanceMode = true; - client.user.setStatus('idle'); - client.radio.restore(client, guilds); - client.user.setStatus('online'); + client.user?.setStatus('idle'); + client.radio?.restore(client, guilds); + client.user?.setStatus('online'); client.config.maintenanceMode = false; break; case "6": client.config.maintenanceMode = true; - client.user.setStatus('idle'); + client.user?.setStatus('idle'); commands.execute(client); - client.user.setStatus('online'); + client.user?.setStatus('online'); client.config.maintenanceMode = false; break; case "7": try { - client.stations.fetch({ + client.stations?.fetch({ url: client.config.stationslistUrl }); - client.streamer.refresh(client); + client.streamer?.refresh(client); } catch (error) { } break; case "8": - client.user.setStatus('dnd'); + client.user?.setStatus('dnd'); client.funcs.logger("Maintenance Mode", "Enabled"); client.config.maintenanceMode = true; break; case "9": - client.user.setStatus('online'); + client.user?.setStatus('online'); client.funcs.logger("Maintenance Mode", "Disabled"); client.config.maintenanceMode = false; break; @@ -151,17 +184,17 @@ export default { client.config.streamerMode = "manual"; client.config.maintenanceMode = true; - client.user.setStatus('idle'); - client.radio.save(client); + client.user?.setStatus('idle'); + client.radio?.save(client); setInterval(() => { - if(client.radio.size == 0 && client.config.streamerMode == "manual" && client.config.maintenanceMode){ - client.streamer.leave(client); + if(client.radio?.size == 0 && client.config.streamerMode == "manual" && client.config.maintenanceMode){ + client.streamer?.leave(client); client.streamer = new Streamer(); client.streamer.init(client); - client.radio.restore(client, guilds); - client.user.setStatus('online'); + client.radio?.restore(client, guilds); + client.user?.setStatus('online'); client.config.maintenanceMode = false; } @@ -175,17 +208,17 @@ export default { client.config.streamerMode = "auto"; client.config.maintenanceMode = true; - client.user.setStatus('idle'); - client.radio.save(client); + client.user?.setStatus('idle'); + client.radio?.save(client); setInterval(() => { - if(client.radio.size == 0 && client.config.streamerMode == "auto" && client.config.maintenanceMode){ - client.streamer.leave(client); + if(client.radio?.size == 0 && client.config.streamerMode == "auto" && client.config.maintenanceMode){ + client.streamer?.leave(client); client.streamer = new Streamer(); client.streamer.init(client); client.radio.restore(client, guilds); - client.user.setStatus('online'); + client.user?.setStatus('online'); client.config.maintenanceMode = false; } diff --git a/src/client/commands/next.ts b/src/client/commands/next.ts index ec5d00f..5b6ba54 100644 --- a/src/client/commands/next.ts +++ b/src/client/commands/next.ts @@ -1,5 +1,6 @@ import { ButtonInteraction, ChatInputCommandInteraction, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; +import { station } from "../classes/Stations" export default { name: 'next', @@ -7,10 +8,15 @@ export default { category: 'radio', async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: any) { if (client.funcs.check(client, interaction, command)) { - const radio = client.radio.get(interaction.guild.id); + const radio = client.radio?.get(interaction.guild?.id); - let index = client.stations.findIndex((station: { name: any; }) => station.name == radio.station.name) + 1; - if(index == client.stations.length) index = 0; + if(!client.stations) return interaction.reply({ + content: client.messageEmojis["error"] + client.messages.maintenance, + ephemeral: true + }); + + let index: number = client.stations.findIndex((station: station) => station.name == radio.station.name) + 1; + if(index == client.stations?.length) index = 0; let station = client.stations[index]; @@ -19,7 +25,7 @@ export default { ephemeral: true }); - client.statistics.update(client, interaction.guild, radio); + client.statistics?.update(client, interaction.guild, radio); let date = new Date(); radio.station = station; diff --git a/src/client/commands/nowplaying.ts b/src/client/commands/nowplaying.ts index c991951..41fe19e 100644 --- a/src/client/commands/nowplaying.ts +++ b/src/client/commands/nowplaying.ts @@ -6,9 +6,9 @@ export default { description: 'Current Radio Station', category: 'radio', async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: any) { - if (client.funcs.check(client, interaction, command)) { + if(client.funcs.check(client, interaction, command)) { let message: any = {}; - const radio = client.radio?.get(interaction.guild.id); + const radio = client.radio?.get(interaction.guild?.id); let date = new Date(); radio.currentTime = date.getTime(); diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index 9e6e1b0..ba378a5 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -1,4 +1,4 @@ -import { ApplicationCommandOptionType, ButtonInteraction, ChatInputCommandInteraction, PermissionFlagsBits, StringSelectMenuInteraction } from "discord.js"; +import { ApplicationCommandOptionType, ChatInputCommandInteraction, GuildMember, PermissionFlagsBits, StringSelectMenuInteraction } from "discord.js"; import { getVoiceConnection, joinVoiceChannel } from "@discordjs/voice"; import RadioClient from "../../Client"; @@ -10,16 +10,9 @@ export default { { type: ApplicationCommandOptionType.String, name: "query", description: "Select station", required: false} ], category: "radio", - async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { + async execute(interaction: ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { let message: any = {}; - if(client.config.maintenanceMode){ - return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.maintenance, - ephemeral: true - }); - } - if(!client.stations) { message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); return interaction.reply({ @@ -28,13 +21,23 @@ export default { }); } - let query = interaction.options?.getString("query") ?? interaction.values?.[0]; + let query : number | string | null = null; + + if(interaction.isChatInputCommand()){ + query = interaction.options?.getNumber("query"); + } + + if(interaction.isStringSelectMenu()){ + query = interaction.values?.[0]; + } + if(!query){ return client.funcs.listStations(client, interaction); } - const radio = client.radio.get(interaction.guild.id); - const voiceChannel = interaction.member.voice.channel; + const radio = client.radio?.get(interaction.guild?.id); + if(!(interaction.member instanceof GuildMember)) return; + const voiceChannel = interaction.member?.voice.channel; if (!voiceChannel) return interaction.reply({ content: client.messageEmojis["error"] + client.messages.noVoiceChannel, ephemeral: true @@ -50,13 +53,13 @@ export default { ephemeral: true }); const permissions = voiceChannel.permissionsFor(interaction.client.user); - if (!permissions.has(PermissionFlagsBits.Connect)) { + if (!permissions?.has(PermissionFlagsBits.Connect)) { return interaction.reply({ content: client.messageEmojis["error"] + client.messages.noPermsConnect, ephemeral: true }); } - if (!permissions.has(PermissionFlagsBits.Speak)) { + if (!permissions?.has(PermissionFlagsBits.Speak)) { return interaction.reply({ content: client.messageEmojis["error"] + client.messages.noPermsSpeak, ephemeral: true @@ -64,7 +67,7 @@ export default { } let station; - if (!isNaN(query)) { + if (typeof query === 'number') { const number = parseInt((query - 1) as unknown as string); if (number > client.stations.length - 1) { return interaction.reply({ @@ -75,17 +78,20 @@ export default { station = client.stations[number]; } } else { - if (query.length < 3) return interaction.reply({ + if(!(typeof query === 'string')) return; + if(query.length < 3) return interaction.reply({ content: client.messageEmojis["error"] + client.messages.tooShortSearch, ephemeral: true }); let type = ""; - if(interaction.values?.[0]){ - type = "direct"; - } else { - type = "text"; + if(interaction.isStringSelectMenu()){ + if(interaction.values?.[0]){ + type = "direct"; + } else { + type = "text"; + } } const sstation = await client.stations.search(query, type); @@ -97,7 +103,7 @@ export default { } if (radio) { - client.statistics.update(client, interaction.guild, radio); + client.statistics?.update(client, interaction.guild, radio); let date = new Date(); radio.station = station; @@ -117,7 +123,7 @@ export default { station: station, startTime: date.getTime() }; - client.radio.set(interaction.guild.id, construct); + client.radio?.set(interaction.guild?.id, construct); try { const connection = @@ -130,11 +136,11 @@ export default { construct.connection = connection; let date = new Date(); construct.startTime = date.getTime(); - client.datastore.checkEntry(interaction.guild.id); + client.datastore?.checkEntry(interaction.guild?.id); client.funcs.play(client, interaction, interaction.guild, station); } catch (error) { console.log(error); - client.radio.delete(interaction.guild.id); + client.radio?.delete(interaction.guild?.id); return interaction.reply({ content: client.messageEmojis["error"] + `An error occured: ${error}`, ephemeral: true diff --git a/src/client/commands/prev.ts b/src/client/commands/prev.ts index 55e1030..6e6e707 100644 --- a/src/client/commands/prev.ts +++ b/src/client/commands/prev.ts @@ -1,6 +1,7 @@ import { ButtonInteraction, ChatInputCommandInteraction, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import { command } from "../commands"; +import { station } from "../classes/Stations" export default { name: 'prev', @@ -8,9 +9,14 @@ export default { category: 'radio', async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: command) { if (client.funcs.check(client, interaction, command)) { - const radio = client.radio.get(interaction.guild.id); + const radio = client.radio?.get(interaction.guild?.id); - let index = client.stations.findIndex((station: { name: any; }) => station.name == radio.station.name) - 1; + if(!client.stations) return interaction.reply({ + content: client.messageEmojis["error"] + client.messages.maintenance, + ephemeral: true + }); + + let index = client.stations.findIndex((station: station) => station.name == radio.station.name) - 1; if(index == -1) index = client.stations.length - 1; let station = client.stations[index]; @@ -20,7 +26,7 @@ export default { ephemeral: true }); - client.statistics.update(client, interaction.guild, radio); + client.statistics?.update(client, interaction.guild, radio); let date = new Date(); radio.station = station; diff --git a/src/client/commands/statistics.ts b/src/client/commands/statistics.ts index 85eba3a..73978fb 100644 --- a/src/client/commands/statistics.ts +++ b/src/client/commands/statistics.ts @@ -8,6 +8,12 @@ export default { category: 'info', execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { let message: any = {}; + + if(!interaction.guild) return interaction.reply({ + content: client.messageEmojis["error"] + client.messages.maintenance, + ephemeral: true + }); + let stations = client.stations; let currentGuild = client.datastore?.getEntry(interaction.guild.id); let global = client.datastore?.getEntry("global"); diff --git a/src/client/commands/status.ts b/src/client/commands/status.ts index 1516221..52e1bb3 100644 --- a/src/client/commands/status.ts +++ b/src/client/commands/status.ts @@ -8,20 +8,25 @@ export default { async execute(interaction: any, client: RadioClient) { let message: any = {}; + if(!client.user) return interaction.reply({ + content: client.messageEmojis["error"] + client.messages.maintenance, + ephemeral: true + }); + message.statusTitle = client.messages.statusTitle.replace("%client.user.username%", client.user.username); - let uptime = client.funcs.msToTime(client.uptime); + let uptime = client.funcs.msToTime(client.uptime || 0); const embed = new EmbedBuilder() .setTitle(message.statusTitle) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, '')) .setColor(client.config.embedColor as ColorResolvable) - .addFields( + .addFields([ { name: client.messages.statusField1, value: uptime }, { name: client.messages.statusField2, value: client.config.version }, { name: client.messages.statusField3, value: Date.now() - interaction.createdTimestamp + "ms" }, { name: client.messages.statusField4, value: client.ws.ping.toString() }, { name: client.messages.statusField5, value: client.config.hostedBy } - ) + ]) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, diff --git a/src/client/commands/stop.ts b/src/client/commands/stop.ts index 6e2a223..92024c2 100644 --- a/src/client/commands/stop.ts +++ b/src/client/commands/stop.ts @@ -7,13 +7,13 @@ export default { category: 'radio', async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: any) { if (client.funcs.check(client, interaction, command)) { - const radio = client.radio?.get(interaction.guild.id); + const radio = client.radio?.get(interaction.guild?.id); client.statistics?.update(client, interaction.guild, radio); radio.connection?.destroy(); - client.funcs.logger('Radio', interaction.guild.id + " / " + 'Stop'); + client.funcs.logger('Radio', interaction.guild?.id + " / " + 'Stop'); const embed = new EmbedBuilder() - .setTitle(client.user.username) + .setTitle(client.user?.username || "-") .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["stop"].replace(/[^0-9]+/g, '')) .setColor(client.config.embedColor as ColorResolvable) .addFields({ @@ -40,7 +40,7 @@ export default { await radio.message?.delete(); }, 5000); - client.radio?.delete(interaction.guild.id); + client.radio?.delete(interaction.guild?.id); interaction.reply({ content: client.messageEmojis["stop"] + client.messages.stop, diff --git a/src/client/emojis.ts b/src/client/emojis.ts index 119f2bb..b7cc2e0 100644 --- a/src/client/emojis.ts +++ b/src/client/emojis.ts @@ -1,6 +1,6 @@ import RadioClient from "../Client"; -export default { +export const emojis = { name: 'emojis', async execute(client: RadioClient): Promise { let customEmojis: any = { diff --git a/src/client/events.ts b/src/client/events.ts index dc32b06..811a92c 100644 --- a/src/client/events.ts +++ b/src/client/events.ts @@ -7,6 +7,6 @@ import uncaughtException from "./events/uncaughtException" import voiceStateUpdate from "./events/voiceStateUpdate" import warning from "./events/warning" -export default { +export const events = { interactionCreate, messageDelete, ready, SIGINT, SIGTERM, uncaughtException, voiceStateUpdate, warning } diff --git a/src/client/events/SIGINT.ts b/src/client/events/SIGINT.ts index 97828cc..b3aa1cf 100644 --- a/src/client/events/SIGINT.ts +++ b/src/client/events/SIGINT.ts @@ -3,7 +3,7 @@ import RadioClient from "../../Client"; export default { name: 'SIGINT', execute(client: RadioClient) { - client.user.setStatus('dnd'); + client.user?.setStatus('dnd'); client.streamer?.leave(client); client.radio?.save(client); diff --git a/src/client/events/interactionCreate.ts b/src/client/events/interactionCreate.ts index b396b68..0f886b1 100644 --- a/src/client/events/interactionCreate.ts +++ b/src/client/events/interactionCreate.ts @@ -5,6 +5,13 @@ export default { name: 'interactionCreate', async execute(client: RadioClient, interaction: any) { + if(client.config.maintenanceMode){ + return interaction.reply({ + content: client.messageEmojis["error"] + client.messages.maintenance, + ephemeral: true + }); + } + const permissions = interaction.channel.permissionsFor(interaction.client.user); if (!permissions.has(PermissionFlagsBits.ViewChannel)) return; diff --git a/src/client/events/messageDelete.ts b/src/client/events/messageDelete.ts index 99a2b73..89584c6 100644 --- a/src/client/events/messageDelete.ts +++ b/src/client/events/messageDelete.ts @@ -1,10 +1,10 @@ -import { Message } from "discord.js"; +import { Message, PartialMessage } from "discord.js"; import RadioClient from "../../Client"; export default { name: 'messageDelete', - async execute(client: RadioClient, msg: Message) { - if(!msg.author.bot || !msg.guild) return; + async execute(client: RadioClient, msg: Message | PartialMessage) { + if(!msg.author?.bot || !msg.guild) return; const radio = client.radio?.get(msg.guild.id); if(!radio) return; if(!radio.message) return; diff --git a/src/client/events/ready.ts b/src/client/events/ready.ts index e080aa7..128474b 100644 --- a/src/client/events/ready.ts +++ b/src/client/events/ready.ts @@ -4,7 +4,7 @@ import Radio from "../classes/Radio"; import Stations from "../classes/Stations"; import Streamer from "../classes/Streamer"; import Statistics from "../classes/Statistics"; -import emojis from "../emojis" +import { emojis } from "../emojis" import commands from "../commands"; export default { @@ -48,7 +48,7 @@ export default { client.streamer.init(client); if(!client.stations) { - client.user.setStatus('dnd'); + client.user?.setStatus('dnd'); } /*GUILDS*/ @@ -76,7 +76,7 @@ export default { setTimeout(function () { /*RESTORE RADIOS*/ - client.radio.restore(client, guilds); + client.radio?.restore(client, guilds); }, 5000); setTimeout(function () { diff --git a/src/client/events/voiceStateUpdate.ts b/src/client/events/voiceStateUpdate.ts index caee4ef..8c7600c 100644 --- a/src/client/events/voiceStateUpdate.ts +++ b/src/client/events/voiceStateUpdate.ts @@ -13,7 +13,7 @@ export default { const radio = client.radio?.get(newState.guild.id); if (!radio) return; - if (newState.member?.id === client.user.id && oldState.member?.id === client.user.id) { + if (newState.member?.id === client.user?.id && oldState.member?.id === client.user?.id) { if (newState.channel === null) { client.statistics?.update(client, newState.guild, radio); diff --git a/src/client/funcs.ts b/src/client/funcs.ts index 5a2c7ae..259d2bc 100644 --- a/src/client/funcs.ts +++ b/src/client/funcs.ts @@ -7,6 +7,6 @@ import msToTime from "./funcs/msToTime"; import play from "./funcs/play"; import saveState from "./funcs/saveState"; -export default { +export const funcs = { check, isDev, listStations, loadState, logger, msToTime, play, saveState } diff --git a/src/client/funcs/check.ts b/src/client/funcs/check.ts index 434848e..b20e452 100644 --- a/src/client/funcs/check.ts +++ b/src/client/funcs/check.ts @@ -1,15 +1,9 @@ import RadioClient from "../../Client"; +import { command } from "../commands"; -export default function check(client: RadioClient, interaction: any, command: any) { +export default function check(client: RadioClient, interaction: any, command: command) { let message: any = {}; const radio = client.radio?.get(interaction.guild.id); - if(client.config.maintenanceMode){ - interaction.reply({ - content: client.messageEmojis["error"] + client.messages.maintenance, - ephemeral: true - }); - return false; - } if(!client.stations) { message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); interaction.reply({ diff --git a/src/client/funcs/logger.ts b/src/client/funcs/logger.ts index 830999d..5279de4 100644 --- a/src/client/funcs/logger.ts +++ b/src/client/funcs/logger.ts @@ -1,5 +1,5 @@ -export default function logger(area : string, text: string){ +export default function logger(area: string, text?: string){ let date = new Date(); console.log('[' + area + '] - ' + date.toISOString()); - if(text) console.log(text + '\n'); + if(text) console.log(text + '\n'); } diff --git a/src/client/funcs/play.ts b/src/client/funcs/play.ts index e717934..6af87a0 100644 --- a/src/client/funcs/play.ts +++ b/src/client/funcs/play.ts @@ -15,7 +15,7 @@ export default async function play(client: RadioClient, interaction: any, guild: message.nowplayingDescription = message.nowplayingDescription.replace("**", ""); const embed = new EmbedBuilder() - .setTitle(client.user.username) + .setTitle(client.user?.username || "-") .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, ''))) .setColor(client.config.embedColor as ColorResolvable) .addFields({ diff --git a/src/client/messages.ts b/src/client/messages.ts index 979038e..f9f4e11 100644 --- a/src/client/messages.ts +++ b/src/client/messages.ts @@ -1,4 +1,4 @@ -export default { +export const messages = { wrongVoiceChannel: "You need to be in the same voice channel as RadioX to use this command!", noPerms: "You need the %command.permission% permission to use this command!", notPlaying: "There is nothing playing!", diff --git a/src/client/utils/typings.ts b/src/client/utils/typings.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/config.ts b/src/config.ts index a00e8e9..747e8b1 100644 --- a/src/config.ts +++ b/src/config.ts @@ -18,7 +18,7 @@ export default { hostedBy: "[Warén Group](https://waren.io)", //Settings - version: process.env.DEV_MODE ? process.env.npm_package_version + "-dev" : process.env.npm_package_version, + version: process.env.DEV_MODE ? (process.env.npm_package_version ?? "0.0.0") + "-dev" : process.env.npm_package_version ?? "-", debug: process.env.DEBUG_MODE || false, devMode: process.env.DEV_MODE || false, maintenanceMode: false, From 348ac90cba4b571ef53d9859eba98f225f4b75d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 02:27:46 +0300 Subject: [PATCH 14/44] Move emojis to messages variable --- src/Client.ts | 5 ++- src/client/commands/bug.ts | 6 ++-- src/client/commands/help.ts | 6 ++-- src/client/commands/invite.ts | 4 +-- src/client/commands/list.ts | 6 ++-- src/client/commands/maintenance.ts | 4 +-- src/client/commands/next.ts | 4 +-- src/client/commands/nowplaying.ts | 4 +-- src/client/commands/play.ts | 18 +++++------ src/client/commands/prev.ts | 4 +-- src/client/commands/statistics.ts | 8 ++--- src/client/commands/status.ts | 6 ++-- src/client/commands/stop.ts | 6 ++-- src/client/emojis.ts | 44 -------------------------- src/client/events/interactionCreate.ts | 8 ++--- src/client/events/ready.ts | 4 --- src/client/funcs/check.ts | 7 ++-- src/client/funcs/play.ts | 16 +++++----- src/client/messages.ts | 14 +++++++- 19 files changed, 68 insertions(+), 106 deletions(-) delete mode 100644 src/client/emojis.ts diff --git a/src/Client.ts b/src/Client.ts index 1a85951..2bbd899 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -6,9 +6,10 @@ import Streamer from "./client/classes/Streamer"; import Statistics from "./client/classes/Statistics"; import { command } from "./client/commands"; import config from "./config"; -import { messages } from "./client/messages"; import { events } from "./client/events" import { funcs } from "./client/funcs"; +import { messages } from "./client/messages"; + const GatewayIntents = new IntentsBitField(); GatewayIntents.add( @@ -28,7 +29,6 @@ export default class RadioClient extends Client { public streamer: Streamer | null; public statistics: Statistics | null; public radio: Radio | null; - public messageEmojis: any | null; public developers: string | undefined; constructor() { @@ -41,7 +41,6 @@ export default class RadioClient extends Client { this.streamer = null; this.statistics = null; this.radio = null; - this.messageEmojis = null; console.log('RadioX ' + this.config.version); console.log('Internet Radio to your Discord guild'); diff --git a/src/client/commands/bug.ts b/src/client/commands/bug.ts index f3a4b18..06bf88b 100644 --- a/src/client/commands/bug.ts +++ b/src/client/commands/bug.ts @@ -7,7 +7,7 @@ export default { category: 'info', async execute(interaction: ChatInputCommandInteraction, client: RadioClient) { if(!client.user) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.maintenance, + content: client.messages.emojis["error"] + client.messages.maintenance, ephemeral: true }); @@ -18,13 +18,13 @@ export default { const embed = new EmbedBuilder() .setTitle(message.bugTitle) - .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, '')) + .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, '')) .setColor(client.config.embedColor as ColorResolvable) .setDescription(message.bugDescription) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, - iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') + iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '') }); interaction.reply({ diff --git a/src/client/commands/help.ts b/src/client/commands/help.ts index 8078419..d161c99 100644 --- a/src/client/commands/help.ts +++ b/src/client/commands/help.ts @@ -8,7 +8,7 @@ export default { execute(interaction: ChatInputCommandInteraction, client: RadioClient) { if(!client.user) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.maintenance, + content: client.messages.emojis["error"] + client.messages.maintenance, ephemeral: true }); @@ -28,13 +28,13 @@ export default { const embed = new EmbedBuilder() .setTitle(message.helpTitle) - .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, '')) + .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, '')) .setColor(client.config.embedColor as ColorResolvable) .setDescription(message.helpDescription) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, - iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') + iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '') }); interaction.reply({ diff --git a/src/client/commands/invite.ts b/src/client/commands/invite.ts index a8fc1e7..16d71d7 100644 --- a/src/client/commands/invite.ts +++ b/src/client/commands/invite.ts @@ -8,7 +8,7 @@ export default { execute(interaction: ChatInputCommandInteraction, client: RadioClient) { if(!client.user) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.maintenance, + content: client.messages.emojis["error"] + client.messages.maintenance, ephemeral: true }); @@ -21,7 +21,7 @@ export default { .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, - iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') + iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '') }); interaction.reply({ diff --git a/src/client/commands/list.ts b/src/client/commands/list.ts index beac6e5..7acc4a8 100644 --- a/src/client/commands/list.ts +++ b/src/client/commands/list.ts @@ -11,7 +11,7 @@ export default { if(!client.stations) { message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); return interaction.reply({ - content: client.messageEmojis["error"] + message.errorToGetPlaylist, + content: client.messages.emojis["error"] + message.errorToGetPlaylist, ephemeral: true }); } @@ -29,13 +29,13 @@ export default { let embed = new EmbedBuilder() .setTitle(client.messages.listTitle) - .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["list"].replace(/[^0-9]+/g, '')) + .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["list"].replace(/[^0-9]+/g, '')) .setColor(client.config.embedColor as ColorResolvable) .setDescription(stations) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, - iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') + iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '') }); interaction.reply({ diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index 42fcc2a..bc269f2 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -14,7 +14,7 @@ export default { let message: any = {}; if(!client.funcs.isDev(client.config.devId, interaction.user.id)) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.notAllowed, + content: client.messages.emojis["error"] + client.messages.notAllowed, ephemeral: true }); @@ -123,7 +123,7 @@ export default { .setDescription(options.find((option: APISelectMenuOption) => option.value == action)?.label || "-") .setFooter({ text: client.messages.footerText, - iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') + iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '') }); interaction.reply({ diff --git a/src/client/commands/next.ts b/src/client/commands/next.ts index 5b6ba54..02dc465 100644 --- a/src/client/commands/next.ts +++ b/src/client/commands/next.ts @@ -11,7 +11,7 @@ export default { const radio = client.radio?.get(interaction.guild?.id); if(!client.stations) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.maintenance, + content: client.messages.emojis["error"] + client.messages.maintenance, ephemeral: true }); @@ -21,7 +21,7 @@ export default { let station = client.stations[index]; if(!station) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.noSearchResults, + content: client.messages.emojis["error"] + client.messages.noSearchResults, ephemeral: true }); diff --git a/src/client/commands/nowplaying.ts b/src/client/commands/nowplaying.ts index 41fe19e..04e7a6b 100644 --- a/src/client/commands/nowplaying.ts +++ b/src/client/commands/nowplaying.ts @@ -21,13 +21,13 @@ export default { const embed = new EmbedBuilder() .setTitle(client.messages.nowplayingTitle) - .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, ''))) + .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messages.emojis["play"].replace(/[^0-9]+/g, ''))) .setColor(client.config.embedColor as ColorResolvable) .setDescription(message.nowplayingDescription) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, - iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') + iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '') }); interaction.reply({ diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index ba378a5..14b5b74 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -16,7 +16,7 @@ export default { if(!client.stations) { message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); return interaction.reply({ - content: client.messageEmojis["error"] + message.errorToGetPlaylist, + content: client.messages.emojis["error"] + message.errorToGetPlaylist, ephemeral: true }); } @@ -39,12 +39,12 @@ export default { if(!(interaction.member instanceof GuildMember)) return; const voiceChannel = interaction.member?.voice.channel; if (!voiceChannel) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.noVoiceChannel, + content: client.messages.emojis["error"] + client.messages.noVoiceChannel, ephemeral: true }); if (radio) { if (voiceChannel !== radio.voiceChannel) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.wrongVoiceChannel, + content: client.messages.emojis["error"] + client.messages.wrongVoiceChannel, ephemeral: true }); } @@ -55,13 +55,13 @@ export default { const permissions = voiceChannel.permissionsFor(interaction.client.user); if (!permissions?.has(PermissionFlagsBits.Connect)) { return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.noPermsConnect, + content: client.messages.emojis["error"] + client.messages.noPermsConnect, ephemeral: true }); } if (!permissions?.has(PermissionFlagsBits.Speak)) { return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.noPermsSpeak, + content: client.messages.emojis["error"] + client.messages.noPermsSpeak, ephemeral: true }); } @@ -71,7 +71,7 @@ export default { const number = parseInt((query - 1) as unknown as string); if (number > client.stations.length - 1) { return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.wrongStationNumber, + content: client.messages.emojis["error"] + client.messages.wrongStationNumber, ephemeral: true }); } else { @@ -80,7 +80,7 @@ export default { } else { if(!(typeof query === 'string')) return; if(query.length < 3) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.tooShortSearch, + content: client.messages.emojis["error"] + client.messages.tooShortSearch, ephemeral: true }); @@ -96,7 +96,7 @@ export default { const sstation = await client.stations.search(query, type); if (!sstation) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.noSearchResults, + content: client.messages.emojis["error"] + client.messages.noSearchResults, ephemeral: true }); station = sstation; @@ -142,7 +142,7 @@ export default { console.log(error); client.radio?.delete(interaction.guild?.id); return interaction.reply({ - content: client.messageEmojis["error"] + `An error occured: ${error}`, + content: client.messages.emojis["error"] + `An error occured: ${error}`, ephemeral: true }); } diff --git a/src/client/commands/prev.ts b/src/client/commands/prev.ts index 6e6e707..d705c46 100644 --- a/src/client/commands/prev.ts +++ b/src/client/commands/prev.ts @@ -12,7 +12,7 @@ export default { const radio = client.radio?.get(interaction.guild?.id); if(!client.stations) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.maintenance, + content: client.messages.emojis["error"] + client.messages.maintenance, ephemeral: true }); @@ -22,7 +22,7 @@ export default { let station = client.stations[index]; if(!station) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.noSearchResults, + content: client.messages.emojis["error"] + client.messages.noSearchResults, ephemeral: true }); diff --git a/src/client/commands/statistics.ts b/src/client/commands/statistics.ts index 73978fb..822d627 100644 --- a/src/client/commands/statistics.ts +++ b/src/client/commands/statistics.ts @@ -10,7 +10,7 @@ export default { let message: any = {}; if(!interaction.guild) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.maintenance, + content: client.messages.emojis["error"] + client.messages.maintenance, ephemeral: true }); @@ -22,7 +22,7 @@ export default { if(!client.stations) { message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); return interaction.reply({ - content: client.messageEmojis["error"] + message.errorToGetPlaylist, + content: client.messages.emojis["error"] + message.errorToGetPlaylist, ephemeral: true }); } @@ -35,13 +35,13 @@ export default { const embed = new EmbedBuilder() .setTitle(client.messages.statisticsTitle) - .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["statistics"].replace(/[^0-9]+/g, '')) + .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["statistics"].replace(/[^0-9]+/g, '')) .setColor(client.config.embedColor as ColorResolvable) .setDescription(statistics) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, - iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') + iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '') }); interaction.reply({ diff --git a/src/client/commands/status.ts b/src/client/commands/status.ts index 52e1bb3..aa6a15b 100644 --- a/src/client/commands/status.ts +++ b/src/client/commands/status.ts @@ -9,7 +9,7 @@ export default { let message: any = {}; if(!client.user) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.maintenance, + content: client.messages.emojis["error"] + client.messages.maintenance, ephemeral: true }); @@ -18,7 +18,7 @@ export default { const embed = new EmbedBuilder() .setTitle(message.statusTitle) - .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, '')) + .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, '')) .setColor(client.config.embedColor as ColorResolvable) .addFields([ { name: client.messages.statusField1, value: uptime }, @@ -30,7 +30,7 @@ export default { .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, - iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') + iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '') }); interaction.reply({ diff --git a/src/client/commands/stop.ts b/src/client/commands/stop.ts index 92024c2..05c28d7 100644 --- a/src/client/commands/stop.ts +++ b/src/client/commands/stop.ts @@ -14,7 +14,7 @@ export default { const embed = new EmbedBuilder() .setTitle(client.user?.username || "-") - .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["stop"].replace(/[^0-9]+/g, '')) + .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["stop"].replace(/[^0-9]+/g, '')) .setColor(client.config.embedColor as ColorResolvable) .addFields({ name: client.messages.nowplayingTitle, @@ -23,7 +23,7 @@ export default { .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, - iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') + iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '') }); if(!radio.message){ @@ -43,7 +43,7 @@ export default { client.radio?.delete(interaction.guild?.id); interaction.reply({ - content: client.messageEmojis["stop"] + client.messages.stop, + content: client.messages.emojis["stop"] + client.messages.stop, ephemeral: true }); } diff --git a/src/client/emojis.ts b/src/client/emojis.ts deleted file mode 100644 index b7cc2e0..0000000 --- a/src/client/emojis.ts +++ /dev/null @@ -1,44 +0,0 @@ -import RadioClient from "../Client"; - -export const emojis = { - name: 'emojis', - async execute(client: RadioClient): Promise { - let customEmojis: any = { - logo: "<:RadioX:688765708808487072>", - eximiabots: "<:EximiaBots:693277919929303132>", - list: "<:RadioXList:688541155519889482>", - play: "<:RadioXPlay:688541155712827458>", - stop: "<:RadioXStop:688541155377414168>", - statistics: "<:RadioXStatistics:694954485507686421>", - maintenance: "<:RadioXMaintenance:695043843057254493>", - error: "<:RadioXError:688541155792781320>", - prev: "<:RadioXPrev:882153637370023957>", - next: "<:RadioXNext:882153637474893834>" - }; - - let fallbackEmojis: any = { - logo: "RadioX", - eximiabots: "EximiaBots", - list: "📜", - play: "▶️", - stop: "⏹️", - statistics: "📊", - maintenance: "🛠️", - error: "❌", - prev: "⏪", - next: "⏩" - }; - - client.messageEmojis = {}; - - for (const customEmojiName in customEmojis) { - const customEmojiID = customEmojis[customEmojiName].replace(/[^0-9]+/g, ''); - const customEmoji = client.emojis.cache.get(customEmojiID); - if (customEmoji) { - client.messageEmojis[customEmojiName] = customEmojis[customEmojiName]; - } else { - client.messageEmojis[customEmojiName] = fallbackEmojis[customEmojiName]; - } - } - } -} diff --git a/src/client/events/interactionCreate.ts b/src/client/events/interactionCreate.ts index 0f886b1..2762e45 100644 --- a/src/client/events/interactionCreate.ts +++ b/src/client/events/interactionCreate.ts @@ -7,7 +7,7 @@ export default { if(client.config.maintenanceMode){ return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.maintenance, + content: client.messages.emojis["error"] + client.messages.maintenance, ephemeral: true }); } @@ -16,7 +16,7 @@ export default { if (!permissions.has(PermissionFlagsBits.ViewChannel)) return; if (!permissions.has(PermissionFlagsBits.EmbedLinks)) return interaction.reply({ - content: client.messageEmojis["error"] + client.messages.noPermsEmbed, + content: client.messages.emojis["error"] + client.messages.noPermsEmbed, ephemeral: true }); @@ -29,7 +29,7 @@ export default { command.execute(interaction, client); } catch (error) { interaction.reply({ - content: client.messageEmojis["error"] + client.messages.runningCommandFailed, + content: client.messages.emojis["error"] + client.messages.runningCommandFailed, ephemeral: true }); console.error(error); @@ -43,7 +43,7 @@ export default { command.execute(interaction, client, command); } catch (error) { interaction.reply({ - content: client.messageEmojis["error"] + client.messages.runningCommandFailed, + content: client.messages.emojis["error"] + client.messages.runningCommandFailed, ephemeral: true }); console.error(error); diff --git a/src/client/events/ready.ts b/src/client/events/ready.ts index 128474b..efd0683 100644 --- a/src/client/events/ready.ts +++ b/src/client/events/ready.ts @@ -4,7 +4,6 @@ import Radio from "../classes/Radio"; import Stations from "../classes/Stations"; import Streamer from "../classes/Streamer"; import Statistics from "../classes/Statistics"; -import { emojis } from "../emojis" import commands from "../commands"; export default { @@ -65,9 +64,6 @@ export default { client.statistics = new Statistics(); client.statistics.calculateGlobal(client); - /*EMOJIS*/ - emojis.execute(client); - /*COMMANDS*/ commands.execute(client); diff --git a/src/client/funcs/check.ts b/src/client/funcs/check.ts index b20e452..8b89a5e 100644 --- a/src/client/funcs/check.ts +++ b/src/client/funcs/check.ts @@ -1,27 +1,26 @@ import RadioClient from "../../Client"; import { command } from "../commands"; - export default function check(client: RadioClient, interaction: any, command: command) { let message: any = {}; const radio = client.radio?.get(interaction.guild.id); if(!client.stations) { message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); interaction.reply({ - content: client.messageEmojis["error"] + message.errorToGetPlaylist, + content: client.messages.emojis["error"] + message.errorToGetPlaylist, ephemeral: true }); return false; } if (!radio) { interaction.reply({ - content: client.messageEmojis["error"] + client.messages.notPlaying, + content: client.messages.emojis["error"] + client.messages.notPlaying, ephemeral: true }); return false; } if (interaction.member.voice.channel !== radio.voiceChannel) { interaction.reply({ - content: client.messageEmojis["error"] + client.messages.wrongVoiceChannel, + content: client.messages.emojis["error"] + client.messages.wrongVoiceChannel, ephemeral: true }); return false; diff --git a/src/client/funcs/play.ts b/src/client/funcs/play.ts index 6af87a0..f407b2b 100644 --- a/src/client/funcs/play.ts +++ b/src/client/funcs/play.ts @@ -16,7 +16,7 @@ export default async function play(client: RadioClient, interaction: any, guild: const embed = new EmbedBuilder() .setTitle(client.user?.username || "-") - .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, ''))) + .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messages.emojis["play"].replace(/[^0-9]+/g, ''))) .setColor(client.config.embedColor as ColorResolvable) .addFields({ name: client.messages.nowplayingTitle, @@ -25,38 +25,38 @@ export default async function play(client: RadioClient, interaction: any, guild: .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, - iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '') + iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '') }); const buttons = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId('list') - .setEmoji(client.messageEmojis["list"]) + .setEmoji(client.messages.emojis["list"]) .setStyle(ButtonStyle.Secondary) ) .addComponents( new ButtonBuilder() .setCustomId('prev') - .setEmoji(client.messageEmojis["prev"]) + .setEmoji(client.messages.emojis["prev"]) .setStyle(ButtonStyle.Secondary) ) .addComponents( new ButtonBuilder() .setCustomId('stop') - .setEmoji(client.messageEmojis["stop"]) + .setEmoji(client.messages.emojis["stop"]) .setStyle(ButtonStyle.Secondary) ) .addComponents( new ButtonBuilder() .setCustomId('next') - .setEmoji(client.messageEmojis["next"]) + .setEmoji(client.messages.emojis["next"]) .setStyle(ButtonStyle.Secondary) ) .addComponents( new ButtonBuilder() .setCustomId('statistics') - .setEmoji(client.messageEmojis["statistics"]) + .setEmoji(client.messages.emojis["statistics"]) .setStyle(ButtonStyle.Secondary) ); @@ -74,7 +74,7 @@ export default async function play(client: RadioClient, interaction: any, guild: message.play = client.messages.play.replace("%radio.station.name%", radio.station.name); interaction?.reply({ - content: client.messageEmojis["play"] + message.play, + content: client.messages.emojis["play"] + message.play, ephemeral: true }); diff --git a/src/client/messages.ts b/src/client/messages.ts index f9f4e11..b6231e1 100644 --- a/src/client/messages.ts +++ b/src/client/messages.ts @@ -35,5 +35,17 @@ export const messages = { statusField4: ":hourglass: Latency", statusField5: ":globe_with_meridians: Hosted by", errorStationURL: "Station can't be URL", - maintenance: "Shhhh... We are now sleeping and dreaming about new features to implement. Will be back soon." + maintenance: "Shhhh... We are now sleeping and dreaming about new features to implement. Will be back soon.", + emojis: { + logo: "<:RadioX:688765708808487072>", + eximiabots: "<:EximiaBots:693277919929303132>", + list: "<:RadioXList:688541155519889482>", + play: "<:RadioXPlay:688541155712827458>", + stop: "<:RadioXStop:688541155377414168>", + statistics: "<:RadioXStatistics:694954485507686421>", + maintenance: "<:RadioXMaintenance:695043843057254493>", + error: "<:RadioXError:688541155792781320>", + prev: "<:RadioXPrev:882153637370023957>", + next: "<:RadioXNext:882153637474893834>" + } }; From 87cf4b62c81ea4f99f265c33ac5a8b3da4c39669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 03:41:04 +0300 Subject: [PATCH 15/44] Simplify events --- src/Client.ts | 45 +------- src/client/events.ts | 45 +++++++- src/client/events/SIGINT.ts | 21 ++-- src/client/events/SIGTERM.ts | 7 +- src/client/events/interactionCreate.ts | 83 ++++++++------- src/client/events/messageDelete.ts | 17 ++- src/client/events/ready.ts | 139 ++++++++++++------------- src/client/events/uncaughtException.ts | 15 ++- src/client/events/voiceStateUpdate.ts | 100 +++++++++--------- src/client/events/warning.ts | 17 ++- 10 files changed, 232 insertions(+), 257 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index 2bbd899..cb598d8 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -6,7 +6,7 @@ import Streamer from "./client/classes/Streamer"; import Statistics from "./client/classes/Statistics"; import { command } from "./client/commands"; import config from "./config"; -import { events } from "./client/events" +import events from "./client/events" import { funcs } from "./client/funcs"; import { messages } from "./client/messages"; @@ -20,7 +20,6 @@ GatewayIntents.add( export default class RadioClient extends Client { readonly commands: Collection; - readonly events = events; readonly funcs = funcs; readonly config = config; readonly messages = messages; @@ -52,47 +51,7 @@ export default class RadioClient extends Client { this.funcs.logger("Maintenance Mode", "Enabled"); this.config.maintenanceMode = true; - this.on("ready", () => { - this.events.ready.execute(this); - }); - - this.on("messageDelete", msg => { - this.events.messageDelete.execute(this, msg); - }); - - this.on("interactionCreate", interaction => { - this.events.interactionCreate.execute(this, interaction); - }); - - this.on("voiceStateUpdate", (oldState, newState) => { - this.events.voiceStateUpdate.execute(this, oldState, newState); - }); - - this.on("error", error => { - this.funcs.logger("Discord Client", "Error"); - console.error(error); - console.log(''); - }); - - process.on('SIGINT', () => { - this.events.SIGINT.execute(this); - }); - - process.on('SIGTERM', () => { - this.events.SIGTERM.execute(this); - }); - - process.on('uncaughtException', (error) => { - this.events.uncaughtException.execute(this, error); - }); - - process.on('exit', () => { - this.funcs.logger("Bot", "Stopping"); - }); - - process.on('warning', (warning) => { - this.events.warning.execute(this, warning); - }); + events(this); this.login(this.config.token).catch((err) => { this.funcs.logger("Discord Client", "Login Error"); diff --git a/src/client/events.ts b/src/client/events.ts index 811a92c..9da068b 100644 --- a/src/client/events.ts +++ b/src/client/events.ts @@ -1,3 +1,4 @@ +import RadioClient from "../Client" import interactionCreate from "./events/interactionCreate" import messageDelete from "./events/messageDelete" import ready from "./events/ready" @@ -7,6 +8,46 @@ import uncaughtException from "./events/uncaughtException" import voiceStateUpdate from "./events/voiceStateUpdate" import warning from "./events/warning" -export const events = { - interactionCreate, messageDelete, ready, SIGINT, SIGTERM, uncaughtException, voiceStateUpdate, warning +export default function events(client: RadioClient) { + client.on("ready", () => { + ready(client); + }); + + client.on("messageDelete", msg => { + messageDelete(client, msg); + }); + + client.on("interactionCreate", interaction => { + interactionCreate(client, interaction); + }); + + client.on("voiceStateUpdate", (oldState, newState) => { + voiceStateUpdate(client, oldState, newState); + }); + + client.on("error", error => { + client.funcs.logger("Discord Client", "Error"); + console.error(error); + console.log(''); + }); + + process.on('SIGINT', () => { + SIGINT(client); + }); + + process.on('SIGTERM', () => { + SIGTERM(client); + }); + + process.on('uncaughtException', (error) => { + uncaughtException(client, error); + }); + + process.on('exit', () => { + client.funcs.logger("Bot", "Stopping"); + }); + + process.on('warning', (error) => { + warning(client, error); + }); } diff --git a/src/client/events/SIGINT.ts b/src/client/events/SIGINT.ts index b3aa1cf..307ce12 100644 --- a/src/client/events/SIGINT.ts +++ b/src/client/events/SIGINT.ts @@ -1,17 +1,14 @@ import RadioClient from "../../Client"; -export default { - name: 'SIGINT', - execute(client: RadioClient) { - client.user?.setStatus('dnd'); +export default function SIGINT(client: RadioClient) { + client.user?.setStatus('dnd'); - client.streamer?.leave(client); - client.radio?.save(client); + client.streamer?.leave(client); + client.radio?.save(client); - setInterval(() => { - if(client.radio?.size == 0){ - process.exit(); - } - }, 500); - } + setInterval(() => { + if(client.radio?.size == 0){ + process.exit(); + } + }, 500); } diff --git a/src/client/events/SIGTERM.ts b/src/client/events/SIGTERM.ts index 7e03abb..c0e492d 100644 --- a/src/client/events/SIGTERM.ts +++ b/src/client/events/SIGTERM.ts @@ -1,8 +1,5 @@ import RadioClient from "../../Client"; -export default { - name: 'SIGTERM', - execute(client: RadioClient) { - process.emit('SIGINT'); - } +export default function SIGTERM(client: RadioClient) { + process.emit('SIGINT'); } diff --git a/src/client/events/interactionCreate.ts b/src/client/events/interactionCreate.ts index 2762e45..25387ca 100644 --- a/src/client/events/interactionCreate.ts +++ b/src/client/events/interactionCreate.ts @@ -1,53 +1,52 @@ -import { PermissionFlagsBits } from "discord.js"; +import { Interaction, PermissionFlagsBits } from "discord.js"; import RadioClient from "../../Client"; -export default { - name: 'interactionCreate', - async execute(client: RadioClient, interaction: any) { +export default function interactionCreate(client: RadioClient, interaction: Interaction) { + if(!(interaction.isButton()) && !(interaction.isChatInputCommand()) && !(interaction.isStringSelectMenu())) return; - if(client.config.maintenanceMode){ - return interaction.reply({ - content: client.messages.emojis["error"] + client.messages.maintenance, - ephemeral: true - }); - } - - const permissions = interaction.channel.permissionsFor(interaction.client.user); - if (!permissions.has(PermissionFlagsBits.ViewChannel)) return; - - if (!permissions.has(PermissionFlagsBits.EmbedLinks)) return interaction.reply({ - content: client.messages.emojis["error"] + client.messages.noPermsEmbed, + if(client.config.maintenanceMode){ + return interaction.reply({ + content: client.messages.emojis["error"] + client.messages.maintenance, ephemeral: true }); + } - if(interaction.isChatInputCommand()){ - const commandName = interaction.commandName; - const command = client.commands.get(commandName); - if (!command) return; + //@ts-ignore + const permissions = interaction.channel?.permissionsFor(interaction.client.user); + if (!permissions.has(PermissionFlagsBits.ViewChannel)) return; - try { - command.execute(interaction, client); - } catch (error) { - interaction.reply({ - content: client.messages.emojis["error"] + client.messages.runningCommandFailed, - ephemeral: true - }); - console.error(error); - } - } else if (interaction.isStringSelectMenu() || interaction.isButton()){ - const commandName = interaction.customId; - const command = client.commands.get(commandName); - if (!command) return; + if (!permissions.has(PermissionFlagsBits.EmbedLinks)) return interaction.reply({ + content: client.messages.emojis["error"] + client.messages.noPermsEmbed, + ephemeral: true + }); - try { - command.execute(interaction, client, command); - } catch (error) { - interaction.reply({ - content: client.messages.emojis["error"] + client.messages.runningCommandFailed, - ephemeral: true - }); - console.error(error); - } + if(interaction.isChatInputCommand()){ + const commandName = interaction.commandName; + const command = client.commands.get(commandName); + if (!command) return; + + try { + command.execute(interaction, client); + } catch (error) { + interaction.reply({ + content: client.messages.emojis["error"] + client.messages.runningCommandFailed, + ephemeral: true + }); + console.error(error); + } + } else if (interaction.isStringSelectMenu() || interaction.isButton()){ + const commandName = interaction.customId; + const command = client.commands.get(commandName); + if (!command) return; + + try { + command.execute(interaction, client, command); + } catch (error) { + interaction.reply({ + content: client.messages.emojis["error"] + client.messages.runningCommandFailed, + ephemeral: true + }); + console.error(error); } } } diff --git a/src/client/events/messageDelete.ts b/src/client/events/messageDelete.ts index 89584c6..3efbbfd 100644 --- a/src/client/events/messageDelete.ts +++ b/src/client/events/messageDelete.ts @@ -1,14 +1,11 @@ import { Message, PartialMessage } from "discord.js"; import RadioClient from "../../Client"; -export default { - name: 'messageDelete', - async execute(client: RadioClient, msg: Message | PartialMessage) { - if(!msg.author?.bot || !msg.guild) return; - const radio = client.radio?.get(msg.guild.id); - if(!radio) return; - if(!radio.message) return; - if(msg.id != radio.message.id) return; - radio.message = null; - } +export default function messageDelete(client: RadioClient, msg: Message | PartialMessage){ + if(!msg.author?.bot || !msg.guild) return; + const radio = client.radio?.get(msg.guild.id); + if(!radio) return; + if(!radio.message) return; + if(msg.id != radio.message.id) return; + radio.message = null; } diff --git a/src/client/events/ready.ts b/src/client/events/ready.ts index efd0683..47e6865 100644 --- a/src/client/events/ready.ts +++ b/src/client/events/ready.ts @@ -6,82 +6,77 @@ import Streamer from "../classes/Streamer"; import Statistics from "../classes/Statistics"; import commands from "../commands"; -export default { - name: 'ready', - async execute(client: RadioClient) { +export default async function ready(client: RadioClient) { + client.funcs.logger("Bot", "Ready"); - client.funcs.logger("Bot", "Ready"); + /*DATASTORE*/ + client.funcs.logger('Datastore', 'Initialize'); + client.datastore = new Datastore(); - /*DATASTORE*/ - client.funcs.logger('Datastore', 'Initialize'); - client.datastore = new Datastore(); + client.datastore.map.forEach((datastore: { guild: { id: string; name: string; }; }) => { + client.funcs.logger('Datastore', datastore.guild.id + " / " + datastore.guild.name); + }); - client.datastore.map.forEach((datastore: { guild: { id: string; name: string; }; }) => { - client.funcs.logger('Datastore', datastore.guild.id + " / " + datastore.guild.name); - }); + client.funcs.logger('Datastore', 'Ready'); - client.funcs.logger('Datastore', 'Ready'); - - /*DEVELOPERS*/ - client.developers = ""; - let user : any= ""; - for (let i = 0; i < client.config.devId.length; i++) { - user = await client.users.fetch(client.config.devId[i]); - client.funcs.logger('Developers', user.tag); - if (i == client.config.devId.length - 1) { - client.developers += user.tag; - } else { - client.developers += user.tag + " & "; - } + /*DEVELOPERS*/ + client.developers = ""; + let user : any= ""; + for (let i = 0; i < client.config.devId.length; i++) { + user = await client.users.fetch(client.config.devId[i]); + client.funcs.logger('Developers', user.tag); + if (i == client.config.devId.length - 1) { + client.developers += user.tag; + } else { + client.developers += user.tag + " & "; } - - /*STATIONS*/ - client.stations = new Stations(); - - await client.stations.fetch({ - url: client.config.stationslistUrl, - show: true - }); - - client.streamer = new Streamer(); - client.streamer.init(client); - - if(!client.stations) { - client.user?.setStatus('dnd'); - } - - /*GUILDS*/ - client.funcs.logger('Guilds', 'Started fetching list'); - - let guilds = await client.guilds.fetch(); - guilds.forEach((guild: { id: string; name: string; }) => { - client.funcs.logger('Guilds', guild.id + " / " + guild.name); - }); - - client.funcs.logger('Guilds', 'Successfully fetched list'); - - /*STATISTICS*/ - client.statistics = new Statistics(); - client.statistics.calculateGlobal(client); - - /*COMMANDS*/ - commands.execute(client); - - /*RADIO*/ - client.radio = new Radio(); - - setTimeout(function () { - /*RESTORE RADIOS*/ - client.radio?.restore(client, guilds); - }, 5000); - - setTimeout(function () { - if(client.stations) { - /*MAINTENANCE MODE*/ - client.funcs.logger("Maintenance Mode", "Disabled"); - client.config.maintenanceMode = false; - } - }, 10000); - } + + /*STATIONS*/ + client.stations = new Stations(); + + await client.stations.fetch({ + url: client.config.stationslistUrl, + show: true + }); + + client.streamer = new Streamer(); + client.streamer.init(client); + + if(!client.stations) { + client.user?.setStatus('dnd'); + } + + /*GUILDS*/ + client.funcs.logger('Guilds', 'Started fetching list'); + + let guilds = await client.guilds.fetch(); + guilds.forEach((guild: { id: string; name: string; }) => { + client.funcs.logger('Guilds', guild.id + " / " + guild.name); + }); + + client.funcs.logger('Guilds', 'Successfully fetched list'); + + /*STATISTICS*/ + client.statistics = new Statistics(); + client.statistics.calculateGlobal(client); + + /*COMMANDS*/ + commands.execute(client); + + /*RADIO*/ + client.radio = new Radio(); + + setTimeout(function () { + /*RESTORE RADIOS*/ + client.radio?.restore(client, guilds); + }, 5000); + + setTimeout(function () { + if(client.stations) { + /*MAINTENANCE MODE*/ + client.funcs.logger("Maintenance Mode", "Disabled"); + client.config.maintenanceMode = false; + } + }, 10000); } diff --git a/src/client/events/uncaughtException.ts b/src/client/events/uncaughtException.ts index 3f22396..b0d8536 100644 --- a/src/client/events/uncaughtException.ts +++ b/src/client/events/uncaughtException.ts @@ -1,13 +1,10 @@ import RadioClient from "../../Client"; -export default { - name: 'uncaughtException', - execute(client: RadioClient, error: any) { - client.funcs.logger("Error"); - console.log(error.stack); - console.log(''); +export default function uncaughtException(client: RadioClient, error: Error) { + client.funcs.logger("Error"); + console.log(error.stack); + console.log(''); - if(error.name == "DiscordAPIError" && error.message == "Unknown interaction") return; - process.emit('SIGINT'); - } + if(error.name == "DiscordAPIError" && error.message == "Unknown interaction") return; + process.emit('SIGINT'); } diff --git a/src/client/events/voiceStateUpdate.ts b/src/client/events/voiceStateUpdate.ts index 8c7600c..cf5fbb4 100644 --- a/src/client/events/voiceStateUpdate.ts +++ b/src/client/events/voiceStateUpdate.ts @@ -5,65 +5,61 @@ const { joinVoiceChannel } = require("@discordjs/voice"); -export default { - name: "voiceStateUpdate", - async execute(client: RadioClient, oldState: VoiceState, newState: VoiceState) { - if (oldState.channel === null) return; - let change = false; - const radio = client.radio?.get(newState.guild.id); - if (!radio) return; +export default async function voiceStateUpdate(client: RadioClient, oldState: VoiceState, newState: VoiceState) { + if (oldState.channel === null) return; + let change = false; + const radio = client.radio?.get(newState.guild.id); + if (!radio) return; - if (newState.member?.id === client.user?.id && oldState.member?.id === client.user?.id) { + if (newState.member?.id === client.user?.id && oldState.member?.id === client.user?.id) { - if (newState.channel === null) { + if (newState.channel === null) { + client.statistics?.update(client, newState.guild, radio); + radio.connection?.destroy(); + radio.message?.delete(); + client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop'); + return client.radio?.delete(newState.guild.id); + } + + const newPermissions = newState.channel.permissionsFor(newState.client.user); + if (!newPermissions?.has(PermissionFlagsBits.Connect) || !newPermissions?.has(PermissionFlagsBits.Speak) || !newPermissions?.has(PermissionFlagsBits.ViewChannel)) { + try { + setTimeout( + async () => ( + radio.connection = joinVoiceChannel({ + channelId: oldState.channel?.id, + guildId: oldState.channel?.guild.id, + adapterCreator: oldState.channel?.guild.voiceAdapterCreator + }) + ), + 1000 + ); + } catch (error) { client.statistics?.update(client, newState.guild, radio); radio.connection?.destroy(); radio.message?.delete(); client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop'); - return client.radio?.delete(newState.guild.id); + client.radio?.delete(oldState.guild.id); } + return; + } + if (newState.channel !== radio.voiceChannel) { + change = true; + radio.voiceChannel = newState.channel; + radio.connection = getVoiceConnection(newState.channel.guild.id); - const newPermissions = newState.channel.permissionsFor(newState.client.user); - if (!newPermissions?.has(PermissionFlagsBits.Connect) || !newPermissions?.has(PermissionFlagsBits.Speak) || !newPermissions?.has(PermissionFlagsBits.ViewChannel)) { - try { - setTimeout( - async () => ( - radio.connection = joinVoiceChannel({ - channelId: oldState.channel?.id, - guildId: oldState.channel?.guild.id, - adapterCreator: oldState.channel?.guild.voiceAdapterCreator - }) - //radio.connection = await oldState.channel.join() - ), - 1000 - ); - } catch (error) { - client.statistics?.update(client, newState.guild, radio); - radio.connection?.destroy(); - radio.message?.delete(); - client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop'); - client.radio?.delete(oldState.guild.id); - } - return; - } - if (newState.channel !== radio.voiceChannel) { - change = true; - radio.voiceChannel = newState.channel; - radio.connection = getVoiceConnection(newState.channel.guild.id); - //radio.connection = await newState.channel.join(); - } } - if ((oldState.channel.members.filter(member => !member.user.bot).size === 0 && oldState.channel === radio.voiceChannel) || change) { - setTimeout(() => { - if (!radio || !radio.connection || !radio.connection === null) return; - if (radio.voiceChannel.members.filter((member: { user: { bot: any; }; }) => !member.user.bot).size === 0) { - client.statistics?.update(client, newState.guild, radio); - radio.connection?.destroy(); - radio.message?.delete(); - client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop'); - client.radio?.delete(newState.guild.id); - } - }, 5000); - } - }, + } + if ((oldState.channel.members.filter(member => !member.user.bot).size === 0 && oldState.channel === radio.voiceChannel) || change) { + setTimeout(() => { + if (!radio || !radio.connection || !radio.connection === null) return; + if (radio.voiceChannel.members.filter((member: { user: { bot: any; }; }) => !member.user.bot).size === 0) { + client.statistics?.update(client, newState.guild, radio); + radio.connection?.destroy(); + radio.message?.delete(); + client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop'); + client.radio?.delete(newState.guild.id); + } + }, 5000); + } }; diff --git a/src/client/events/warning.ts b/src/client/events/warning.ts index 4b8dd8e..431cf03 100644 --- a/src/client/events/warning.ts +++ b/src/client/events/warning.ts @@ -1,14 +1,11 @@ import RadioClient from "../../Client"; -export default { - name: 'warning', - execute(client: RadioClient, warning: Error) { - if(warning.name == "ExperimentalWarning" && warning.message.startsWith("stream/web")) return; +export default function warning(client: RadioClient, warning: Error) { + if(warning.name == "ExperimentalWarning" && warning.message.startsWith("stream/web")) return; - client.funcs.logger("Warning"); - console.warn(warning.name); - console.warn(warning.message); - console.warn(warning.stack); - console.log(''); - } + client.funcs.logger("Warning"); + console.warn(warning.name); + console.warn(warning.message); + console.warn(warning.stack); + console.log(''); } From 3cec154343ccb6a68536b8337d25aa938f23158b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 03:51:40 +0300 Subject: [PATCH 16/44] Simplicy Commands --- src/client/commands.ts | 3 +-- src/client/events/ready.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/client/commands.ts b/src/client/commands.ts index 997c7da..b0a9183 100644 --- a/src/client/commands.ts +++ b/src/client/commands.ts @@ -21,8 +21,7 @@ export interface command { execute: any } -export default { - async execute(client: RadioClient) { +export default async function commands(client: RadioClient) { const commands : command[] = [ bug, help, invite, list, maintenance, next, nowplaying, play, prev, statistics, status, stop ]; for(const command of commands){ diff --git a/src/client/events/ready.ts b/src/client/events/ready.ts index 47e6865..ec75ba3 100644 --- a/src/client/events/ready.ts +++ b/src/client/events/ready.ts @@ -62,7 +62,7 @@ export default async function ready(client: RadioClient) { client.statistics.calculateGlobal(client); /*COMMANDS*/ - commands.execute(client); + commands(client); /*RADIO*/ client.radio = new Radio(); From 6c1f0944db15e566adc2145f90f42195e7550e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 03:54:44 +0300 Subject: [PATCH 17/44] Update Maintenance command --- src/client/commands/maintenance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index bc269f2..4331714 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -155,7 +155,7 @@ export default { case "6": client.config.maintenanceMode = true; client.user?.setStatus('idle'); - commands.execute(client); + commands(client); client.user?.setStatus('online'); client.config.maintenanceMode = false; break; From 97881f73315c6690a3ab2900e42c412324cb3759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 03:56:58 +0300 Subject: [PATCH 18/44] Fix typo in commands.ts --- src/client/commands.ts | 62 ++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/client/commands.ts b/src/client/commands.ts index b0a9183..d2fe02a 100644 --- a/src/client/commands.ts +++ b/src/client/commands.ts @@ -22,46 +22,44 @@ export interface command { } export default async function commands(client: RadioClient) { - const commands : command[] = [ bug, help, invite, list, maintenance, next, nowplaying, play, prev, statistics, status, stop ]; + const commands : command[] = [ bug, help, invite, list, maintenance, next, nowplaying, play, prev, statistics, status, stop ]; + for(const command of commands){ + client.commands.set(command.name, command); + } + + if(!client.application) return; + client.funcs.logger('Application Commands', 'Started refreshing application (/) commands.'); + if(client.config.devMode){ + client.application.commands.set([]); for(const command of commands){ - client.commands.set(command.name, command); - } - - if(!client.application) return; - client.funcs.logger('Application Commands', 'Started refreshing application (/) commands.'); - if(client.config.devMode){ - client.application.commands.set([]); - for(const command of commands){ - let guilds = await client.guilds.fetch(); - guilds.forEach(async (guild: { id: Snowflake; name: string; }) => { - if(!client.application) return; - client.application.commands.create({ - name: command.name, - description: command.description, - options: command.options || [] - }, guild.id); - client.funcs.logger('Application Commands', 'Guild: ' + guild.id + " (" + guild.name + ") \n" + 'Command: ' + command.name); - }); - } - } else { - for(const command of commands){ + let guilds = await client.guilds.fetch(); + guilds.forEach(async (guild: { id: Snowflake; name: string; }) => { + if(!client.application) return; client.application.commands.create({ name: command.name, description: command.description, options: command.options || [] - }); - - client.funcs.logger('Application Commands', 'Command: ' + command.name); - } - - let guilds = await client.guilds.fetch(); - guilds.forEach(async (guild: { id: Snowflake; }) => { - if(!client.application) return; - client.application.commands.set([], guild.id); + }, guild.id); + client.funcs.logger('Application Commands', 'Guild: ' + guild.id + " (" + guild.name + ") \n" + 'Command: ' + command.name); }); } - client.funcs.logger('Application Commands', 'Successfully reloaded application (/) commands.' + "\n"); + } else { + for(const command of commands){ + client.application.commands.create({ + name: command.name, + description: command.description, + options: command.options || [] + }); + client.funcs.logger('Application Commands', 'Command: ' + command.name); + } + + let guilds = await client.guilds.fetch(); + guilds.forEach(async (guild: { id: Snowflake; }) => { + if(!client.application) return; + client.application.commands.set([], guild.id); + }); } + client.funcs.logger('Application Commands', 'Successfully reloaded application (/) commands.' + "\n"); } From bc238d919ddd5b0b5af16ecbb0ed011d3940b518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 04:37:06 +0300 Subject: [PATCH 19/44] Rename devId to devIds in config --- src/Client.ts | 1 - src/client/commands/maintenance.ts | 2 +- src/client/events/ready.ts | 14 ++++---------- src/client/funcs/isDev.ts | 12 ++++++------ src/config.ts | 2 +- 5 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/Client.ts b/src/Client.ts index cb598d8..336bf33 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -28,7 +28,6 @@ export default class RadioClient extends Client { public streamer: Streamer | null; public statistics: Statistics | null; public radio: Radio | null; - public developers: string | undefined; constructor() { super({ diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index 4331714..6c2e82b 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -13,7 +13,7 @@ export default { async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { let message: any = {}; - if(!client.funcs.isDev(client.config.devId, interaction.user.id)) return interaction.reply({ + if(!client.funcs.isDev(client.config.devIDs, interaction.user.id)) return interaction.reply({ content: client.messages.emojis["error"] + client.messages.notAllowed, ephemeral: true }); diff --git a/src/client/events/ready.ts b/src/client/events/ready.ts index ec75ba3..b36ebf5 100644 --- a/src/client/events/ready.ts +++ b/src/client/events/ready.ts @@ -20,17 +20,11 @@ export default async function ready(client: RadioClient) { client.funcs.logger('Datastore', 'Ready'); /*DEVELOPERS*/ - client.developers = ""; - let user : any= ""; - for (let i = 0; i < client.config.devId.length; i++) { - user = await client.users.fetch(client.config.devId[i]); - client.funcs.logger('Developers', user.tag); - if (i == client.config.devId.length - 1) { - client.developers += user.tag; - } else { - client.developers += user.tag + " & "; - } + let developers : string[] = []; + for(let devID of client.config.devIDs){ + developers.push((await client.users.fetch(devID)).tag); } + client.funcs.logger('Developers', developers.join(" & ")); /*STATIONS*/ client.stations = new Stations(); diff --git a/src/client/funcs/isDev.ts b/src/client/funcs/isDev.ts index 5d54e06..e601633 100644 --- a/src/client/funcs/isDev.ts +++ b/src/client/funcs/isDev.ts @@ -1,10 +1,10 @@ -export default function isDev(devList : any, authorID : any){ +import { Snowflake } from "discord.js"; + +export default function isDev(devIDs : any[], authorID : Snowflake){ let response = false; - Object.keys(devList).forEach(function(oneDev) { - let devID = devList[oneDev]; + for (const devID of devIDs){ if(authorID == devID){ - response = true; + return true; } - }); - return response; + } } diff --git a/src/config.ts b/src/config.ts index 747e8b1..aa8aa22 100644 --- a/src/config.ts +++ b/src/config.ts @@ -8,7 +8,7 @@ export default { //support supportGuild: "https://discord.gg/rRA65Mn", - devId: [ + devIDs: [ "493174343484833802", "360363051792203779" ], From 3686cd1b0e4a0fd5c635223c38c9d5d45c65b961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 04:58:01 +0300 Subject: [PATCH 20/44] Replace any types to more strict types --- src/client/classes/Datastore.ts | 4 ++-- src/client/classes/Stations.ts | 8 ++++---- src/client/classes/Streamer.ts | 13 +++++++------ src/client/commands/next.ts | 3 ++- src/client/funcs/listStations.ts | 18 +++++++----------- src/client/funcs/play.ts | 7 +++++-- src/client/funcs/saveState.ts | 3 ++- 7 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/client/classes/Datastore.ts b/src/client/classes/Datastore.ts index cc7fa2a..d398a12 100644 --- a/src/client/classes/Datastore.ts +++ b/src/client/classes/Datastore.ts @@ -2,7 +2,7 @@ import fs from 'fs'; import path from 'path'; export default class { - map: Map; + map: Map; constructor() { this.map = new Map(); this.loadData(); @@ -49,7 +49,7 @@ export default class { this.saveEntry(id, newData); } - loadEntry(id: any){ + loadEntry(id: string){ try { const json = require(`../../../datastore/` + id + '.json'); this.map.set(id, json); diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index 5f555ce..144c7ca 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -7,7 +7,7 @@ export interface station { name: string, owner: string, logo: string, - stream: [] + stream: any } export default class Stations extends Array { @@ -22,11 +22,11 @@ export default class Stations extends Array { logger('Stations', 'Started fetching list - ' + options.url); let list = await fetch(options.url) .then(this.checkFetchStatus) - .then((response: { json: () => any; }) => response.json()); + .then((response: { json: () => station; }) => response.json()); if(list){ this.length = 0; - list.forEach((station: any) => { + list.forEach((station: station) => { try { this.push(station); } catch (error) { @@ -61,7 +61,7 @@ export default class Stations extends Array { } checkFetchStatus(response: any) { - if (response.ok) { // res.status >= 200 && res.status < 300 + if (response.ok) { return response; } else { throw new Error(response.status + " " + response.statusText); diff --git a/src/client/classes/Streamer.ts b/src/client/classes/Streamer.ts index 5b6cce2..55733bc 100644 --- a/src/client/classes/Streamer.ts +++ b/src/client/classes/Streamer.ts @@ -1,6 +1,7 @@ import logger from "../funcs/logger"; import { createAudioPlayer, createAudioResource, NoSubscriberBehavior } from "@discordjs/voice"; import RadioClient from "../../Client"; +import { station } from "./Stations"; export default class Streamer { map: any; @@ -29,7 +30,7 @@ export default class Streamer { if(this.mode == "auto"){ if(!client.stations) return; - client.stations.forEach((station: any) => { + client.stations.forEach((station: station) => { this.play(station); }); } @@ -40,13 +41,13 @@ export default class Streamer { let streamers = this.map.keys(); streamers.forEach((streamer: any) => { - if(client.stations?.findIndex((station: { name: any; }) => station.name == streamer) == -1){ + if(client.stations?.findIndex((station: station) => station.name == streamer) == -1){ this.stop(streamer); } }); } - play(station: any) { + play(station: station) { let audioPlayer = this.map.get(station.name); if(!audioPlayer) { if(this.mode == "auto"){ @@ -95,7 +96,7 @@ export default class Streamer { return audioPlayer; } - stop(station: any){ + stop(station: station){ let audioPlayer = this.map.get(station.name); if(audioPlayer){ logger('Streamer', station.name + " / " + "Stop"); @@ -105,7 +106,7 @@ export default class Streamer { this.map.delete(station.name); } - listen(station: any) { + listen(station: station) { let audioPlayer = this.map.get(station.name); if(!audioPlayer || this.mode == "manual" && audioPlayer.subscribers.length == 0) audioPlayer = this.play(station); return audioPlayer; @@ -113,7 +114,7 @@ export default class Streamer { leave(client: RadioClient) { if(!client.stations) return; - client.stations.forEach((station: any) => { + client.stations.forEach((station: station) => { this.stop(station); }); } diff --git a/src/client/commands/next.ts b/src/client/commands/next.ts index 02dc465..43a3b92 100644 --- a/src/client/commands/next.ts +++ b/src/client/commands/next.ts @@ -1,12 +1,13 @@ import { ButtonInteraction, ChatInputCommandInteraction, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import { station } from "../classes/Stations" +import { command } from "../commands"; export default { name: 'next', description: 'Next Station', category: 'radio', - async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: any) { + async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: command) { if (client.funcs.check(client, interaction, command)) { const radio = client.radio?.get(interaction.guild?.id); diff --git a/src/client/funcs/listStations.ts b/src/client/funcs/listStations.ts index 35bffc4..d60a43e 100644 --- a/src/client/funcs/listStations.ts +++ b/src/client/funcs/listStations.ts @@ -1,20 +1,19 @@ -import { ActionRowBuilder, StringSelectMenuBuilder } from "discord.js"; +import { ActionRowBuilder, SelectMenuComponentOptionData, StringSelectMenuBuilder } from "discord.js"; import RadioClient from "../../Client"; +import { station } from "../classes/Stations"; export default function listStations(client: RadioClient, interaction: any){ - let stations: any = new Array(); - let options: any = new Array(); - if(!client.stations) return; - stations = client.stations.forEach((station: { name?: any; owner?: any; label?: any; description?: any; value?: any; }) => { + let options : SelectMenuComponentOptionData[] = new Array(); + + client.stations.forEach((station: station) => { if(station.name == "GrooveFM") return; - station = { + options.push({ label: station.name, description: station.owner, value: station.name - }; - options.push(station); + }); }); const menu = new ActionRowBuilder() @@ -25,9 +24,6 @@ export default function listStations(client: RadioClient, interaction: any){ .addOptions(options) ); - stations = null; - options = null; - return interaction.reply({ content: '**Select station:**', components: [menu], diff --git a/src/client/funcs/play.ts b/src/client/funcs/play.ts index f407b2b..6943850 100644 --- a/src/client/funcs/play.ts +++ b/src/client/funcs/play.ts @@ -1,8 +1,11 @@ -import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ColorResolvable, EmbedBuilder } from "discord.js"; +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, Guild, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; +import { station } from "../classes/Stations"; -export default async function play(client: RadioClient, interaction: any, guild: any, station: any) { +export default async function play(client: RadioClient, interaction: ChatInputCommandInteraction | StringSelectMenuInteraction | null, guild: Guild | null, station: station) { + if(!guild) return; let message: any = {}; + const radio = client.radio?.get(guild.id); const audioPlayer = client.streamer?.listen(station); radio.connection.subscribe(audioPlayer); diff --git a/src/client/funcs/saveState.ts b/src/client/funcs/saveState.ts index 0bba27a..5552f31 100644 --- a/src/client/funcs/saveState.ts +++ b/src/client/funcs/saveState.ts @@ -1,6 +1,7 @@ +import { Guild } from "discord.js"; import RadioClient from "../../Client"; -export default function saveState(client: RadioClient, guild: any, radio: any){ +export default function saveState(client: RadioClient, guild: Guild, radio: any){ if(!client.datastore) return; client.datastore.checkEntry(guild.id); From 78d6b92dbd2990f0863006eb884b928067511338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 06:04:28 +0300 Subject: [PATCH 21/44] Add replace method to messages variable --- src/client/commands/bug.ts | 13 ++++++------- src/client/commands/help.ts | 13 ++++++------- src/client/commands/invite.ts | 5 +++-- src/client/commands/list.ts | 5 +++-- src/client/commands/nowplaying.ts | 10 +++++----- src/client/commands/play.ts | 5 +++-- src/client/commands/statistics.ts | 5 +++-- src/client/commands/status.ts | 4 +++- src/client/funcs/check.ts | 5 +++-- src/client/funcs/play.ts | 21 ++++++++++----------- src/client/messages.ts | 12 ++++++++++++ 11 files changed, 57 insertions(+), 41 deletions(-) diff --git a/src/client/commands/bug.ts b/src/client/commands/bug.ts index 06bf88b..3a66e87 100644 --- a/src/client/commands/bug.ts +++ b/src/client/commands/bug.ts @@ -11,16 +11,15 @@ export default { ephemeral: true }); - let message : any = {}; - - message.bugTitle = client.messages.bugTitle.replace("%client.user.username%", client.user.username); - message.bugDescription = client.messages.bugDescription.replace("%client.config.supportGuild%", client.config.supportGuild); - const embed = new EmbedBuilder() - .setTitle(message.bugTitle) + .setTitle(client.messages.replace(client.messages.bugTitle, { + "%client.user.username%": client.user.username + })) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, '')) .setColor(client.config.embedColor as ColorResolvable) - .setDescription(message.bugDescription) + .setDescription(client.messages.replace(client.messages.bugDescription, { + "%client.config.supportGuild%": client.config.supportGuild + })) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, diff --git a/src/client/commands/help.ts b/src/client/commands/help.ts index d161c99..964c2b7 100644 --- a/src/client/commands/help.ts +++ b/src/client/commands/help.ts @@ -12,8 +12,6 @@ export default { ephemeral: true }); - let message: any = {}; - const categories : any= []; for (let i = 0; i < client.commands.size; i++) { if (!categories.includes([...client.commands.values()][i].category)) categories.push([...client.commands.values()][i].category); @@ -23,14 +21,15 @@ export default { commands += `**» ${categories[i].toUpperCase()}**\n${client.commands.filter(x => x.category === categories[i]).map((x: { name: any; }) => `\`${x.name}\``).join(', ')}\n`; } - message.helpTitle = client.messages.helpTitle.replace("%client.user.username%", client.user?.username || "-"); - message.helpDescription = client.messages.helpDescription.replace("%commands%", commands); - const embed = new EmbedBuilder() - .setTitle(message.helpTitle) + .setTitle(client.messages.replace(client.messages.helpTitle, { + "%client.user.username%": client.user.username + })) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, '')) .setColor(client.config.embedColor as ColorResolvable) - .setDescription(message.helpDescription) + .setDescription(client.messages.replace(client.messages.helpDescription, { + "%commands%": commands + })) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, diff --git a/src/client/commands/invite.ts b/src/client/commands/invite.ts index 16d71d7..bd49c09 100644 --- a/src/client/commands/invite.ts +++ b/src/client/commands/invite.ts @@ -13,9 +13,10 @@ export default { }); let message: any = {}; - message.inviteTitle = client.messages.inviteTitle.replace("%client.user.username%", client.user.username); const embed = new EmbedBuilder() - .setTitle(message.inviteTitle) + .setTitle(client.messages.replace(client.messages.inviteTitle, { + "%client.user.username%": client.user.username + })) .setColor(client.config.embedColor as ColorResolvable) .setURL("https://discord.com/api/oauth2/authorize?client_id=" + client.user.id + "&permissions=2184465408&scope=applications.commands%20bot") //View Channels, Send Messages, Embed Links, Use External Emojis, Use Slash Commands, Connect, Speak, Use Voice Activity .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') diff --git a/src/client/commands/list.ts b/src/client/commands/list.ts index 7acc4a8..9b365df 100644 --- a/src/client/commands/list.ts +++ b/src/client/commands/list.ts @@ -9,9 +9,10 @@ export default { let message: any = {}; if(!client.stations) { - message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); return interaction.reply({ - content: client.messages.emojis["error"] + message.errorToGetPlaylist, + content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, { + "%client.config.supportGuild%": client.config.supportGuild + }), ephemeral: true }); } diff --git a/src/client/commands/nowplaying.ts b/src/client/commands/nowplaying.ts index 04e7a6b..f5f6250 100644 --- a/src/client/commands/nowplaying.ts +++ b/src/client/commands/nowplaying.ts @@ -15,15 +15,15 @@ export default { radio.playTime = parseInt(radio.currentTime)-parseInt(radio.startTime); const completed = (radio.playTime); - message.nowplayingDescription = client.messages.nowplayingDescription.replace("%radio.station.name%", radio.station.name); - message.nowplayingDescription = message.nowplayingDescription.replace("%radio.station.owner%" + "\n", radio.station.name != radio.station.owner ? radio.station.owner + "\n" : ""); - message.nowplayingDescription = message.nowplayingDescription.replace("%client.funcs.msToTime(completed)%", client.funcs.msToTime(completed)); - const embed = new EmbedBuilder() .setTitle(client.messages.nowplayingTitle) .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messages.emojis["play"].replace(/[^0-9]+/g, ''))) .setColor(client.config.embedColor as ColorResolvable) - .setDescription(message.nowplayingDescription) + .setDescription(client.messages.replace(client.messages.nowplayingDescription, { + "%radio.station.name%": radio.station.name, + "%radio.station.owner%\n": radio.station.name != radio.station.owner ? radio.station.owner + "\n" : "", + "%client.funcs.msToTime(completed)%": client.funcs.msToTime(completed) + })) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ text: client.messages.footerText, diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index 14b5b74..2d19f0b 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -14,9 +14,10 @@ export default { let message: any = {}; if(!client.stations) { - message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); return interaction.reply({ - content: client.messages.emojis["error"] + message.errorToGetPlaylist, + content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, { + "%client.config.supportGuild%": client.config.supportGuild + }), ephemeral: true }); } diff --git a/src/client/commands/statistics.ts b/src/client/commands/statistics.ts index 822d627..3ec0cb7 100644 --- a/src/client/commands/statistics.ts +++ b/src/client/commands/statistics.ts @@ -20,9 +20,10 @@ export default { let statistics = ""; if(!client.stations) { - message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); return interaction.reply({ - content: client.messages.emojis["error"] + message.errorToGetPlaylist, + content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, { + "%client.config.supportGuild%": client.config.supportGuild + }), ephemeral: true }); } diff --git a/src/client/commands/status.ts b/src/client/commands/status.ts index aa6a15b..4f9ec4a 100644 --- a/src/client/commands/status.ts +++ b/src/client/commands/status.ts @@ -17,7 +17,9 @@ export default { let uptime = client.funcs.msToTime(client.uptime || 0); const embed = new EmbedBuilder() - .setTitle(message.statusTitle) + .setTitle(client.messages.replace(client.messages.statusTitle, { + "%client.user.username%": client.user.username + })) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, '')) .setColor(client.config.embedColor as ColorResolvable) .addFields([ diff --git a/src/client/funcs/check.ts b/src/client/funcs/check.ts index 8b89a5e..1e27cdf 100644 --- a/src/client/funcs/check.ts +++ b/src/client/funcs/check.ts @@ -4,9 +4,10 @@ export default function check(client: RadioClient, interaction: any, command: co let message: any = {}; const radio = client.radio?.get(interaction.guild.id); if(!client.stations) { - message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); interaction.reply({ - content: client.messages.emojis["error"] + message.errorToGetPlaylist, + content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, { + "%client.config.supportGuild%": client.config.supportGuild + }), ephemeral: true }); return false; diff --git a/src/client/funcs/play.ts b/src/client/funcs/play.ts index 6943850..c46131b 100644 --- a/src/client/funcs/play.ts +++ b/src/client/funcs/play.ts @@ -4,26 +4,25 @@ import { station } from "../classes/Stations"; export default async function play(client: RadioClient, interaction: ChatInputCommandInteraction | StringSelectMenuInteraction | null, guild: Guild | null, station: station) { if(!guild) return; - let message: any = {}; const radio = client.radio?.get(guild.id); const audioPlayer = client.streamer?.listen(station); radio.connection.subscribe(audioPlayer); client.funcs.logger('Radio', guild.id + " / " + "Play" + " / " + radio.station.name); - message.nowplayingDescription = client.messages.nowplayingDescription.replace("%radio.station.name%", radio.station.name); - message.nowplayingDescription = message.nowplayingDescription.replace("%radio.station.owner%", radio.station.name != radio.station.owner ? radio.station.owner + "\n" : ""); - message.nowplayingDescription = message.nowplayingDescription.replace("%client.funcs.msToTime(completed)%", ""); - message.nowplayingDescription = message.nowplayingDescription.replace("**", ""); - message.nowplayingDescription = message.nowplayingDescription.replace("**", ""); - const embed = new EmbedBuilder() .setTitle(client.user?.username || "-") .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messages.emojis["play"].replace(/[^0-9]+/g, ''))) .setColor(client.config.embedColor as ColorResolvable) .addFields({ name: client.messages.nowplayingTitle, - value: message.nowplayingDescription + value: client.messages.replace(client.messages.nowplayingDescription, { + "%radio.station.name%": radio.station.name, + "%radio.station.owner%\n": radio.station.name != radio.station.owner ? radio.station.owner + "\n" : "", + "%client.funcs.msToTime(completed)%": "", + "**": "", + "**:2": "" + }) }) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ @@ -74,10 +73,10 @@ export default async function play(client: RadioClient, interaction: ChatInputCo } } - message.play = client.messages.play.replace("%radio.station.name%", radio.station.name); - interaction?.reply({ - content: client.messages.emojis["play"] + message.play, + content: client.messages.emojis["play"] + client.messages.replace(client.messages.play, { + "%radio.station.name%": radio.station.name + }), ephemeral: true }); diff --git a/src/client/messages.ts b/src/client/messages.ts index b6231e1..be0d000 100644 --- a/src/client/messages.ts +++ b/src/client/messages.ts @@ -1,4 +1,16 @@ export const messages = { + replace(message: string, variables: { [key: string]: string }){ + for(let variable in variables){ + if(variable.includes('%')){ + message = message.replace(variable, variables[variable]); + } else if(variable.includes(':')){ + message = message.replace(variable.split(':')[0], variables[variable]); + } else { + message = message.replace(variable, variables[variable]); + } + } + return message; + }, wrongVoiceChannel: "You need to be in the same voice channel as RadioX to use this command!", noPerms: "You need the %command.permission% permission to use this command!", notPlaying: "There is nothing playing!", From c181066c673bfb8d37a88efbc99798b18a7c9966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 07:03:21 +0300 Subject: [PATCH 22/44] Update Play command --- src/client/commands/play.ts | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index 2d19f0b..b5e580f 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -22,10 +22,10 @@ export default { }); } - let query : number | string | null = null; + let query: string | null = null; if(interaction.isChatInputCommand()){ - query = interaction.options?.getNumber("query"); + query = interaction.options?.getString("query"); } if(interaction.isStringSelectMenu()){ @@ -37,22 +37,27 @@ export default { } const radio = client.radio?.get(interaction.guild?.id); + if(!(interaction.member instanceof GuildMember)) return; const voiceChannel = interaction.member?.voice.channel; + if (!voiceChannel) return interaction.reply({ content: client.messages.emojis["error"] + client.messages.noVoiceChannel, ephemeral: true }); + if (radio) { if (voiceChannel !== radio.voiceChannel) return interaction.reply({ content: client.messages.emojis["error"] + client.messages.wrongVoiceChannel, ephemeral: true }); } + if (!query) return interaction.reply({ content: client.messages.noQuery, ephemeral: true }); + const permissions = voiceChannel.permissionsFor(interaction.client.user); if (!permissions?.has(PermissionFlagsBits.Connect)) { return interaction.reply({ @@ -68,9 +73,9 @@ export default { } let station; - if (typeof query === 'number') { - const number = parseInt((query - 1) as unknown as string); - if (number > client.stations.length - 1) { + if(!isNaN(parseInt(query) - 1)){ + let number = parseInt(query) - 1; + if(number > client.stations.length - 1) { return interaction.reply({ content: client.messages.emojis["error"] + client.messages.wrongStationNumber, ephemeral: true @@ -79,20 +84,16 @@ export default { station = client.stations[number]; } } else { - if(!(typeof query === 'string')) return; + if(query.length < 3) return interaction.reply({ content: client.messages.emojis["error"] + client.messages.tooShortSearch, ephemeral: true }); - let type = ""; + let type = "text"; - if(interaction.isStringSelectMenu()){ - if(interaction.values?.[0]){ - type = "direct"; - } else { - type = "text"; - } + if(interaction.isStringSelectMenu() && interaction.values?.[0]){ + type = "direct"; } const sstation = await client.stations.search(query, type); From 7ba5ee97a8e0dcb6c0cd28d4a770db2a083ab54d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 07:10:21 +0300 Subject: [PATCH 23/44] Remove unused message variables in commands --- src/client/commands/invite.ts | 1 - src/client/commands/list.ts | 1 - src/client/commands/maintenance.ts | 1 - src/client/commands/nowplaying.ts | 2 +- src/client/commands/play.ts | 1 - src/client/commands/statistics.ts | 1 - src/client/commands/status.ts | 2 -- src/client/funcs/check.ts | 3 ++- 8 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/client/commands/invite.ts b/src/client/commands/invite.ts index bd49c09..65268be 100644 --- a/src/client/commands/invite.ts +++ b/src/client/commands/invite.ts @@ -12,7 +12,6 @@ export default { ephemeral: true }); - let message: any = {}; const embed = new EmbedBuilder() .setTitle(client.messages.replace(client.messages.inviteTitle, { "%client.user.username%": client.user.username diff --git a/src/client/commands/list.ts b/src/client/commands/list.ts index 9b365df..eba28ed 100644 --- a/src/client/commands/list.ts +++ b/src/client/commands/list.ts @@ -6,7 +6,6 @@ export default { description: 'List radio stations', category: 'radio', execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { - let message: any = {}; if(!client.stations) { return interaction.reply({ diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index 6c2e82b..eb20c3a 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -11,7 +11,6 @@ export default { description: 'Bot Maintenance', category: 'info', async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { - let message: any = {}; if(!client.funcs.isDev(client.config.devIDs, interaction.user.id)) return interaction.reply({ content: client.messages.emojis["error"] + client.messages.notAllowed, diff --git a/src/client/commands/nowplaying.ts b/src/client/commands/nowplaying.ts index f5f6250..13a0855 100644 --- a/src/client/commands/nowplaying.ts +++ b/src/client/commands/nowplaying.ts @@ -7,7 +7,7 @@ export default { category: 'radio', async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: any) { if(client.funcs.check(client, interaction, command)) { - let message: any = {}; + const radio = client.radio?.get(interaction.guild?.id); let date = new Date(); diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index b5e580f..2122be6 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -11,7 +11,6 @@ export default { ], category: "radio", async execute(interaction: ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { - let message: any = {}; if(!client.stations) { return interaction.reply({ diff --git a/src/client/commands/statistics.ts b/src/client/commands/statistics.ts index 3ec0cb7..0cccbfb 100644 --- a/src/client/commands/statistics.ts +++ b/src/client/commands/statistics.ts @@ -7,7 +7,6 @@ export default { description: 'Show statistics', category: 'info', execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { - let message: any = {}; if(!interaction.guild) return interaction.reply({ content: client.messages.emojis["error"] + client.messages.maintenance, diff --git a/src/client/commands/status.ts b/src/client/commands/status.ts index 4f9ec4a..6d2418d 100644 --- a/src/client/commands/status.ts +++ b/src/client/commands/status.ts @@ -6,14 +6,12 @@ export default { description: 'Bot Status', category: 'info', async execute(interaction: any, client: RadioClient) { - let message: any = {}; if(!client.user) return interaction.reply({ content: client.messages.emojis["error"] + client.messages.maintenance, ephemeral: true }); - message.statusTitle = client.messages.statusTitle.replace("%client.user.username%", client.user.username); let uptime = client.funcs.msToTime(client.uptime || 0); const embed = new EmbedBuilder() diff --git a/src/client/funcs/check.ts b/src/client/funcs/check.ts index 1e27cdf..449d16d 100644 --- a/src/client/funcs/check.ts +++ b/src/client/funcs/check.ts @@ -1,7 +1,8 @@ import RadioClient from "../../Client"; import { command } from "../commands"; + export default function check(client: RadioClient, interaction: any, command: command) { - let message: any = {}; + const radio = client.radio?.get(interaction.guild.id); if(!client.stations) { interaction.reply({ From 95216f5accde88af067b8821f2f0df309507633c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 07:11:45 +0300 Subject: [PATCH 24/44] Remove unused variable in isDev function --- src/client/funcs/isDev.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/funcs/isDev.ts b/src/client/funcs/isDev.ts index e601633..d68dba3 100644 --- a/src/client/funcs/isDev.ts +++ b/src/client/funcs/isDev.ts @@ -1,7 +1,6 @@ import { Snowflake } from "discord.js"; export default function isDev(devIDs : any[], authorID : Snowflake){ - let response = false; for (const devID of devIDs){ if(authorID == devID){ return true; From 227e0bcaaa47504a6cf82a225df4fb821594ab46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 07:12:21 +0300 Subject: [PATCH 25/44] Typings in listStations function --- src/client/funcs/listStations.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client/funcs/listStations.ts b/src/client/funcs/listStations.ts index d60a43e..74ed88d 100644 --- a/src/client/funcs/listStations.ts +++ b/src/client/funcs/listStations.ts @@ -1,8 +1,8 @@ -import { ActionRowBuilder, SelectMenuComponentOptionData, StringSelectMenuBuilder } from "discord.js"; +import { ActionRowBuilder, ButtonInteraction, ChatInputCommandInteraction, SelectMenuComponentOptionData, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import { station } from "../classes/Stations"; -export default function listStations(client: RadioClient, interaction: any){ +export default function listStations(client: RadioClient, interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction){ if(!client.stations) return; let options : SelectMenuComponentOptionData[] = new Array(); @@ -16,7 +16,7 @@ export default function listStations(client: RadioClient, interaction: any){ }); }); - const menu = new ActionRowBuilder() + const menu: ActionRowBuilder = new ActionRowBuilder() .addComponents( new StringSelectMenuBuilder() .setCustomId('play') From 40cd3a9ec59ddd48f4781cbd43f4a0b8a2ab73ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 6 Jun 2023 08:05:54 +0300 Subject: [PATCH 26/44] More typings to classes, commands, events, funcs --- src/client/classes/Datastore.ts | 52 ++++++++++++++++++++------- src/client/classes/Radio.ts | 17 +++++++-- src/client/classes/Stations.ts | 6 ++-- src/client/classes/Statistics.ts | 9 ++--- src/client/classes/Streamer.ts | 4 +-- src/client/commands/help.ts | 5 +-- src/client/commands/nowplaying.ts | 3 +- src/client/commands/play.ts | 3 +- src/client/commands/status.ts | 4 +-- src/client/commands/stop.ts | 3 +- src/client/events/voiceStateUpdate.ts | 4 +-- src/client/funcs/check.ts | 6 ++-- src/client/funcs/isDev.ts | 2 +- src/client/funcs/saveState.ts | 5 +-- 14 files changed, 84 insertions(+), 39 deletions(-) diff --git a/src/client/classes/Datastore.ts b/src/client/classes/Datastore.ts index d398a12..891b72c 100644 --- a/src/client/classes/Datastore.ts +++ b/src/client/classes/Datastore.ts @@ -1,6 +1,32 @@ -import fs from 'fs'; +import { Guild } from 'discord.js'; +import fs, { NoParamCallback } from 'fs'; import path from 'path'; +interface entry { + guild: { + id: string, + name?: string + }, + statistics: { + [key: string]: { + "time": number, + "used": number + } + } | {}, + state: { + channels: { + "text": string, + "voice": string + }, + date: string, + station: { + name: string, + owner: string + } + } | {}, + updated?: string +} + export default class { map: Map; constructor() { @@ -40,11 +66,13 @@ export default class { } createEntry(id: string){ - let newData: any = {}; - newData.guild = {}; - newData.guild.id = id; - newData.statistics = {}; - newData.state = {}; + let newData: entry = { + guild: { + id: id, + }, + statistics: {}, + state: {} + }; this.map.set(id, newData); this.saveEntry(id, newData); } @@ -61,7 +89,7 @@ export default class { return this.map.get(id); } - updateEntry(guild: any, newData: any) { + updateEntry(guild: Guild | { id: string, name: string }, newData: entry) { newData.guild.name = guild.name; let date = new Date(); @@ -72,7 +100,7 @@ export default class { //this.showEntry(this.getEntry(guild.id)); } - showEntry(data : any){ + showEntry(data : entry){ console.log(data); } @@ -96,12 +124,10 @@ export default class { this.updateEntry(newData.guild, newData); } - saveEntry(file: string, data: any) { - data = JSON.stringify(data, null, 4); - - fs.writeFile(path.join(path.dirname(__dirname), '../../datastore') + "/" + file + ".json", data, 'utf8', function(err: any) { + saveEntry(file: string, data: entry) { + fs.writeFile(path.join(path.dirname(__dirname), '../../datastore') + "/" + file + ".json", JSON.stringify(data, null, 4), 'utf8', function(err: any) { if (err) { - //console.log(err); + } }); } diff --git a/src/client/classes/Radio.ts b/src/client/classes/Radio.ts index ca9de72..2137211 100644 --- a/src/client/classes/Radio.ts +++ b/src/client/classes/Radio.ts @@ -1,6 +1,19 @@ -import { getVoiceConnection, joinVoiceChannel } from "@discordjs/voice"; -import { Guild, GuildMember, VoiceChannel } from "discord.js"; +import { Guild, GuildMember, TextBasedChannel, VoiceBasedChannel, VoiceChannel } from "discord.js"; +import { getVoiceConnection, joinVoiceChannel, VoiceConnection } from "@discordjs/voice"; import RadioClient from "../../Client"; +import { station } from "./Stations"; + +export interface radio { + textChannel: TextBasedChannel | null, + voiceChannel: VoiceBasedChannel, + connection: VoiceConnection | null, + message: null, + station: station, + datastore?: any, + currentTime?: number, + startTime: number, + playTime?: number, +} export default class Radio extends Map { diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index 144c7ca..a1b7fa1 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -40,7 +40,7 @@ export default class Stations extends Array { }); } - list.forEach(async (station: { stream: { [x: string]: any; default: string | number; }; }) => { + list.forEach(async (station: station) => { try { let stationTest = await fetch(station.stream[station.stream.default]); if(stationTest.ok === true) return; @@ -83,7 +83,7 @@ export default class Stations extends Array { return foundStation; } else { - let foundStations : any[] = []; + let foundStations : { station: string, name: string, probability: number }[] = []; if (key == "radio") return false; this @@ -126,7 +126,7 @@ export default class Stations extends Array { } } } - let highestProbabilityStation; + let highestProbabilityStation : any | { station: string, name: string, probability: number } | string | null = null; for (let i = 0; i < foundStations.length; i++) { if ( !highestProbabilityStation || diff --git a/src/client/classes/Statistics.ts b/src/client/classes/Statistics.ts index 7f21fb0..7f52bbd 100644 --- a/src/client/classes/Statistics.ts +++ b/src/client/classes/Statistics.ts @@ -1,14 +1,15 @@ import { Guild } from "discord.js"; import RadioClient from "../../Client"; +import { radio } from "./Radio"; export default class Statistics { - map: any; + map: Map; constructor() { this.map = new Map(); } - update(client: RadioClient, guild: Guild | null, radio: any) { + update(client: RadioClient, guild: Guild | null, radio: radio) { if(!guild) return; client.datastore?.checkEntry(guild.id); @@ -24,8 +25,8 @@ export default class Statistics { let date = new Date(); radio.currentTime = date.getTime(); - radio.playTime = parseInt(radio.currentTime)-parseInt(radio.startTime); - radio.datastore.statistics[radio.station.name].time = parseInt(radio.datastore.statistics[radio.station.name].time)+parseInt(radio.playTime); + radio.playTime = radio.currentTime - radio.startTime; + radio.datastore.statistics[radio.station.name].time = parseInt(radio.datastore.statistics[radio.station.name].time) + radio.playTime; radio.datastore.statistics[radio.station.name].used = parseInt(radio.datastore.statistics[radio.station.name].used)+1; client.datastore?.updateEntry(guild, radio.datastore); diff --git a/src/client/classes/Streamer.ts b/src/client/classes/Streamer.ts index 55733bc..1da2190 100644 --- a/src/client/classes/Streamer.ts +++ b/src/client/classes/Streamer.ts @@ -5,12 +5,10 @@ import { station } from "./Stations"; export default class Streamer { map: any; - mode: any | null; - logger: any; + mode: "auto" | "manual" = "manual"; constructor() { this.map = new Map(); - this.mode = null; } init(client: RadioClient){ diff --git a/src/client/commands/help.ts b/src/client/commands/help.ts index 964c2b7..17b8619 100644 --- a/src/client/commands/help.ts +++ b/src/client/commands/help.ts @@ -1,5 +1,6 @@ import { ChatInputCommandInteraction, ColorResolvable, EmbedBuilder } from "discord.js"; import RadioClient from "../../Client"; +import { command } from "../commands"; export default { name: 'help', @@ -12,13 +13,13 @@ export default { ephemeral: true }); - const categories : any= []; + const categories: string[] = []; for (let i = 0; i < client.commands.size; i++) { if (!categories.includes([...client.commands.values()][i].category)) categories.push([...client.commands.values()][i].category); } let commands = ''; for (let i = 0; i < categories.length; i++) { - commands += `**» ${categories[i].toUpperCase()}**\n${client.commands.filter(x => x.category === categories[i]).map((x: { name: any; }) => `\`${x.name}\``).join(', ')}\n`; + commands += `**» ${categories[i].toUpperCase()}**\n${client.commands.filter(x => x.category === categories[i]).map((x: command) => `\`${x.name}\``).join(', ')}\n`; } const embed = new EmbedBuilder() diff --git a/src/client/commands/nowplaying.ts b/src/client/commands/nowplaying.ts index 13a0855..8b07394 100644 --- a/src/client/commands/nowplaying.ts +++ b/src/client/commands/nowplaying.ts @@ -1,11 +1,12 @@ import { ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; +import { command } from "../commands"; export default { name: 'nowplaying', description: 'Current Radio Station', category: 'radio', - async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: any) { + async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: command) { if(client.funcs.check(client, interaction, command)) { const radio = client.radio?.get(interaction.guild?.id); diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index 2122be6..1186211 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -1,6 +1,7 @@ import { ApplicationCommandOptionType, ChatInputCommandInteraction, GuildMember, PermissionFlagsBits, StringSelectMenuInteraction } from "discord.js"; import { getVoiceConnection, joinVoiceChannel } from "@discordjs/voice"; import RadioClient from "../../Client"; +import { radio } from "../classes/Radio" export default { name: "play", @@ -116,7 +117,7 @@ export default { } let date = new Date(); - const construct: any = { + const construct: radio = { textChannel: interaction.channel, voiceChannel: voiceChannel, connection: null, diff --git a/src/client/commands/status.ts b/src/client/commands/status.ts index 6d2418d..bcca102 100644 --- a/src/client/commands/status.ts +++ b/src/client/commands/status.ts @@ -1,11 +1,11 @@ -import { ColorResolvable, EmbedBuilder } from "discord.js"; +import { ChatInputCommandInteraction, ColorResolvable, EmbedBuilder } from "discord.js"; import RadioClient from "../../Client"; export default { name: 'status', description: 'Bot Status', category: 'info', - async execute(interaction: any, client: RadioClient) { + async execute(interaction: ChatInputCommandInteraction, client: RadioClient) { if(!client.user) return interaction.reply({ content: client.messages.emojis["error"] + client.messages.maintenance, diff --git a/src/client/commands/stop.ts b/src/client/commands/stop.ts index 05c28d7..75303e2 100644 --- a/src/client/commands/stop.ts +++ b/src/client/commands/stop.ts @@ -1,11 +1,12 @@ import { ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; +import { command } from "../commands"; export default { name: 'stop', description: 'Stop radio', category: 'radio', - async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: any) { + async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: command) { if (client.funcs.check(client, interaction, command)) { const radio = client.radio?.get(interaction.guild?.id); client.statistics?.update(client, interaction.guild, radio); diff --git a/src/client/events/voiceStateUpdate.ts b/src/client/events/voiceStateUpdate.ts index cf5fbb4..8caad08 100644 --- a/src/client/events/voiceStateUpdate.ts +++ b/src/client/events/voiceStateUpdate.ts @@ -1,4 +1,4 @@ -import { PermissionFlagsBits, VoiceState } from "discord.js"; +import { GuildMember, PermissionFlagsBits, VoiceState } from "discord.js"; import RadioClient from "../../Client"; const { getVoiceConnection, @@ -53,7 +53,7 @@ export default async function voiceStateUpdate(client: RadioClient, oldState: Vo if ((oldState.channel.members.filter(member => !member.user.bot).size === 0 && oldState.channel === radio.voiceChannel) || change) { setTimeout(() => { if (!radio || !radio.connection || !radio.connection === null) return; - if (radio.voiceChannel.members.filter((member: { user: { bot: any; }; }) => !member.user.bot).size === 0) { + if (radio.voiceChannel.members.filter((member: GuildMember) => !member.user.bot).size === 0) { client.statistics?.update(client, newState.guild, radio); radio.connection?.destroy(); radio.message?.delete(); diff --git a/src/client/funcs/check.ts b/src/client/funcs/check.ts index 449d16d..cafb5e5 100644 --- a/src/client/funcs/check.ts +++ b/src/client/funcs/check.ts @@ -1,9 +1,10 @@ +import { ButtonInteraction, ChatInputCommandInteraction, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import { command } from "../commands"; -export default function check(client: RadioClient, interaction: any, command: command) { +export default function check(client: RadioClient, interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, command: command) { - const radio = client.radio?.get(interaction.guild.id); + const radio = client.radio?.get(interaction.guild?.id); if(!client.stations) { interaction.reply({ content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, { @@ -20,6 +21,7 @@ export default function check(client: RadioClient, interaction: any, command: co }); return false; } + //@ts-ignore if (interaction.member.voice.channel !== radio.voiceChannel) { interaction.reply({ content: client.messages.emojis["error"] + client.messages.wrongVoiceChannel, diff --git a/src/client/funcs/isDev.ts b/src/client/funcs/isDev.ts index d68dba3..b74e906 100644 --- a/src/client/funcs/isDev.ts +++ b/src/client/funcs/isDev.ts @@ -1,6 +1,6 @@ import { Snowflake } from "discord.js"; -export default function isDev(devIDs : any[], authorID : Snowflake){ +export default function isDev(devIDs : string[], authorID : Snowflake){ for (const devID of devIDs){ if(authorID == devID){ return true; diff --git a/src/client/funcs/saveState.ts b/src/client/funcs/saveState.ts index 5552f31..9634ccb 100644 --- a/src/client/funcs/saveState.ts +++ b/src/client/funcs/saveState.ts @@ -1,7 +1,8 @@ import { Guild } from "discord.js"; import RadioClient from "../../Client"; +import { radio } from "../classes/Radio"; -export default function saveState(client: RadioClient, guild: Guild, radio: any){ +export default function saveState(client: RadioClient, guild: Guild, radio: radio){ if(!client.datastore) return; client.datastore.checkEntry(guild.id); @@ -11,7 +12,7 @@ export default function saveState(client: RadioClient, guild: Guild, radio: any) data.state = {}; data.state.channels = {}; - data.state.channels.text = radio.textChannel.id; + data.state.channels.text = radio.textChannel?.id; data.state.channels.voice = radio.voiceChannel.id; data.state.date = date.toISOString(); data.state.station = {}; From 26a7b2cf25ca3f31395f92a8e952f3881aa78f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Wed, 7 Jun 2023 05:22:46 +0300 Subject: [PATCH 27/44] NodeJS 18 & Node-Fetch Drop --- package-lock.json | 4 ++-- package.json | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index ff6f7dc..5ae9d22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,8 +35,8 @@ "typescript": "^5.1.3" }, "engines": { - "node": ">=16.9.1", - "npm": ">=7.0.0" + "node": ">=18.16.0", + "npm": ">=8.0.0" } }, "node_modules/@cspotcode/source-map-support": { diff --git a/package.json b/package.json index 5d29fc1..4939156 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "discord.js": "^14.11.0", "dotenv": "^16.1.4", "libsodium-wrappers": "^0.7.11", - "node-fetch": "^3.3.1", "path": "^0.12.7" }, "devDependencies": { @@ -44,7 +43,7 @@ "typescript": "^5.1.3" }, "engines": { - "node": ">=16.9.1", + "node": ">=18.16.0", "npm": ">=7.0.0" } } From 25ac99379b09c837aa51bb4780e3f71c168f6e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Wed, 7 Jun 2023 05:23:30 +0300 Subject: [PATCH 28/44] Dockerfile Update - NodeJS 18 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a052374..7b1cc31 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16-alpine +FROM node:18-alpine #Dependencies RUN apk add --virtual .build-deps python3 make g++ gcc git From 16ef8e70e62486e42407e007ecded131e6d21630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Wed, 7 Jun 2023 06:41:58 +0300 Subject: [PATCH 29/44] Typescript continues --- src/client/classes/Datastore.ts | 59 +++++++----------------------- src/client/classes/Radio.ts | 43 +++++++++++++++------- src/client/classes/Stations.ts | 56 ++++++++++------------------ src/client/classes/Statistics.ts | 50 ++++++++++++++++++------- src/client/classes/Streamer.ts | 17 ++++----- src/client/commands/maintenance.ts | 5 +-- src/client/events/ready.ts | 7 ++-- src/client/funcs/loadState.ts | 9 ++--- src/client/funcs/play.ts | 4 +- src/client/funcs/saveState.ts | 21 ++++++----- 10 files changed, 129 insertions(+), 142 deletions(-) diff --git a/src/client/classes/Datastore.ts b/src/client/classes/Datastore.ts index 891b72c..3efa223 100644 --- a/src/client/classes/Datastore.ts +++ b/src/client/classes/Datastore.ts @@ -1,34 +1,21 @@ import { Guild } from 'discord.js'; -import fs, { NoParamCallback } from 'fs'; +import fs from 'fs'; import path from 'path'; +import { state } from './Radio'; +import { statistics } from './Statistics'; -interface entry { +export interface datastore { guild: { id: string, name?: string }, - statistics: { - [key: string]: { - "time": number, - "used": number - } - } | {}, - state: { - channels: { - "text": string, - "voice": string - }, - date: string, - station: { - name: string, - owner: string - } - } | {}, + statistics: statistics | {}, + state: state | {}, updated?: string } -export default class { - map: Map; +export default class Datastore { + map: Map; constructor() { this.map = new Map(); this.loadData(); @@ -66,7 +53,7 @@ export default class { } createEntry(id: string){ - let newData: entry = { + let newData: datastore = { guild: { id: id, }, @@ -89,7 +76,7 @@ export default class { return this.map.get(id); } - updateEntry(guild: Guild | { id: string, name: string }, newData: entry) { + updateEntry(guild: Guild | { id: string, name: string }, newData: datastore) { newData.guild.name = guild.name; let date = new Date(); @@ -100,32 +87,12 @@ export default class { //this.showEntry(this.getEntry(guild.id)); } - showEntry(data : entry){ + showEntry(data : datastore){ console.log(data); } - createTestFile () { - let newData = { - "guild": { - "id": "test", - "name": "Test" - }, - "statistics": { - "test": { - "time": 0, - "used": 0 - } - }, - "state": { - - } - } - - this.updateEntry(newData.guild, newData); - } - - saveEntry(file: string, data: entry) { - fs.writeFile(path.join(path.dirname(__dirname), '../../datastore') + "/" + file + ".json", JSON.stringify(data, null, 4), 'utf8', function(err: any) { + saveEntry(file: string, data: datastore) { + fs.writeFile(path.join(path.dirname(__dirname), '../../datastore') + "/" + file + ".json", JSON.stringify(data, null, 4), 'utf8', function(err: NodeJS.ErrnoException | null) { if (err) { } diff --git a/src/client/classes/Radio.ts b/src/client/classes/Radio.ts index 2137211..06020ef 100644 --- a/src/client/classes/Radio.ts +++ b/src/client/classes/Radio.ts @@ -1,27 +1,40 @@ -import { Guild, GuildMember, TextBasedChannel, VoiceBasedChannel, VoiceChannel } from "discord.js"; +import { Channel, Collection, GuildMember, OAuth2Guild, TextBasedChannel, VoiceBasedChannel, VoiceChannel } from "discord.js"; import { getVoiceConnection, joinVoiceChannel, VoiceConnection } from "@discordjs/voice"; import RadioClient from "../../Client"; import { station } from "./Stations"; +import { datastore } from "./Datastore"; export interface radio { - textChannel: TextBasedChannel | null, - voiceChannel: VoiceBasedChannel, + textChannel: Channel | TextBasedChannel | undefined | null, + voiceChannel: Channel | VoiceBasedChannel | undefined, connection: VoiceConnection | null, message: null, station: station, - datastore?: any, + datastore?: datastore, currentTime?: number, startTime: number, playTime?: number, } +export interface state extends Object { + channels: { + "text": string, + "voice": string + }, + date: string, + station: { + name: string, + owner: string + } +} + export default class Radio extends Map { constructor() { super(); } - save(client: RadioClient) { + save(client: RadioClient): void { let currentRadios = this.keys(); let radio = currentRadios.next(); @@ -29,7 +42,7 @@ export default class Radio extends Map { let currentRadio = this.get(radio.value); if (currentRadio) { - currentRadio.guild = client.datastore?.getEntry(radio.value).guild; + currentRadio.guild = client.datastore?.getEntry(radio.value)?.guild; client.statistics?.update(client, currentRadio.guild, currentRadio); client.funcs.saveState(client, currentRadio.guild, currentRadio); @@ -42,29 +55,32 @@ export default class Radio extends Map { } } - restore(client: RadioClient, guilds: any) { + restore(client: RadioClient, guilds: Collection): void { if(!client.stations) return; - guilds.forEach(async (guild: Guild) => { + guilds.forEach(async (guild: OAuth2Guild) => { let state = client.funcs.loadState(client, guild); + if(!state) return; - if(!state.station || !state.channels.voice || !state.channels.text) return; + if(!state.hasOwnProperty('station') || !state.hasOwnProperty('channels')) return; + let voiceChannel = client.channels.cache.get(state.channels.voice); if(!voiceChannel || !(voiceChannel instanceof VoiceChannel)) return; if(voiceChannel.members.filter((member: GuildMember) => !member.user.bot).size === 0) return; - - const sstation = await client.stations?.search(state.station.name, "direct"); + const sstation = client.stations?.search(state.station.name, "direct"); let station = sstation; if(!station) return; - const construct: any = { + let date = new Date(); + const construct: radio = { textChannel: client.channels.cache.get(state.channels.text), voiceChannel: client.channels.cache.get(state.channels.voice), connection: null, message: null, - station: station + station: station, + startTime: date.getTime() }; this.set(guild.id, construct); @@ -81,6 +97,7 @@ export default class Radio extends Map { let date = new Date(); construct.startTime = date.getTime(); client.datastore?.checkEntry(guild.id); + //@ts-ignore client.funcs.play(client, null, guild, station); } catch (error) { console.log(error); diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index a1b7fa1..637b413 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -1,62 +1,44 @@ -const _importDynamic = new Function('modulePath', 'return import(modulePath)'); -// @ts-ignore -const fetch = (...args: any) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); import logger from "../funcs/logger"; export interface station { name: string, owner: string, logo: string, - stream: any + stream: { + [key: string]: string + } } export default class Stations extends Array { - logger: any; + counter: number; constructor() { super(); + this.counter = 0; } - async fetch(options: any){ + async fetch(options: { url: string, show?: boolean }){ try { logger('Stations', 'Started fetching list - ' + options.url); - let list = await fetch(options.url) + let stations = await fetch(options.url) .then(this.checkFetchStatus) - .then((response: { json: () => station; }) => response.json()); + .then((response: { json: () => station[]; }) => response.json()); - if(list){ - this.length = 0; - list.forEach((station: station) => { - try { - this.push(station); - } catch (error) { - - } - }); - - if(options.show){ - list.forEach((station: { name: any; }) => { - logger('Stations', station.name); - }); - } - - list.forEach(async (station: station) => { - try { - let stationTest = await fetch(station.stream[station.stream.default]); - if(stationTest.ok === true) return; - this.splice(this.indexOf(station),1); - } catch (error) { - this.splice(this.indexOf(station),1); - } - }); + if(!stations) return; + for (const station of stations){ + this.push(station.name); + if(options.show) logger('Stations', station.name); } + this.counter = 0; + logger('Stations', 'Successfully fetched list'); } catch (error) { logger('Stations', 'Fetching list failed'); console.error(error + "\n"); - if(this.length == 0) this.fetch(options); + this.counter = this.counter + 1; + if(this.length == 0 && 5 < this.counter) this.fetch(options); } } @@ -126,21 +108,23 @@ export default class Stations extends Array { } } } - let highestProbabilityStation : any | { station: string, name: string, probability: number } | string | null = null; + /*let highestProbabilityStation : { station: string, name: string, probability: number } | string | undefined; for (let i = 0; i < foundStations.length; i++) { if ( !highestProbabilityStation || + //@ts-ignore highestProbabilityStation.probability < foundStations[i].probability ) highestProbabilityStation = foundStations[i]; if ( highestProbabilityStation && + //@ts-ignore highestProbabilityStation.probability === foundStations[i].probability ) { highestProbabilityStation = foundStations[i].station; } } - return highestProbabilityStation; + return highestProbabilityStation;*/ } } }; diff --git a/src/client/classes/Statistics.ts b/src/client/classes/Statistics.ts index 7f52bbd..438e5c0 100644 --- a/src/client/classes/Statistics.ts +++ b/src/client/classes/Statistics.ts @@ -2,8 +2,17 @@ import { Guild } from "discord.js"; import RadioClient from "../../Client"; import { radio } from "./Radio"; +export interface statistics { + [key: string]: statistic +} + +interface statistic { + "time": number, + "used": number +} + export default class Statistics { - map: Map; + map: Map; constructor() { this.map = new Map(); @@ -16,19 +25,26 @@ export default class Statistics { radio.datastore = client.datastore?.getEntry(guild.id); + //@ts-ignore if(!radio.datastore.statistics[radio.station.name]){ - radio.datastore.statistics[radio.station.name] = {}; - radio.datastore.statistics[radio.station.name].time = 0; - radio.datastore.statistics[radio.station.name].used = 0; + //@ts-ignore + radio.datastore.statistics[radio.station.name] = { + time: 0, + used: 0 + }; + //@ts-ignore client.datastore?.updateEntry(guild, radio.datastore); } let date = new Date(); radio.currentTime = date.getTime(); radio.playTime = radio.currentTime - radio.startTime; + //@ts-ignore radio.datastore.statistics[radio.station.name].time = parseInt(radio.datastore.statistics[radio.station.name].time) + radio.playTime; + //@ts-ignore radio.datastore.statistics[radio.station.name].used = parseInt(radio.datastore.statistics[radio.station.name].used)+1; + //@ts-ignore client.datastore?.updateEntry(guild, radio.datastore); this.calculateGlobal(client); } @@ -39,7 +55,7 @@ export default class Statistics { let guilds = client.datastore.map.keys(); let stations = client.stations; - let statistics : any = {}; + let statistics : statistics = {}; if(!client.stations) return; @@ -50,14 +66,18 @@ export default class Statistics { if(calculation.value != 'global'){ if(stations){ for(const station of stations) { - if(currentGuild.statistics[station.name] && currentGuild.statistics[station.name].time && parseInt(currentGuild.statistics[station.name].time) != 0 && currentGuild.statistics[station.name].used && parseInt(currentGuild.statistics[station.name].used) != 0){ + //@ts-ignore + if(currentGuild.statistics[station.name] && currentGuild.statistics[station.name]?.time && parseInt(currentGuild.statistics[station.name].time) != 0 && currentGuild.statistics[station.name].used && parseInt(currentGuild.statistics[station.name].used) != 0){ if(!statistics[station.name]){ - statistics[station.name] = {}; - statistics[station.name].time = 0; - statistics[station.name].used = 0; + statistics[station.name] = { + time: 0, + used: 0 + }; } + //@ts-ignore statistics[station.name].time = parseInt(statistics[station.name].time)+parseInt(currentGuild.statistics[station.name].time); + //@ts-ignore statistics[station.name].used = parseInt(statistics[station.name].used)+parseInt(currentGuild.statistics[station.name].used); } } @@ -66,11 +86,13 @@ export default class Statistics { calculation = guilds.next(); } - let newData : any = {}; - newData.guild = {}; - newData.guild.id = "global"; - newData.guild.name = "global"; - newData.statistics = statistics; + let newData = { + guild: { + id: "global", + name: "global" + }, + statistics: statistics + }; client.datastore.updateEntry(newData.guild, newData); } diff --git a/src/client/classes/Streamer.ts b/src/client/classes/Streamer.ts index 1da2190..6a55421 100644 --- a/src/client/classes/Streamer.ts +++ b/src/client/classes/Streamer.ts @@ -4,7 +4,7 @@ import RadioClient from "../../Client"; import { station } from "./Stations"; export default class Streamer { - map: any; + map: Map; mode: "auto" | "manual" = "manual"; constructor() { @@ -37,12 +37,11 @@ export default class Streamer { refresh(client: RadioClient){ this.init(client); - let streamers = this.map.keys(); - streamers.forEach((streamer: any) => { + for (const streamer of this.map.keys()){ if(client.stations?.findIndex((station: station) => station.name == streamer) == -1){ this.stop(streamer); } - }); + } } play(station: station) { @@ -94,14 +93,14 @@ export default class Streamer { return audioPlayer; } - stop(station: station){ - let audioPlayer = this.map.get(station.name); + stop(streamer: string){ + let audioPlayer = this.map.get(streamer); if(audioPlayer){ - logger('Streamer', station.name + " / " + "Stop"); + logger('Streamer', streamer + " / " + "Stop"); audioPlayer.removeAllListeners(); audioPlayer.stop(); } - this.map.delete(station.name); + this.map.delete(streamer); } listen(station: station) { @@ -113,7 +112,7 @@ export default class Streamer { leave(client: RadioClient) { if(!client.stations) return; client.stations.forEach((station: station) => { - this.stop(station); + this.stop(station.name); }); } }; diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index eb20c3a..7985e33 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -1,10 +1,7 @@ -import { ActionRowBuilder, AnyComponentBuilder, APIActionRowComponent, APISelectMenuOption, ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js"; +import { ActionRowBuilder, APISelectMenuOption, ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import Streamer from "../classes/Streamer"; import commands from "../commands"; -const _importDynamic = new Function('modulePath', 'return import(modulePath)'); -// @ts-ignore -const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args)); export default { name: 'maintenance', diff --git a/src/client/events/ready.ts b/src/client/events/ready.ts index b36ebf5..3defdb1 100644 --- a/src/client/events/ready.ts +++ b/src/client/events/ready.ts @@ -1,10 +1,11 @@ import RadioClient from "../../Client"; -import Datastore from "../classes/Datastore"; +import Datastore, { datastore } from "../classes/Datastore"; import Radio from "../classes/Radio"; import Stations from "../classes/Stations"; import Streamer from "../classes/Streamer"; import Statistics from "../classes/Statistics"; import commands from "../commands"; +import { OAuth2Guild } from "discord.js"; export default async function ready(client: RadioClient) { client.funcs.logger("Bot", "Ready"); @@ -13,7 +14,7 @@ export default async function ready(client: RadioClient) { client.funcs.logger('Datastore', 'Initialize'); client.datastore = new Datastore(); - client.datastore.map.forEach((datastore: { guild: { id: string; name: string; }; }) => { + client.datastore.map.forEach((datastore: datastore) => { client.funcs.logger('Datastore', datastore.guild.id + " / " + datastore.guild.name); }); @@ -45,7 +46,7 @@ export default async function ready(client: RadioClient) { client.funcs.logger('Guilds', 'Started fetching list'); let guilds = await client.guilds.fetch(); - guilds.forEach((guild: { id: string; name: string; }) => { + guilds.forEach((guild: OAuth2Guild) => { client.funcs.logger('Guilds', guild.id + " / " + guild.name); }); diff --git a/src/client/funcs/loadState.ts b/src/client/funcs/loadState.ts index cc69fd6..a2922f8 100644 --- a/src/client/funcs/loadState.ts +++ b/src/client/funcs/loadState.ts @@ -1,15 +1,12 @@ -import { Guild } from "discord.js"; +import { OAuth2Guild } from "discord.js"; import RadioClient from "../../Client"; -export default function loadState(client: RadioClient, guild: Guild){ +export default function loadState(client: RadioClient, guild: OAuth2Guild) { if(!client.datastore) return; let data = client.datastore.getEntry(guild.id); if(!data) return; - let state; - - state = data.state; + let state = data.state; if(!state) return; - data.state = {}; client.datastore.updateEntry(guild, data); return state; diff --git a/src/client/funcs/play.ts b/src/client/funcs/play.ts index c46131b..9738730 100644 --- a/src/client/funcs/play.ts +++ b/src/client/funcs/play.ts @@ -1,8 +1,8 @@ -import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, Guild, StringSelectMenuInteraction } from "discord.js"; +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, Guild, OAuth2Guild, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import { station } from "../classes/Stations"; -export default async function play(client: RadioClient, interaction: ChatInputCommandInteraction | StringSelectMenuInteraction | null, guild: Guild | null, station: station) { +export default async function play(client: RadioClient, interaction: ChatInputCommandInteraction | StringSelectMenuInteraction | null, guild: OAuth2Guild | Guild | null, station: station) { if(!guild) return; const radio = client.radio?.get(guild.id); diff --git a/src/client/funcs/saveState.ts b/src/client/funcs/saveState.ts index 9634ccb..63a6dd5 100644 --- a/src/client/funcs/saveState.ts +++ b/src/client/funcs/saveState.ts @@ -9,15 +9,18 @@ export default function saveState(client: RadioClient, guild: Guild, radio: radi let date = new Date(); let data = client.datastore.getEntry(guild.id); - - data.state = {}; - data.state.channels = {}; - data.state.channels.text = radio.textChannel?.id; - data.state.channels.voice = radio.voiceChannel.id; - data.state.date = date.toISOString(); - data.state.station = {}; - data.state.station.name = radio.station.name; - data.state.station.owner = radio.station.owner; + if(!data) return; + data.state = { + channels: { + text: radio.textChannel?.id, + voice: radio.voiceChannel?.id + }, + date: date.toISOString(), + station: { + name: radio.station.name, + owner: radio.station.owner + } + }; client.datastore.updateEntry(guild, data); } From 24a6e80f26c7ed4b24543428e6f276d914da37e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Wed, 7 Jun 2023 17:42:21 +0300 Subject: [PATCH 30/44] Adding more typings --- src/client/classes/Datastore.ts | 6 +++--- src/client/classes/Radio.ts | 10 +++++----- src/client/commands/list.ts | 3 ++- src/client/funcs/loadState.ts | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/client/classes/Datastore.ts b/src/client/classes/Datastore.ts index 3efa223..9f4f1fe 100644 --- a/src/client/classes/Datastore.ts +++ b/src/client/classes/Datastore.ts @@ -9,8 +9,8 @@ export interface datastore { id: string, name?: string }, - statistics: statistics | {}, - state: state | {}, + statistics: statistics, + state: state | null, updated?: string } @@ -58,7 +58,7 @@ export default class Datastore { id: id, }, statistics: {}, - state: {} + state: null }; this.map.set(id, newData); this.saveEntry(id, newData); diff --git a/src/client/classes/Radio.ts b/src/client/classes/Radio.ts index 06020ef..357c120 100644 --- a/src/client/classes/Radio.ts +++ b/src/client/classes/Radio.ts @@ -16,10 +16,10 @@ export interface radio { playTime?: number, } -export interface state extends Object { +export interface state { channels: { - "text": string, - "voice": string + "text": string | undefined, + "voice": string | undefined }, date: string, station: { @@ -62,7 +62,7 @@ export default class Radio extends Map { let state = client.funcs.loadState(client, guild); if(!state) return; - if(!state.hasOwnProperty('station') || !state.hasOwnProperty('channels')) return; + if(state.channels?.text === undefined || state.channels?.voice === undefined) return; let voiceChannel = client.channels.cache.get(state.channels.voice); if(!voiceChannel || !(voiceChannel instanceof VoiceChannel)) return; @@ -97,7 +97,7 @@ export default class Radio extends Map { let date = new Date(); construct.startTime = date.getTime(); client.datastore?.checkEntry(guild.id); - //@ts-ignore + client.funcs.play(client, null, guild, station); } catch (error) { console.log(error); diff --git a/src/client/commands/list.ts b/src/client/commands/list.ts index eba28ed..12fabe3 100644 --- a/src/client/commands/list.ts +++ b/src/client/commands/list.ts @@ -1,5 +1,6 @@ import { ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; +import { station } from "../classes/Stations"; export default { name: 'list', @@ -21,7 +22,7 @@ export default { if(radio && !client.config.maintenanceMode){ client.funcs.listStations(client, interaction); } else { - let stations = `${client.stations.map((s: { name: any; }) => `**#** ${s.name}`).join('\n')}` + let stations = `${client.stations.map((s: station) => `**#** ${s.name}`).join('\n')}` const hashs = stations.split('**#**').length; for (let i = 0; i < hashs; i++) { stations = stations.replace('**#**', `**${i + 1}.**`); diff --git a/src/client/funcs/loadState.ts b/src/client/funcs/loadState.ts index a2922f8..67f4ffa 100644 --- a/src/client/funcs/loadState.ts +++ b/src/client/funcs/loadState.ts @@ -7,7 +7,7 @@ export default function loadState(client: RadioClient, guild: OAuth2Guild) { if(!data) return; let state = data.state; if(!state) return; - data.state = {}; + data.state = null; client.datastore.updateEntry(guild, data); return state; } From cbae9ae38f71bf259f6ca66892a0cb01ca1de824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Wed, 7 Jun 2023 17:43:02 +0300 Subject: [PATCH 31/44] Fix Stations class --- src/client/classes/Stations.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index 637b413..cff62c5 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -10,14 +10,12 @@ export interface station { } export default class Stations extends Array { - counter: number; constructor() { super(); - this.counter = 0; } - async fetch(options: { url: string, show?: boolean }){ + async fetch(options: { url: string, show?: boolean}){ try { logger('Stations', 'Started fetching list - ' + options.url); let stations = await fetch(options.url) @@ -26,19 +24,18 @@ export default class Stations extends Array { if(!stations) return; for (const station of stations){ - this.push(station.name); + this.push(station); if(options.show) logger('Stations', station.name); } - this.counter = 0; - logger('Stations', 'Successfully fetched list'); } catch (error) { logger('Stations', 'Fetching list failed'); console.error(error + "\n"); - this.counter = this.counter + 1; - if(this.length == 0 && 5 < this.counter) this.fetch(options); + if(this.length == 0) setTimeout( () => { + this.fetch(options) + }, 150 ); } } @@ -57,10 +54,10 @@ export default class Stations extends Array { if(type == "direct"){ let foundStation; - this.forEach(station => { + for(const station of this){ if(station.name != key) return false; foundStation = station; - }); + } return foundStation; } else { From d260c6ea4f4376af44908261fd33081898943edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Wed, 7 Jun 2023 17:43:19 +0300 Subject: [PATCH 32/44] Fix Statistics class --- src/client/classes/Statistics.ts | 36 ++++++++++++++------------------ 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/client/classes/Statistics.ts b/src/client/classes/Statistics.ts index 438e5c0..78ea997 100644 --- a/src/client/classes/Statistics.ts +++ b/src/client/classes/Statistics.ts @@ -25,36 +25,31 @@ export default class Statistics { radio.datastore = client.datastore?.getEntry(guild.id); - //@ts-ignore + if(radio.datastore === undefined) return; + if(!radio.datastore.statistics[radio.station.name]){ - //@ts-ignore radio.datastore.statistics[radio.station.name] = { time: 0, used: 0 }; - //@ts-ignore client.datastore?.updateEntry(guild, radio.datastore); } let date = new Date(); radio.currentTime = date.getTime(); radio.playTime = radio.currentTime - radio.startTime; - //@ts-ignore - radio.datastore.statistics[radio.station.name].time = parseInt(radio.datastore.statistics[radio.station.name].time) + radio.playTime; - - //@ts-ignore - radio.datastore.statistics[radio.station.name].used = parseInt(radio.datastore.statistics[radio.station.name].used)+1; - //@ts-ignore + radio.datastore.statistics[radio.station.name] = { + time: radio.datastore.statistics[radio.station.name].time + radio.playTime, + used: radio.datastore.statistics[radio.station.name].used + 1 + } client.datastore?.updateEntry(guild, radio.datastore); this.calculateGlobal(client); } calculateGlobal(client: RadioClient){ - if(!client.stations) return; if(!client.datastore?.map) return; let guilds = client.datastore.map.keys(); - let stations = client.stations; let statistics : statistics = {}; if(!client.stations) return; @@ -64,10 +59,10 @@ export default class Statistics { while (!calculation.done) { let currentGuild = client.datastore.getEntry(calculation.value); if(calculation.value != 'global'){ - if(stations){ - for(const station of stations) { - //@ts-ignore - if(currentGuild.statistics[station.name] && currentGuild.statistics[station.name]?.time && parseInt(currentGuild.statistics[station.name].time) != 0 && currentGuild.statistics[station.name].used && parseInt(currentGuild.statistics[station.name].used) != 0){ + if(client.stations){ + for(const station of client.stations) { + if(!currentGuild) return; + if(currentGuild.statistics[station.name] && currentGuild.statistics[station.name]?.time && currentGuild.statistics[station.name].time != 0 && currentGuild.statistics[station.name].used && currentGuild.statistics[station.name].used != 0){ if(!statistics[station.name]){ statistics[station.name] = { time: 0, @@ -75,10 +70,10 @@ export default class Statistics { }; } - //@ts-ignore - statistics[station.name].time = parseInt(statistics[station.name].time)+parseInt(currentGuild.statistics[station.name].time); - //@ts-ignore - statistics[station.name].used = parseInt(statistics[station.name].used)+parseInt(currentGuild.statistics[station.name].used); + statistics[station.name] = { + time: statistics[station.name].time + currentGuild.statistics[station.name].time, + used: statistics[station.name].used + currentGuild.statistics[station.name].used + } } } } @@ -91,7 +86,8 @@ export default class Statistics { id: "global", name: "global" }, - statistics: statistics + statistics: statistics, + state: null }; client.datastore.updateEntry(newData.guild, newData); } From 9e165713ce327ae357544bac41a81b45878006a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Wed, 7 Jun 2023 17:43:39 +0300 Subject: [PATCH 33/44] Fix Streamer class --- src/client/classes/Streamer.ts | 43 ++++++++++++++++------------------ 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/src/client/classes/Streamer.ts b/src/client/classes/Streamer.ts index 6a55421..a3f7157 100644 --- a/src/client/classes/Streamer.ts +++ b/src/client/classes/Streamer.ts @@ -1,14 +1,15 @@ import logger from "../funcs/logger"; -import { createAudioPlayer, createAudioResource, NoSubscriberBehavior } from "@discordjs/voice"; +import { AudioPlayer, AudioPlayerStatus, createAudioPlayer, createAudioResource, NoSubscriberBehavior } from "@discordjs/voice"; import RadioClient from "../../Client"; import { station } from "./Stations"; export default class Streamer { - map: Map; - mode: "auto" | "manual" = "manual"; + map: Map; + mode: "auto" | "manual"; constructor() { this.map = new Map(); + this.mode = "manual"; } init(client: RadioClient){ @@ -28,9 +29,9 @@ export default class Streamer { if(this.mode == "auto"){ if(!client.stations) return; - client.stations.forEach((station: station) => { + for(const station of client.stations){ this.play(station); - }); + } } } @@ -52,44 +53,40 @@ export default class Streamer { behaviors: { noSubscriber: NoSubscriberBehavior.Play, maxMissedFrames: Math.round(5000 / 20), - }, + } }); - } - if(this.mode == "manual"){ + } else { audioPlayer = createAudioPlayer({ behaviors: { noSubscriber: NoSubscriberBehavior.Stop, maxMissedFrames: Math.round(5000 / 20), - }, + } }); } + this.map.set(station.name, audioPlayer); } + const url = station.stream[station.stream.default]; const resource = createAudioResource(url); audioPlayer.play(resource); + audioPlayer - .on('playing', () => { + .on(AudioPlayerStatus.Playing, () => { logger('Streamer', station.name + " / " + "Playing"); }) - .on('idle', () => { + .on(AudioPlayerStatus.Idle, () => { logger('Streamer', station.name + " / " + "Idle"); - audioPlayer.removeAllListeners(); - if(this.mode == "manual" && audioPlayer.subscribers.length == 0) return; - this.play(station); }) - .on('paused', () => { + .on(AudioPlayerStatus.Paused, () => { logger('Streamer', station.name + " / " + "Paused"); }) - .on('buffering', () => { + .on(AudioPlayerStatus.Buffering, () => { logger('Streamer', station.name + " / " + "Buffering"); }) - .on('autopaused', () => { + .on(AudioPlayerStatus.AutoPaused, () => { logger('Streamer', station.name + " / " + "AutoPaused"); }) - .on('error', (error: string) => { - logger('Streamer', station.name + " / " + "Error" + "\n" + error); - }); return audioPlayer; } @@ -105,14 +102,14 @@ export default class Streamer { listen(station: station) { let audioPlayer = this.map.get(station.name); - if(!audioPlayer || this.mode == "manual" && audioPlayer.subscribers.length == 0) audioPlayer = this.play(station); + if(!audioPlayer) audioPlayer = this.play(station); return audioPlayer; } leave(client: RadioClient) { if(!client.stations) return; - client.stations.forEach((station: station) => { + for(const station of client.stations){ this.stop(station.name); - }); + } } }; From 938f8ab69b8bc21b11a485a714a6f867d81f3070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Wed, 7 Jun 2023 17:46:47 +0300 Subject: [PATCH 34/44] Remove unnecessary await in Play command --- src/client/commands/play.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index 1186211..7857245 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -96,7 +96,7 @@ export default { type = "direct"; } - const sstation = await client.stations.search(query, type); + const sstation = client.stations.search(query, type); if (!sstation) return interaction.reply({ content: client.messages.emojis["error"] + client.messages.noSearchResults, ephemeral: true From b29624cba324349d98e53fa7afb1300868103b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Wed, 7 Jun 2023 17:47:39 +0300 Subject: [PATCH 35/44] Update listStations function --- src/client/funcs/listStations.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/client/funcs/listStations.ts b/src/client/funcs/listStations.ts index 74ed88d..bddb5f1 100644 --- a/src/client/funcs/listStations.ts +++ b/src/client/funcs/listStations.ts @@ -1,20 +1,18 @@ import { ActionRowBuilder, ButtonInteraction, ChatInputCommandInteraction, SelectMenuComponentOptionData, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; -import { station } from "../classes/Stations"; export default function listStations(client: RadioClient, interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction){ if(!client.stations) return; let options : SelectMenuComponentOptionData[] = new Array(); - client.stations.forEach((station: station) => { - if(station.name == "GrooveFM") return; + for (const station of client.stations){ options.push({ label: station.name, description: station.owner, value: station.name }); - }); + } const menu: ActionRowBuilder = new ActionRowBuilder() .addComponents( From 3f1d576c44fe4f67cade52be9eea7b938f261ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Wed, 7 Jun 2023 21:33:28 +0300 Subject: [PATCH 36/44] Add more Typescript typings --- src/client/classes/Stations.ts | 27 ++++++++++++--------------- src/client/commands.ts | 2 +- src/client/commands/bug.ts | 4 ++-- src/client/commands/help.ts | 4 ++-- src/client/commands/invite.ts | 4 ++-- src/client/commands/list.ts | 4 ++-- src/client/commands/maintenance.ts | 6 +++--- src/client/commands/nowplaying.ts | 4 ++-- src/client/commands/statistics.ts | 4 ++-- src/client/commands/status.ts | 4 ++-- src/client/commands/stop.ts | 4 ++-- src/client/funcs/listStations.ts | 2 +- src/client/funcs/play.ts | 6 +++--- src/config.ts | 4 +++- 14 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index cff62c5..8979505 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -18,11 +18,10 @@ export default class Stations extends Array { async fetch(options: { url: string, show?: boolean}){ try { logger('Stations', 'Started fetching list - ' + options.url); - let stations = await fetch(options.url) + let stations: station[] = await fetch(options.url) .then(this.checkFetchStatus) - .then((response: { json: () => station[]; }) => response.json()); + .then((response: Response) => response.json()); - if(!stations) return; for (const station of stations){ this.push(station); if(options.show) logger('Stations', station.name); @@ -39,7 +38,7 @@ export default class Stations extends Array { } } - checkFetchStatus(response: any) { + checkFetchStatus(response: Response) { if (response.ok) { return response; } else { @@ -48,14 +47,12 @@ export default class Stations extends Array { } search(key: string, type: string) { - if (this === null) return false; - if (!key) return false; - if (!type) return false; + if (this === null || !key || !type) return null; if(type == "direct"){ let foundStation; for(const station of this){ - if(station.name != key) return false; + if(station.name != key) return null; foundStation = station; } @@ -63,7 +60,7 @@ export default class Stations extends Array { } else { let foundStations : { station: string, name: string, probability: number }[] = []; - if (key == "radio") return false; + if (key == "radio") return null; this .filter( @@ -84,7 +81,7 @@ export default class Stations extends Array { foundStations.push({ station: x, name: x.name, probability: probabilityIncrement }) ); } - if (foundStations.length === 0) return false; + if (foundStations.length === 0) return null; for (let i = 0; i < foundStations.length; i++) { for (let j = 0; j < foundStations.length; j++) { if (foundStations[i] === foundStations[j] && i !== j) foundStations.splice(i, 1); @@ -105,23 +102,23 @@ export default class Stations extends Array { } } } - /*let highestProbabilityStation : { station: string, name: string, probability: number } | string | undefined; + let highestProbabilityStation : { station: string, name: string, probability: number } | undefined; + let stationName = ""; + for (let i = 0; i < foundStations.length; i++) { if ( !highestProbabilityStation || - //@ts-ignore highestProbabilityStation.probability < foundStations[i].probability ) highestProbabilityStation = foundStations[i]; if ( highestProbabilityStation && - //@ts-ignore highestProbabilityStation.probability === foundStations[i].probability ) { - highestProbabilityStation = foundStations[i].station; + stationName = foundStations[i].station; } } - return highestProbabilityStation;*/ + return stationName; } } }; diff --git a/src/client/commands.ts b/src/client/commands.ts index d2fe02a..87244c1 100644 --- a/src/client/commands.ts +++ b/src/client/commands.ts @@ -18,7 +18,7 @@ export interface command { description: string, category: string, options?: [], - execute: any + execute: Function } export default async function commands(client: RadioClient) { diff --git a/src/client/commands/bug.ts b/src/client/commands/bug.ts index 3a66e87..5fb9e57 100644 --- a/src/client/commands/bug.ts +++ b/src/client/commands/bug.ts @@ -1,4 +1,4 @@ -import { ChatInputCommandInteraction, ColorResolvable, EmbedBuilder } from "discord.js"; +import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js"; import RadioClient from "../../Client"; export default { @@ -16,7 +16,7 @@ export default { "%client.user.username%": client.user.username })) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor as ColorResolvable) + .setColor(client.config.embedColor) .setDescription(client.messages.replace(client.messages.bugDescription, { "%client.config.supportGuild%": client.config.supportGuild })) diff --git a/src/client/commands/help.ts b/src/client/commands/help.ts index 17b8619..b81ba1b 100644 --- a/src/client/commands/help.ts +++ b/src/client/commands/help.ts @@ -1,4 +1,4 @@ -import { ChatInputCommandInteraction, ColorResolvable, EmbedBuilder } from "discord.js"; +import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js"; import RadioClient from "../../Client"; import { command } from "../commands"; @@ -27,7 +27,7 @@ export default { "%client.user.username%": client.user.username })) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor as ColorResolvable) + .setColor(client.config.embedColor) .setDescription(client.messages.replace(client.messages.helpDescription, { "%commands%": commands })) diff --git a/src/client/commands/invite.ts b/src/client/commands/invite.ts index 65268be..a45d52c 100644 --- a/src/client/commands/invite.ts +++ b/src/client/commands/invite.ts @@ -1,4 +1,4 @@ -import { ChatInputCommandInteraction, ColorResolvable, EmbedBuilder } from "discord.js"; +import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js"; import RadioClient from "../../Client"; export default { @@ -16,7 +16,7 @@ export default { .setTitle(client.messages.replace(client.messages.inviteTitle, { "%client.user.username%": client.user.username })) - .setColor(client.config.embedColor as ColorResolvable) + .setColor(client.config.embedColor) .setURL("https://discord.com/api/oauth2/authorize?client_id=" + client.user.id + "&permissions=2184465408&scope=applications.commands%20bot") //View Channels, Send Messages, Embed Links, Use External Emojis, Use Slash Commands, Connect, Speak, Use Voice Activity .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ diff --git a/src/client/commands/list.ts b/src/client/commands/list.ts index 12fabe3..165b93d 100644 --- a/src/client/commands/list.ts +++ b/src/client/commands/list.ts @@ -1,4 +1,4 @@ -import { ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; +import { ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import { station } from "../classes/Stations"; @@ -31,7 +31,7 @@ export default { let embed = new EmbedBuilder() .setTitle(client.messages.listTitle) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["list"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor as ColorResolvable) + .setColor(client.config.embedColor) .setDescription(stations) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index 7985e33..e255915 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -1,4 +1,4 @@ -import { ActionRowBuilder, APISelectMenuOption, ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js"; +import { ActionRowBuilder, APISelectMenuOption, ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import Streamer from "../classes/Streamer"; import commands from "../commands"; @@ -95,7 +95,7 @@ export default { } ); - const menu : ActionRowBuilder = new ActionRowBuilder() + const menu = new ActionRowBuilder() .addComponents( new StringSelectMenuBuilder() .setCustomId('maintenance') @@ -115,7 +115,7 @@ export default { const embed = new EmbedBuilder() .setTitle(client.messages.maintenanceTitle) - .setColor(client.config.embedColor as ColorResolvable) + .setColor(client.config.embedColor) .setDescription(options.find((option: APISelectMenuOption) => option.value == action)?.label || "-") .setFooter({ text: client.messages.footerText, diff --git a/src/client/commands/nowplaying.ts b/src/client/commands/nowplaying.ts index 8b07394..20ed34e 100644 --- a/src/client/commands/nowplaying.ts +++ b/src/client/commands/nowplaying.ts @@ -1,4 +1,4 @@ -import { ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; +import { ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import { command } from "../commands"; @@ -19,7 +19,7 @@ export default { const embed = new EmbedBuilder() .setTitle(client.messages.nowplayingTitle) .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messages.emojis["play"].replace(/[^0-9]+/g, ''))) - .setColor(client.config.embedColor as ColorResolvable) + .setColor(client.config.embedColor) .setDescription(client.messages.replace(client.messages.nowplayingDescription, { "%radio.station.name%": radio.station.name, "%radio.station.owner%\n": radio.station.name != radio.station.owner ? radio.station.owner + "\n" : "", diff --git a/src/client/commands/statistics.ts b/src/client/commands/statistics.ts index 0cccbfb..f33be1b 100644 --- a/src/client/commands/statistics.ts +++ b/src/client/commands/statistics.ts @@ -1,4 +1,4 @@ -import { ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; +import { ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; @@ -36,7 +36,7 @@ export default { const embed = new EmbedBuilder() .setTitle(client.messages.statisticsTitle) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["statistics"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor as ColorResolvable) + .setColor(client.config.embedColor) .setDescription(statistics) .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') .setFooter({ diff --git a/src/client/commands/status.ts b/src/client/commands/status.ts index bcca102..ebc23c9 100644 --- a/src/client/commands/status.ts +++ b/src/client/commands/status.ts @@ -1,4 +1,4 @@ -import { ChatInputCommandInteraction, ColorResolvable, EmbedBuilder } from "discord.js"; +import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js"; import RadioClient from "../../Client"; export default { @@ -19,7 +19,7 @@ export default { "%client.user.username%": client.user.username })) .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor as ColorResolvable) + .setColor(client.config.embedColor) .addFields([ { name: client.messages.statusField1, value: uptime }, { name: client.messages.statusField2, value: client.config.version }, diff --git a/src/client/commands/stop.ts b/src/client/commands/stop.ts index 75303e2..aa15563 100644 --- a/src/client/commands/stop.ts +++ b/src/client/commands/stop.ts @@ -1,4 +1,4 @@ -import { ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; +import { ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import { command } from "../commands"; @@ -16,7 +16,7 @@ export default { const embed = new EmbedBuilder() .setTitle(client.user?.username || "-") .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["stop"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor as ColorResolvable) + .setColor(client.config.embedColor) .addFields({ name: client.messages.nowplayingTitle, value: "-" diff --git a/src/client/funcs/listStations.ts b/src/client/funcs/listStations.ts index bddb5f1..96349a6 100644 --- a/src/client/funcs/listStations.ts +++ b/src/client/funcs/listStations.ts @@ -14,7 +14,7 @@ export default function listStations(client: RadioClient, interaction: ButtonInt }); } - const menu: ActionRowBuilder = new ActionRowBuilder() + const menu = new ActionRowBuilder() .addComponents( new StringSelectMenuBuilder() .setCustomId('play') diff --git a/src/client/funcs/play.ts b/src/client/funcs/play.ts index 9738730..ca062d3 100644 --- a/src/client/funcs/play.ts +++ b/src/client/funcs/play.ts @@ -1,4 +1,4 @@ -import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, Guild, OAuth2Guild, StringSelectMenuInteraction } from "discord.js"; +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, EmbedBuilder, Guild, OAuth2Guild, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import { station } from "../classes/Stations"; @@ -13,7 +13,7 @@ export default async function play(client: RadioClient, interaction: ChatInputCo const embed = new EmbedBuilder() .setTitle(client.user?.username || "-") .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messages.emojis["play"].replace(/[^0-9]+/g, ''))) - .setColor(client.config.embedColor as ColorResolvable) + .setColor(client.config.embedColor) .addFields({ name: client.messages.nowplayingTitle, value: client.messages.replace(client.messages.nowplayingDescription, { @@ -30,7 +30,7 @@ export default async function play(client: RadioClient, interaction: ChatInputCo iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '') }); - const buttons = new ActionRowBuilder() + const buttons = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId('list') diff --git a/src/config.ts b/src/config.ts index aa8aa22..59df496 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,3 +1,5 @@ +import { ColorResolvable } from "discord.js"; + export default { //credentials @@ -14,7 +16,7 @@ export default { ], //misc - embedColor: "#88aa00", + embedColor: "#88aa00" as ColorResolvable, hostedBy: "[Warén Group](https://waren.io)", //Settings From 408c5aaab811db4cc5cd6058d9138e742bdaa372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Thu, 8 Jun 2023 00:28:48 +0300 Subject: [PATCH 37/44] Limit commands in maintenance mode --- src/client/commands/list.ts | 7 +++++++ src/client/commands/next.ts | 19 +++++++++++++++---- src/client/commands/prev.ts | 19 +++++++++++++++---- src/client/events/interactionCreate.ts | 7 ------- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/client/commands/list.ts b/src/client/commands/list.ts index 165b93d..563d418 100644 --- a/src/client/commands/list.ts +++ b/src/client/commands/list.ts @@ -8,6 +8,13 @@ export default { category: 'radio', execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { + if(client.config.maintenanceMode){ + return interaction.reply({ + content: client.messages.emojis["error"] + client.messages.maintenance, + ephemeral: true + }); + } + if(!client.stations) { return interaction.reply({ content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, { diff --git a/src/client/commands/next.ts b/src/client/commands/next.ts index 43a3b92..60dfd46 100644 --- a/src/client/commands/next.ts +++ b/src/client/commands/next.ts @@ -11,10 +11,21 @@ export default { if (client.funcs.check(client, interaction, command)) { const radio = client.radio?.get(interaction.guild?.id); - if(!client.stations) return interaction.reply({ - content: client.messages.emojis["error"] + client.messages.maintenance, - ephemeral: true - }); + if(client.config.maintenanceMode){ + return interaction.reply({ + content: client.messages.emojis["error"] + client.messages.maintenance, + ephemeral: true + }); + } + + if(!client.stations) { + return interaction.reply({ + content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, { + "%client.config.supportGuild%": client.config.supportGuild + }), + ephemeral: true + }); + } let index: number = client.stations.findIndex((station: station) => station.name == radio.station.name) + 1; if(index == client.stations?.length) index = 0; diff --git a/src/client/commands/prev.ts b/src/client/commands/prev.ts index d705c46..fa8e39c 100644 --- a/src/client/commands/prev.ts +++ b/src/client/commands/prev.ts @@ -11,10 +11,21 @@ export default { if (client.funcs.check(client, interaction, command)) { const radio = client.radio?.get(interaction.guild?.id); - if(!client.stations) return interaction.reply({ - content: client.messages.emojis["error"] + client.messages.maintenance, - ephemeral: true - }); + if(client.config.maintenanceMode){ + return interaction.reply({ + content: client.messages.emojis["error"] + client.messages.maintenance, + ephemeral: true + }); + } + + if(!client.stations) { + return interaction.reply({ + content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, { + "%client.config.supportGuild%": client.config.supportGuild + }), + ephemeral: true + }); + } let index = client.stations.findIndex((station: station) => station.name == radio.station.name) - 1; if(index == -1) index = client.stations.length - 1; diff --git a/src/client/events/interactionCreate.ts b/src/client/events/interactionCreate.ts index 25387ca..0002943 100644 --- a/src/client/events/interactionCreate.ts +++ b/src/client/events/interactionCreate.ts @@ -4,13 +4,6 @@ import RadioClient from "../../Client"; export default function interactionCreate(client: RadioClient, interaction: Interaction) { if(!(interaction.isButton()) && !(interaction.isChatInputCommand()) && !(interaction.isStringSelectMenu())) return; - if(client.config.maintenanceMode){ - return interaction.reply({ - content: client.messages.emojis["error"] + client.messages.maintenance, - ephemeral: true - }); - } - //@ts-ignore const permissions = interaction.channel?.permissionsFor(interaction.client.user); if (!permissions.has(PermissionFlagsBits.ViewChannel)) return; From 2579549f0bc352a6a4d989f9b2e2f1f0958925e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Thu, 8 Jun 2023 00:30:01 +0300 Subject: [PATCH 38/44] Create event listeners once in Streamer class --- src/client/classes/Streamer.ts | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/client/classes/Streamer.ts b/src/client/classes/Streamer.ts index a3f7157..9e583e2 100644 --- a/src/client/classes/Streamer.ts +++ b/src/client/classes/Streamer.ts @@ -64,6 +64,23 @@ export default class Streamer { }); } + audioPlayer + .on(AudioPlayerStatus.Playing, () => { + logger('Streamer', station.name + " / " + "Playing"); + }) + .on(AudioPlayerStatus.Idle, () => { + logger('Streamer', station.name + " / " + "Idle"); + }) + .on(AudioPlayerStatus.Paused, () => { + logger('Streamer', station.name + " / " + "Paused"); + }) + .on(AudioPlayerStatus.Buffering, () => { + logger('Streamer', station.name + " / " + "Buffering"); + }) + .on(AudioPlayerStatus.AutoPaused, () => { + logger('Streamer', station.name + " / " + "AutoPaused"); + }) + this.map.set(station.name, audioPlayer); } @@ -71,22 +88,6 @@ export default class Streamer { const resource = createAudioResource(url); audioPlayer.play(resource); - audioPlayer - .on(AudioPlayerStatus.Playing, () => { - logger('Streamer', station.name + " / " + "Playing"); - }) - .on(AudioPlayerStatus.Idle, () => { - logger('Streamer', station.name + " / " + "Idle"); - }) - .on(AudioPlayerStatus.Paused, () => { - logger('Streamer', station.name + " / " + "Paused"); - }) - .on(AudioPlayerStatus.Buffering, () => { - logger('Streamer', station.name + " / " + "Buffering"); - }) - .on(AudioPlayerStatus.AutoPaused, () => { - logger('Streamer', station.name + " / " + "AutoPaused"); - }) return audioPlayer; } From b5caeb7cd34243f6abd475b831e77b1268628e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Thu, 8 Jun 2023 00:30:28 +0300 Subject: [PATCH 39/44] Remove unused variable Statistics commands --- src/client/commands/statistics.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/commands/statistics.ts b/src/client/commands/statistics.ts index f33be1b..636be21 100644 --- a/src/client/commands/statistics.ts +++ b/src/client/commands/statistics.ts @@ -13,7 +13,6 @@ export default { ephemeral: true }); - let stations = client.stations; let currentGuild = client.datastore?.getEntry(interaction.guild.id); let global = client.datastore?.getEntry("global"); let statistics = ""; From 6de5e69dc0da4b1edc3227f723ce98e604324958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Thu, 8 Jun 2023 00:31:13 +0300 Subject: [PATCH 40/44] Limit Play command when on maintenance mode --- src/client/commands/play.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index 7857245..e9bb0cc 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -13,6 +13,13 @@ export default { category: "radio", async execute(interaction: ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { + if(client.config.maintenanceMode){ + return interaction.reply({ + content: client.messages.emojis["error"] + client.messages.maintenance, + ephemeral: true + }); + } + if(!client.stations) { return interaction.reply({ content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, { From 64f53c38d7c7ee2206bf4db632abbcc1f2c7d8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Thu, 8 Jun 2023 00:48:03 +0300 Subject: [PATCH 41/44] Remove ts-ignore and fix usage reason --- src/client/events/interactionCreate.ts | 17 +++++++++-------- src/client/funcs/check.ts | 6 +++--- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/client/events/interactionCreate.ts b/src/client/events/interactionCreate.ts index 0002943..8a5986d 100644 --- a/src/client/events/interactionCreate.ts +++ b/src/client/events/interactionCreate.ts @@ -1,17 +1,18 @@ -import { Interaction, PermissionFlagsBits } from "discord.js"; +import { ChannelType, Interaction, PermissionFlagsBits } from "discord.js"; import RadioClient from "../../Client"; export default function interactionCreate(client: RadioClient, interaction: Interaction) { if(!(interaction.isButton()) && !(interaction.isChatInputCommand()) && !(interaction.isStringSelectMenu())) return; - //@ts-ignore - const permissions = interaction.channel?.permissionsFor(interaction.client.user); - if (!permissions.has(PermissionFlagsBits.ViewChannel)) return; + if(interaction.channel?.type != ChannelType.DM){ + const permissions = interaction.channel?.permissionsFor(interaction.client.user); + if (!permissions?.has(PermissionFlagsBits.ViewChannel)) return; - if (!permissions.has(PermissionFlagsBits.EmbedLinks)) return interaction.reply({ - content: client.messages.emojis["error"] + client.messages.noPermsEmbed, - ephemeral: true - }); + if (!permissions?.has(PermissionFlagsBits.EmbedLinks)) return interaction.reply({ + content: client.messages.emojis["error"] + client.messages.noPermsEmbed, + ephemeral: true + }); + } if(interaction.isChatInputCommand()){ const commandName = interaction.commandName; diff --git a/src/client/funcs/check.ts b/src/client/funcs/check.ts index cafb5e5..63b6252 100644 --- a/src/client/funcs/check.ts +++ b/src/client/funcs/check.ts @@ -1,4 +1,4 @@ -import { ButtonInteraction, ChatInputCommandInteraction, StringSelectMenuInteraction } from "discord.js"; +import { ButtonInteraction, ChatInputCommandInteraction, GuildMember, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import { command } from "../commands"; @@ -21,8 +21,8 @@ export default function check(client: RadioClient, interaction: ButtonInteractio }); return false; } - //@ts-ignore - if (interaction.member.voice.channel !== radio.voiceChannel) { + + if (interaction.member instanceof GuildMember && interaction.member?.voice.channel !== radio.voiceChannel) { interaction.reply({ content: client.messages.emojis["error"] + client.messages.wrongVoiceChannel, ephemeral: true From c9229f3cdae06e3046ac21ee8c233deef0a20088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Thu, 8 Jun 2023 04:53:11 +0300 Subject: [PATCH 42/44] Dependencies Update --- package-lock.json | 2377 +-------------------------------------------- package.json | 2 +- 2 files changed, 23 insertions(+), 2356 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9180817..e1097b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "eximiabots-radiox", "version": "0.5.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -17,7 +17,6 @@ "discord.js": "^14.11.0", "dotenv": "^16.1.4", "libsodium-wrappers": "^0.7.11", - "node-fetch": "^3.3.1", "path": "^0.12.7" }, "devDependencies": { @@ -125,25 +124,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@discordjs/node-pre-gyp/node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/@discordjs/node-pre-gyp/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -467,9 +447,9 @@ } }, "node_modules/@sapphire/shapeshift": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.1.tgz", - "integrity": "sha512-zZb+VCDAoqxN+Kc1ICFaNvkLo6VaZPBxQPIPHcxHLIk7AEQWzkRjRYOSxPv9CQbvBR6CAO2EEB2jiAOiCDbyzA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.2.tgz", + "integrity": "sha512-YRbCXWy969oGIdqR/wha62eX8GNHsvyYi0Rfd4rNW6tSVVa8p0ELiMEuOH/k8rgtvRoM+EMV7Csqz77YdwiDpA==", "dependencies": { "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21" @@ -988,14 +968,6 @@ "node": ">= 8" } }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1424,28 +1396,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -1459,9 +1409,9 @@ } }, "node_modules/file-type": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.4.0.tgz", - "integrity": "sha512-o6MQrZKTAK6WpvmQk3jqTVUmqxYBxW5bloUfrdH1ZnRFDvvAPNr+l+rgOxM3nkqWT+3khaj3FRMDydWe0xhu+w==", + "version": "18.5.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.5.0.tgz", + "integrity": "sha512-yvpl5U868+V6PqXHMmsESpg6unQ5GfnPssl4dxdJudBrr9qy7Fddt7EVX1VLlddFfe8Gj9N7goCZH22FXuSQXQ==", "dependencies": { "readable-web-to-node-stream": "^3.0.2", "strtok3": "^7.0.0", @@ -1584,17 +1534,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/from": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", @@ -1648,9 +1587,9 @@ } }, "node_modules/glob": { - "version": "10.2.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz", - "integrity": "sha512-U/rnDpXJGF414QQQZv5uVsabTVxMSwzS5CH0p3DRCIV6ownl4f7PzGnkGmvlum2wB+9RlJWJZ6ACU1INnBqiPA==", + "version": "10.2.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.7.tgz", + "integrity": "sha512-jTKehsravOJo8IJxUGfZILnkvVJM/MOfHRs8QcXolVef2zNI9Tqyy5+SeuOAZd3upViEZQLyFpQhYiHLrMUNmA==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", @@ -2144,39 +2083,23 @@ "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", "dev": true }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, "node_modules/node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" + "whatwg-url": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "4.x || >=6.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/nopt": { @@ -3040,14 +2963,6 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, - "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "engines": { - "node": ">= 8" - } - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -3242,2253 +3157,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "dependencies": { - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - } - }, - "@discordjs/builders": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.6.3.tgz", - "integrity": "sha512-CTCh8NqED3iecTNuiz49mwSsrc2iQb4d0MjMdmS/8pb69Y4IlzJ/DIy/p5GFlgOrFbNO2WzMHkWKQSiJ3VNXaw==", - "requires": { - "@discordjs/formatters": "^0.3.1", - "@discordjs/util": "^0.3.1", - "@sapphire/shapeshift": "^3.8.2", - "discord-api-types": "^0.37.41", - "fast-deep-equal": "^3.1.3", - "ts-mixer": "^6.0.3", - "tslib": "^2.5.0" - } - }, - "@discordjs/collection": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.1.tgz", - "integrity": "sha512-aWEc9DCf3TMDe9iaJoOnO2+JVAjeRNuRxPZQA6GVvBf+Z3gqUuWYBy2NWh4+5CLYq5uoc3MOvUQ5H5m8CJBqOA==" - }, - "@discordjs/formatters": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.1.tgz", - "integrity": "sha512-M7X4IGiSeh4znwcRGcs+49B5tBkNDn4k5bmhxJDAUhRxRHTiFAOTVUNQ6yAKySu5jZTnCbSvTYHW3w0rAzV1MA==", - "requires": { - "discord-api-types": "^0.37.41" - } - }, - "@discordjs/node-pre-gyp": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/@discordjs/node-pre-gyp/-/node-pre-gyp-0.4.5.tgz", - "integrity": "sha512-YJOVVZ545x24mHzANfYoy0BJX5PDyeZlpiJjDkUBM/V/Ao7TFX9lcUvCN4nr0tbr5ubeaXxtEBILUrHtTphVeQ==", - "requires": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "@discordjs/opus": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@discordjs/opus/-/opus-0.9.0.tgz", - "integrity": "sha512-NEE76A96FtQ5YuoAVlOlB3ryMPrkXbUCTQICHGKb8ShtjXyubGicjRMouHtP1RpuDdm16cDa+oI3aAMo1zQRUQ==", - "requires": { - "@discordjs/node-pre-gyp": "^0.4.5", - "node-addon-api": "^5.0.0" - } - }, - "@discordjs/rest": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.7.1.tgz", - "integrity": "sha512-Ofa9UqT0U45G/eX86cURQnX7gzOJLG2oC28VhIk/G6IliYgQF7jFByBJEykPSHE4MxPhqCleYvmsrtfKh1nYmQ==", - "requires": { - "@discordjs/collection": "^1.5.1", - "@discordjs/util": "^0.3.0", - "@sapphire/async-queue": "^1.5.0", - "@sapphire/snowflake": "^3.4.2", - "discord-api-types": "^0.37.41", - "file-type": "^18.3.0", - "tslib": "^2.5.0", - "undici": "^5.22.0" - } - }, - "@discordjs/util": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.3.1.tgz", - "integrity": "sha512-HxXKYKg7vohx2/OupUN/4Sd02Ev3PBJ5q0gtjdcvXb0ErCva8jNHWfe/v5sU3UKjIB/uxOhc+TDOnhqffj9pRA==" - }, - "@discordjs/voice": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.16.0.tgz", - "integrity": "sha512-ToGCvHD1cBscuW3p+C7zOF5+L7MJmU4GjdOARfNk9mkHyFFZq4grK+Sxr3QXKbp27DtfDBc9uqD4GUOYgxngfA==", - "requires": { - "@types/ws": "^8.5.4", - "discord-api-types": "^0.37.37", - "prism-media": "^1.3.5", - "tslib": "^2.5.0", - "ws": "^8.13.0" - } - }, - "@discordjs/ws": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-0.8.3.tgz", - "integrity": "sha512-hcYtppanjHecbdNyCKQNH2I4RP9UrphDgmRgLYrATEQF1oo4sYSve7ZmGsBEXSzH72MO2tBPdWSThunbxUVk0g==", - "requires": { - "@discordjs/collection": "^1.5.1", - "@discordjs/rest": "^1.7.1", - "@discordjs/util": "^0.3.1", - "@sapphire/async-queue": "^1.5.0", - "@types/ws": "^8.5.4", - "@vladfrangu/async_event_emitter": "^2.2.1", - "discord-api-types": "^0.37.41", - "tslib": "^2.5.0", - "ws": "^8.13.0" - } - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.2", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@eslint/js": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", - "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true - }, - "@sapphire/async-queue": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", - "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==" - }, - "@sapphire/shapeshift": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.1.tgz", - "integrity": "sha512-zZb+VCDAoqxN+Kc1ICFaNvkLo6VaZPBxQPIPHcxHLIk7AEQWzkRjRYOSxPv9CQbvBR6CAO2EEB2jiAOiCDbyzA==", - "requires": { - "fast-deep-equal": "^3.1.3", - "lodash": "^4.17.21" - } - }, - "@sapphire/snowflake": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz", - "integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==" - }, - "@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true - }, - "@types/node": { - "version": "20.2.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", - "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==" - }, - "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, - "@types/ws": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", - "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", - "requires": { - "@types/node": "*" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz", - "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/type-utils": "5.59.9", - "@typescript-eslint/utils": "5.59.9", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", - "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz", - "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz", - "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.59.9", - "@typescript-eslint/utils": "5.59.9", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz", - "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz", - "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz", - "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz", - "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.9", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@vladfrangu/async_event_emitter": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.2.tgz", - "integrity": "sha512-HIzRG7sy88UZjBJamssEczH5q7t5+axva19UbZLO6u0ySbYPrwzWiXBcC0WuHyhKKoeCyneH+FvYzKQq/zTtkQ==" - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "requires": { - "streamsearch": "^1.1.0" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "discord-api-types": { - "version": "0.37.43", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.43.tgz", - "integrity": "sha512-bBhDWU3TF9KADxR/mHp1K4Bvu/LRtFQdGyBjADu4e66F3ZnD4kp12W/SJCttIaCcMXzPV3sfty6eDGRNRph51Q==" - }, - "discord.js": { - "version": "14.11.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.11.0.tgz", - "integrity": "sha512-CkueWYFQ28U38YPR8HgsBR/QT35oPpMbEsTNM30Fs8loBIhnA4s70AwQEoy6JvLcpWWJO7GY0y2BUzZmuBMepQ==", - "requires": { - "@discordjs/builders": "^1.6.3", - "@discordjs/collection": "^1.5.1", - "@discordjs/formatters": "^0.3.1", - "@discordjs/rest": "^1.7.1", - "@discordjs/util": "^0.3.1", - "@discordjs/ws": "^0.8.3", - "@sapphire/snowflake": "^3.4.2", - "@types/ws": "^8.5.4", - "discord-api-types": "^0.37.41", - "fast-deep-equal": "^3.1.3", - "lodash.snakecase": "^4.1.1", - "tslib": "^2.5.0", - "undici": "^5.22.0", - "ws": "^8.13.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dotenv": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.4.tgz", - "integrity": "sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==" - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", - "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.42.0", - "@humanwhocodes/config-array": "^0.11.10", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "dependencies": { - "eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "eslint-config-prettier": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", - "dev": true, - "requires": {} - }, - "eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "dev": true - }, - "espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", - "dev": true, - "requires": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "requires": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-type": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.4.0.tgz", - "integrity": "sha512-o6MQrZKTAK6WpvmQk3jqTVUmqxYBxW5bloUfrdH1ZnRFDvvAPNr+l+rgOxM3nkqWT+3khaj3FRMDydWe0xhu+w==", - "requires": { - "readable-web-to-node-stream": "^3.0.2", - "strtok3": "^7.0.0", - "token-types": "^5.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "signal-exit": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", - "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", - "dev": true - } - } - }, - "formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "requires": { - "fetch-blob": "^3.1.2" - } - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", - "dev": true - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - } - }, - "glob": { - "version": "10.2.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz", - "integrity": "sha512-U/rnDpXJGF414QQQZv5uVsabTVxMSwzS5CH0p3DRCIV6ownl4f7PzGnkGmvlum2wB+9RlJWJZ6ACU1INnBqiPA==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2", - "path-scurry": "^1.7.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "jackspeak": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", - "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "libsodium": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.11.tgz", - "integrity": "sha512-WPfJ7sS53I2s4iM58QxY3Inb83/6mjlYgcmZs7DJsvDlnmVUwNinBCi5vBT43P6bHRy01O4zsMU2CoVR6xJ40A==" - }, - "libsodium-wrappers": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.11.tgz", - "integrity": "sha512-SrcLtXj7BM19vUKtQuyQKiQCRJPgbpauzl3s0rSwD+60wtHqSUuqcoawlMDheCJga85nKOQwxNYQxf/CKAvs6Q==", - "requires": { - "libsodium": "^0.7.11" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" - }, - "lru-cache": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", - "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", - "dev": true - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minipass": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", - "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==", - "dev": true - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" - }, - "node-cleanup": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", - "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", - "dev": true - }, - "node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" - }, - "node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", - "requires": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - } - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "requires": { - "abbrev": "1" - } - }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "path": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", - "requires": { - "process": "^0.11.1", - "util": "^0.10.3" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-scurry": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", - "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", - "dev": true, - "requires": { - "lru-cache": "^9.1.1", - "minipass": "^5.0.0 || ^6.0.2" - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dev": true, - "requires": { - "through": "~2.3" - } - }, - "peek-readable": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", - "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "prism-media": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.5.tgz", - "integrity": "sha512-IQdl0Q01m4LrkN1EGIE9lphov5Hy7WWlH6ulf5QdGePLlPas9p2mhgddTEHrlaXYjjFToM1/rWuwF37VF4taaA==", - "requires": {} - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" - }, - "ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", - "dev": true, - "requires": { - "event-stream": "=3.3.4" - } - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "requires": { - "readable-stream": "^3.6.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", - "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", - "dev": true, - "requires": { - "glob": "^10.2.5" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", - "dev": true, - "requires": { - "through": "2" - } - }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", - "dev": true, - "requires": { - "duplexer": "~0.1.1" - } - }, - "streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "strtok3": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", - "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", - "requires": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "token-types": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", - "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", - "requires": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "ts-mixer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", - "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" - }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, - "tsc-watch": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-6.0.4.tgz", - "integrity": "sha512-cHvbvhjO86w2aGlaHgSCeQRl+Aqw6X6XN4sQMPZKF88GoP30O+oTuh5lRIJr5pgFWrRpF1AgXnJJ2DoFEIPHyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "node-cleanup": "^2.1.2", - "ps-tree": "^1.2.0", - "string-argv": "^0.3.1" - } - }, - "tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typescript": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", - "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", - "dev": true - }, - "undici": { - "version": "5.22.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", - "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", - "requires": { - "busboy": "^1.6.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "requires": {} - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } } } diff --git a/package.json b/package.json index 9a2f3e1..9d3209d 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,6 @@ }, "engines": { "node": ">=18.16.0", - "npm": ">=7.0.0" + "npm": ">=8.0.0" } } From 224a1f849d2515adb39b45bef073cb5bc62fd56d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Thu, 8 Jun 2023 04:54:13 +0300 Subject: [PATCH 43/44] Fix direct search in Stations class --- src/client/classes/Stations.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index 8979505..c8319af 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -22,7 +22,7 @@ export default class Stations extends Array { .then(this.checkFetchStatus) .then((response: Response) => response.json()); - for (const station of stations){ + for(const station of stations){ this.push(station); if(options.show) logger('Stations', station.name); } @@ -50,15 +50,8 @@ export default class Stations extends Array { if (this === null || !key || !type) return null; if(type == "direct"){ - let foundStation; - for(const station of this){ - if(station.name != key) return null; - foundStation = station; - } - - return foundStation; + return this.find(station => station.name === key); } else { - let foundStations : { station: string, name: string, probability: number }[] = []; if (key == "radio") return null; From 7cd00ed6450da48911f06cbc27b13828e7a8de06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Thu, 8 Jun 2023 05:27:28 +0300 Subject: [PATCH 44/44] Handling missing access to guilds in commands.ts --- src/client/commands.ts | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/client/commands.ts b/src/client/commands.ts index 87244c1..5874489 100644 --- a/src/client/commands.ts +++ b/src/client/commands.ts @@ -35,18 +35,22 @@ export default async function commands(client: RadioClient) { for(const command of commands){ let guilds = await client.guilds.fetch(); guilds.forEach(async (guild: { id: Snowflake; name: string; }) => { - if(!client.application) return; - client.application.commands.create({ - name: command.name, - description: command.description, - options: command.options || [] - }, guild.id); - client.funcs.logger('Application Commands', 'Guild: ' + guild.id + " (" + guild.name + ") \n" + 'Command: ' + command.name); + try { + if(!client.application) return; + await client.application.commands.create({ + name: command.name, + description: command.description, + options: command.options || [] + }, guild.id); + client.funcs.logger('Application Commands', 'Guild: ' + guild.id + " (" + guild.name + ") \n" + 'Command: ' + command.name); + } catch(DiscordAPIError) { + client.funcs.logger('Application Commands', 'Guild: ' + guild.id + " (" + guild.name + ") [FAILED] \n" + 'Command: ' + command.name); + } }); } } else { for(const command of commands){ - client.application.commands.create({ + await client.application.commands.create({ name: command.name, description: command.description, options: command.options || [] @@ -57,8 +61,11 @@ export default async function commands(client: RadioClient) { let guilds = await client.guilds.fetch(); guilds.forEach(async (guild: { id: Snowflake; }) => { - if(!client.application) return; - client.application.commands.set([], guild.id); + try { + if(!client.application) return; + await client.application.commands.set([], guild.id); + } catch (DiscordAPIError){ + } }); } client.funcs.logger('Application Commands', 'Successfully reloaded application (/) commands.' + "\n");