From 80f98e0d02faf8e4262e881d0354c0122cd12299 Mon Sep 17 00:00:00 2001 From: Bradford <2139924-aswang@users.noreply.gitlab.com> Date: Sun, 11 Jun 2023 23:27:07 +0100 Subject: [PATCH] major refactor to typescript --- .env.template | 2 +- bot/.eslintrc.json => .eslintrc.json | 0 .gitignore | 136 +- .vscode/launch.json | 22 + Dockerfile | 16 +- README.md | 27 +- bot/.gitignore | 132 - bot/bot-utils.js | 137 - bot/chain.js | 21 - bot/client.js | 55 - bot/commands/list_monitored_nodes.js | 153 - bot/commands/monitor_node.js | 82 - bot/commands/unmonitor_node.js | 51 - bot/db.js | 132 - bot/events/interactionCreate.js | 36 - bot/events/ready.js | 23 - bot/index.js | 23 - bot/messager.js | 19 - bot/package.json | 28 - bot/poller.js | 88 - bot/utils.js | 30 - ...only-compose.yml => mongo-only-compose.yml | 0 bot/package-lock.json => package-lock.json | 2521 +++++++++-------- package.json | 36 + {bot/res => res}/xx_logo_color.png | Bin {bot/res => res}/xx_logo_color.svg | 0 src/@types/discord.d.ts | 9 + src/bot-utils.ts | 169 ++ src/cmix/index.ts | 75 + src/cmix/types.ts | 27 + src/custom-derives/index.ts | 19 + src/custom-derives/staking/index.ts | 6 + src/custom-derives/staking/stakerRewards.ts | 333 +++ src/db/index.ts | 191 ++ src/db/types.ts | 41 + src/discord/commands/list_monitored_nodes.ts | 222 ++ src/discord/commands/monitor_node.ts | 107 + src/discord/commands/unmonitor_node.ts | 78 + src/discord/events/interactionCreate.ts | 40 + src/discord/events/ready.ts | 28 + src/discord/index.ts | 57 + src/discord/types.ts | 5 + src/index.ts | 34 + src/messager.ts | 23 + src/utils.ts | 40 + tsconfig.json | 104 + 46 files changed, 3134 insertions(+), 2244 deletions(-) rename bot/.eslintrc.json => .eslintrc.json (100%) create mode 100644 .vscode/launch.json delete mode 100644 bot/.gitignore delete mode 100644 bot/bot-utils.js delete mode 100644 bot/chain.js delete mode 100644 bot/client.js delete mode 100644 bot/commands/list_monitored_nodes.js delete mode 100644 bot/commands/monitor_node.js delete mode 100644 bot/commands/unmonitor_node.js delete mode 100644 bot/db.js delete mode 100644 bot/events/interactionCreate.js delete mode 100644 bot/events/ready.js delete mode 100644 bot/index.js delete mode 100644 bot/messager.js delete mode 100644 bot/package.json delete mode 100644 bot/poller.js delete mode 100644 bot/utils.js rename bot/mongo-only-compose.yml => mongo-only-compose.yml (100%) rename bot/package-lock.json => package-lock.json (53%) create mode 100644 package.json rename {bot/res => res}/xx_logo_color.png (100%) rename {bot/res => res}/xx_logo_color.svg (100%) create mode 100644 src/@types/discord.d.ts create mode 100755 src/bot-utils.ts create mode 100644 src/cmix/index.ts create mode 100644 src/cmix/types.ts create mode 100644 src/custom-derives/index.ts create mode 100644 src/custom-derives/staking/index.ts create mode 100644 src/custom-derives/staking/stakerRewards.ts create mode 100644 src/db/index.ts create mode 100644 src/db/types.ts create mode 100644 src/discord/commands/list_monitored_nodes.ts create mode 100644 src/discord/commands/monitor_node.ts create mode 100644 src/discord/commands/unmonitor_node.ts create mode 100644 src/discord/events/interactionCreate.ts create mode 100644 src/discord/events/ready.ts create mode 100644 src/discord/index.ts create mode 100644 src/discord/types.ts create mode 100644 src/index.ts create mode 100644 src/messager.ts create mode 100644 src/utils.ts create mode 100644 tsconfig.json diff --git a/.env.template b/.env.template index 7f5480c..911d99d 100644 --- a/.env.template +++ b/.env.template @@ -11,7 +11,7 @@ BOT_AVATAR=res/xx_logo_color.png # this is not updated on bot login # XX API variables ENDPOINT=https://dashboard-api.xx.network/v1/nodes -ENDPOINT_POLLING=60 # how often to pull the current node list +ENDPOINT_CRON=* * * * * # how often (in seconds) to pull the current node list (default is every minute) DASHBOARD_URL=https://dashboard.xx.network/nodes # used to build dashbord URIs # MongoDb variables diff --git a/bot/.eslintrc.json b/.eslintrc.json similarity index 100% rename from bot/.eslintrc.json rename to .eslintrc.json diff --git a/.gitignore b/.gitignore index 2eea525..93a9f1f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,135 @@ -.env \ No newline at end of file +built +*.crt + +# Boilerplate from https://github.com/github/gitignore/blob/main/Node.gitignore + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..6dbb4a5 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch index.ts", + "type": "node", + "request": "launch", + "runtimeArgs": [ + "-r", + "ts-node/register" + ], + "args": [ + "${workspaceFolder}/src/index.ts" + ], + "env": { + "TS_NODE_PROJECT": "${workspaceFolder}/tsconfig.json" + }, + "envFile": "${workspaceFolder}/.env" + } + ] +} + diff --git a/Dockerfile b/Dockerfile index 5c57644..a744900 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,13 +6,15 @@ WORKDIR /usr/src/app # Install app dependencies # A wildcard is used to ensure both package.json AND package-lock.json are copied # where available (npm@5+) -COPY bot/package*.json ./ - +COPY package*.json ./ +COPY tsconfig.json ./ RUN npm install -# If you are building your code for production -# RUN npm ci --only=production -# Bundle app source -COPY bot . +# Copy source code & resources +COPY src ./src +COPY res ./res + +# Build the project +RUN npm run build -CMD [ "node", "index.js" ] +CMD [ "npm", "run", "start" ] diff --git a/README.md b/README.md index fe0d24c..79dbd38 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +# Demo + +The latest version of this bot is accessible at the [engul.ph discord server](https://discord.gg/Y7jQEbv5za). + # Getting Started Clone this repo into your linux environment. @@ -65,7 +69,7 @@ Use the `bot-utils.js` script to deploy the bot commands to your dev server or g Run this command to view the script options: ``` -$ docker run --env-file .env -it xx_monitor_bot-bot node bot-utils.js +$ docker run --env-file .env -it xx_monitor_bot-bot node built/bot-utils.js ``` ### **Required:** Deploy commands to server or globally @@ -75,19 +79,19 @@ You may choose to deploy globally or to a specific server. Deploying globally al To deploy globally: ``` -$ docker run --env-file .env -it xx_monitor_bot-bot node bot-utils.js deploy --global +$ docker run --env-file .env -it xx_monitor_bot-bot node built/bot-utils.js deploy --global ``` To deploy to a server: ``` -$ docker run --env-file .env -it xx_monitor_bot-bot node bot-utils.js deploy +$ docker run --env-file .env -it xx_monitor_bot-bot node built/bot-utils.js deploy ``` To un-deploy: ``` -$ docker run --env-file .env -it xx_monitor_bot-bot node bot-utils.js deploy --reset +$ docker run --env-file .env -it xx_monitor_bot-bot node built/bot-utils.js deploy --reset ``` **To deploy changes you make to the `SlashCommandBuilder` object in your commands**: @@ -96,12 +100,12 @@ Just deploy as you originally did, either globally or to a server. ### Update username ``` -$ docker run --env-file .env -it xx_monitor_bot-bot node bot-utils.js username "xx monitor bot" +$ docker run --env-file .env -it xx_monitor_bot-bot node built/bot-utils.js username "xx monitor bot" ``` ### Update avatar ``` -$ docker run --env-file .env --volume :/image -it xx_monitor_bot-bot node bot-utils.js avatar /image +$ docker run --env-file .env --volume :/image -it xx_monitor_bot-bot node built/bot-utils.js avatar /image ``` ### Using `bot-utils.js` locally @@ -109,11 +113,9 @@ $ docker run --env-file .env --volume :/image -it xx_monitor_bot-bot Use the following commands to install the required packages and publish the slash commands to your server: ```bash -$ cd bot $ npm install -$ node bot-utils.js help +$ node built/bot-utils.js help $ [... command output ...] -$ cd .. ``` You can also set the bot username and status with the `BOT_USERNAME` and `BOT_STATUS` variables in `.env` and they will be set each time the bot starts. @@ -161,15 +163,14 @@ To run the bot outside docker for testing or development, first start up an ephe ```bash $ cd bot -$ docker compose -f mongo-only-compose.yml --env-file ../.env up +$ docker compose -f mongo-only-compose.yml --env-file .env up ``` From another terminal, run: ```bash -$ cd bot $ npm install # if it hasn't been run before -$ node index.js +$ npm run start ``` Now you can run the app without building a docker image for each test run. @@ -191,5 +192,5 @@ $ docker compose build ... $ docker compose up -d ... -$ docker run --env-file .env -it xx_monitor_bot-bot node bot-utils.js deploy --global # note! deploy how you originally deployed +$ docker run --env-file .env -it xx_monitor_bot-bot node built/bot-utils.js deploy --global # note! deploy how you originally deployed ``` \ No newline at end of file diff --git a/bot/.gitignore b/bot/.gitignore deleted file mode 100644 index d5e4e10..0000000 --- a/bot/.gitignore +++ /dev/null @@ -1,132 +0,0 @@ -# Boilerplate from https://github.com/github/gitignore/blob/main/Node.gitignore - -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* -.pnpm-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Snowpack dependency directory (https://snowpack.dev/) -web_modules/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional stylelint cache -.stylelintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variable files -.env -.env.development.local -.env.test.local -.env.production.local -.env.local - -# parcel-bundler cache (https://parceljs.org/) -.cache -.parcel-cache - -# Next.js build output -.next -out - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and not Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# vuepress v2.x temp and cache directory -.temp -.cache - -# Docusaurus cache and generated files -.docusaurus - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Stores VSCode versions used for testing VSCode extensions -.vscode-test - -# yarn v2 -.yarn/cache -.yarn/unplugged -.yarn/build-state.yml -.yarn/install-state.gz -.pnp.* diff --git a/bot/bot-utils.js b/bot/bot-utils.js deleted file mode 100644 index 582ab7a..0000000 --- a/bot/bot-utils.js +++ /dev/null @@ -1,137 +0,0 @@ -// Script from https://discordjs.guide/creating-your-bot/command-deployment.html#command-registration, modified - -// manually expand the environmental variables -var dotenv = require('dotenv').config({ path: '../.env' }); -var dotenvExpand = require('dotenv-expand'); -dotenvExpand.expand(dotenv); - - -// Discord token & application id are required. -if (!process.env.DISCORD_TOKEN) { - throw new Error("DISCORD_TOKEN environment variable missing."); -} -if (!process.env.APP_ID) { - throw new Error("APP_ID environment variable missing."); -} -const clientId = process.env.APP_ID; -const token = process.env.DISCORD_TOKEN; - - -// client commands -async function init_client() { - const { Client, GatewayIntentBits, Events } = require('discord.js'); - const client = new Client({ intents: [GatewayIntentBits.Guilds] }); - client.once(Events.ClientReady, (...args) => { - console.log(`Ready! Logged in as ${client.user.tag}`); - }); - - await client.login(process.env.DISCORD_TOKEN); - return client; -} - - -// deploy commands -async function deploy(guildId=null) { - const { REST, Routes } = require('discord.js'); - const fs = require('node:fs'); - const rest = new REST({ version: '10' }).setToken(token); - - const commands = []; - // Grab all the command files from the commands directory - const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); - - // Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment - for (const file of commandFiles) { - const command = require(`./commands/${file}`); - commands.push(command.data.toJSON()); - } - - console.log(`Prepared ${commands.length} application (/) commands for deployment.`); - - (async () => { - try { - // Deploying commands - const route = guildId ? Routes.applicationGuildCommands(clientId, guildId) : Routes.applicationCommands(clientId); - const data = await rest.put( - route, - { body: commands }, - ); - - console.log(`Successfully reloaded ${data.length} application (/) commands.`); - } catch (error) { - // And of course, make sure you catch and log any errors! - console.error(error); - } - })(); -} - - -// command parsing -(async function(){ - const { Command, Option, Argument } = require('commander'); - const program = new Command(); - - program - .name('bot-utils') - .description('Utilities to deploy the xx monitor bot to discord servers'); - - program - .command('deploy') - .description('Deploy commands to server(s)') - .addOption(new Option('--server ', 'Deploy to the given server id').default(process.env.DEV_GUILD_ID, 'env DEV_GUILD_ID')) - .addOption(new Option('--global', 'Deploy to all bot-joined servers - this will duplicate guild-issued commands! see https://stackoverflow.com/a/70167704/1486966').conflicts(['server', 'reset'])) - .addOption(new Option('--reset', 'Resets the global and guild commands if you have deployed to both')) - .action( async (options) => { - if (options.reset) - { - // reset the commands in server and globally; see https://stackoverflow.com/a/70167704/1486966 - console.log('Resetting commands...'); - const client = await init_client(); - console.log('Resetting commands globally (may take ~1 hour to update)...'); - client.application.commands.set([]); - console.log(`Resetting commands in server # ${process.env.DEV_GUILD_ID} (takes effect immediately)...`); - const guild = client.guilds.cache.get(process.env.DEV_GUILD_ID); - guild.commands.set([]); - client.destroy(); - } - else if (options.global) - { - // deploy commands globally - console.log('Deploying commands globally'); - await deploy(); - } - else - { - // deploy commands to a single server - console.log(`Deploying commands to server id ${options.server}`) - await deploy(options.server); - } - console.log("Complete"); - }); - - program - .command('username') - .description('Set bot username (rate limited to 2x/hour)') - .addArgument(new Argument('')) - .action( async (username) => { - console.log(`Setting username to ${username}`); - const client = await init_client(); - const result = await client.user.setUsername(username); - console.log("Complete"); - client.destroy(); - }); - - program - .command('avatar') - .description('Set bot avatar') - .addArgument(new Argument('')) - .action( async (path) => { - console.log(`Setting avatar to ${path}`); - const client = await init_client(); - await client.user.setAvatar(path); - console.log("Complete"); - client.destroy(); - }); - - program.parse(); -})(); diff --git a/bot/chain.js b/bot/chain.js deleted file mode 100644 index 918e0c6..0000000 --- a/bot/chain.js +++ /dev/null @@ -1,21 +0,0 @@ -const { ApiPromise, WsProvider } = require('@polkadot/api'); -const wsProvider = new WsProvider('wss://192.168.0.179:443'); -const api = await ApiPromise.create({ provider: wsProvider }); - -async function main () { - const wsProvider = new WsProvider('wss://192.168.0.180:63007'); - const api = await ApiPromise.create({ provider: wsProvider }); - - let count = 0; - - const unsubscribe = await api.rpc.chain.subscribeNewHeads((header) => { - console.log(`Chain is at block: #${header.number}`); - - if (++count === 256) { - unsubscribe(); - process.exit(0); - } - }); -} - -main().catch(console.error); \ No newline at end of file diff --git a/bot/client.js b/bot/client.js deleted file mode 100644 index 596fd53..0000000 --- a/bot/client.js +++ /dev/null @@ -1,55 +0,0 @@ -const fs = require('node:fs'); -const path = require('node:path'); -const { Client, Collection, GatewayIntentBits } = require('discord.js'); - - -// Discord token is required. -if (!process.env.DISCORD_TOKEN) { - throw new Error("DISCORD_TOKEN environment variable missing."); -} - - -async function client_init() { - // Create a new client instance - const client = new Client({ intents: [GatewayIntentBits.Guilds] }); - - - // Commands initialization - from https://discordjs.guide/creating-your-bot/command-handling.html#loading-command-files - client.commands = new Collection(); - - const commandsPath = path.join(__dirname, 'commands'); - const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); - - // Build collection of available commands from the commands directory - for (const file of commandFiles) { - const filePath = path.join(commandsPath, file); - const command = require(filePath); - // Set a new item in the Collection with the key as the command name and the value as the exported module - if ('data' in command && 'execute' in command) { - client.commands.set(command.data.name, command); - } else { - console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); - } - } - - - // Events initialization - from https://discordjs.guide/creating-your-bot/event-handling.html#individual-event-files - const eventsPath = path.join(__dirname, 'events'); - const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js')); - - for (const file of eventFiles) { - const filePath = path.join(eventsPath, file); - const event = require(filePath); - if (event.once) { - client.once(event.name, (...args) => event.execute(...args)); - } else { - client.on(event.name, (...args) => event.execute(...args)); - } - } - - - // Log in to Discord with your client's token - client.login(process.env.DISCORD_TOKEN); -} - -client_init(); \ No newline at end of file diff --git a/bot/commands/list_monitored_nodes.js b/bot/commands/list_monitored_nodes.js deleted file mode 100644 index fe56f9f..0000000 --- a/bot/commands/list_monitored_nodes.js +++ /dev/null @@ -1,153 +0,0 @@ -const { SlashCommandBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, MessageFlags } = require('discord.js'); -const moment = require('moment'); -const base64url = require('base64url'); -const { prettify_node, icons } = require('../utils.js') - - -function build_response_buttons(db, nodes, unmonitor_buttons = true) { - var rows = []; - const MAX_BUTTON_TEXT_LEN = 80; // 80 is value from exception thrown when string is too long - - nodes.forEach( (node) => { - const row = new ActionRowBuilder(); // let's build on this puppy - - // node status - disabled (just used to show node id) - const button_style = node.status === db.status.UNKNOWN ? ButtonStyle.Secondary : (node.status === db.status.ONLINE ? ButtonStyle.Success : ButtonStyle.Danger ); - row.addComponents( - new ButtonBuilder() - .setCustomId(`${node.node}-status`) - .setDisabled(true) - .setLabel(db.sutats[node.status]) - .setStyle(button_style), - ); - - // node id button - disabled - row.addComponents( - new ButtonBuilder() - .setCustomId(`${node.node}-text`) - .setDisabled(true) - .setLabel(prettify_node(node.name, node.node, false, MAX_BUTTON_TEXT_LEN)) - .setStyle(ButtonStyle.Primary), - ); - - // unmonitor button - if (unmonitor_buttons) { - row.addComponents( - new ButtonBuilder() - .setCustomId(node.node) - .setLabel('Unmonitor') - .setStyle(ButtonStyle.Danger), - ); - } - - // dashboard link - const url = `${process.env.DASHBOARD_URL}/${base64url.fromBase64(node.node)}` - row.addComponents( - new ButtonBuilder() - .setURL(url) - .setLabel('Dashboard') - .setStyle(ButtonStyle.Link), - ); - - rows.push(row); - }); - - return rows -} - -function build_response_text(db, nodes) { - var reply_string = '' - - // Print a list of nodes - nodes.forEach((node) => { - const url = `${process.env.DASHBOARD_URL}/${base64url.fromBase64(node.node)}` - const changed = node.changed ? ` since ${moment(node.changed).fromNow()}`: '' - - - var line = db.status_icon[db.sutats[node.status]] // node status icon - line += ` ${prettify_node(node.name, node.node)}` // node name & id - line += ` _(${db.sutats[node.status]}${changed})_` // status text & time since change - line += ` [${icons.LINK}](${url})`; // link to dashboard page for node - - reply_string += line + '\n'; - }); - - return reply_string; -} - -async function build_response(db, user_id, fancy = true, unmonitor_buttons = true) { - - // Get a list of user's monitored nodes - const nodes = await db.list_user_nodes(user_id) - - // User isn't monitoring any nodes - if (nodes.length <= 0) { - return {text: `${icons.ERROR} You aren't monitoring any nodes.`, components: []} - } - - const reply_string = `You are monitoring ${nodes.length} node${nodes.length > 1? 's': ''}:\n`; - - - // User is monitoring 1-5 nodes AND the fancy flag is set - show buttons - if (nodes.length > 0 && nodes.length <= 5 && fancy) { - return {text: reply_string, components: build_response_buttons(db, nodes, unmonitor_buttons)}; - } - // Build a codeblock if we have results > 5 or fancy flag is unset - else { - return {text: `${reply_string}${build_response_text(db, nodes)}`, components: []}; - } -} - -module.exports = { - data: new SlashCommandBuilder() - .setName('list_monitored_nodes') - .setDescription('Display a list of validators that you are monitoring') - .addStringOption(option => - option.setName('format') - .setDescription('Choose the format of the validator list. Default is Text.') - .addChoices( - { name: 'Text', value: 'text' }, - { name: 'Buttons', value: 'buttons' }, - )), - async execute(interaction, db) { - const user = interaction.user; - const format = interaction.options.getString('format'); - const fancy = (format == 'buttons') ? true : false; - const channel = interaction.channel ? interaction.channel : await interaction.client.channels.fetch(interaction.channelId); - const eph = !channel.isDMBased() ? true : false; // make the message ephemeral / visible only to user if not in dm - - var { text, components } = await build_response(db, user.id, fancy); // build fancy list (if plain not set by user) - await interaction.reply({ content: text, components: components, ephemeral: eph, flags: MessageFlags.SuppressEmbeds }); - - // if we have button components, make sure we have the right callback - if (components.length) { - - // button event handling - https://discordjs.guide/interactions/buttons.html#updating-the-button-message - - const filter = i => i.user.id === user.id; - const collector = channel.createMessageComponentCollector({ filter, time: 45000, dispose: true }); - - collector.on('collect', async i => { - - // if button was clicked, delete it from user and update message - const result = await db.delete_node(user.id, i.customId) - if (result.deletedCount) { - const deleted = result.deleted[0]; - // Deleted node successfully - var reply_string = `${icons.DELETE} You are no longer monitoring ${prettify_node(deleted.name, i.customId)}.` - var { text, components } = await build_response(db, user.id); - await i.update({ content: text, components: components }); - await interaction.followUp({ content: reply_string, ephemeral: eph }); - } - }); - - collector.on('end', async () => { - // Disable the unmonitor buttons because we're done listening for them - var { text, components } = await build_response(db, user.id, true, false); - await interaction.editReply({ content: text, components: components }); - }); - } - - console.log(`User ${user.id} interaction from ${eph ? 'channel' : 'dm' }: listed nodes`); - }, -}; diff --git a/bot/commands/monitor_node.js b/bot/commands/monitor_node.js deleted file mode 100644 index 8ce2441..0000000 --- a/bot/commands/monitor_node.js +++ /dev/null @@ -1,82 +0,0 @@ -const { SlashCommandBuilder, DiscordAPIError } = require('discord.js'); -const { UpdateResult } = require('mongodb'); -const { prettify_node, icons } = require('../utils.js') - - -module.exports = { - data: new SlashCommandBuilder() - .setName('monitor_node') - .setDescription('Register a new validator node to monitor') - .addStringOption(option => - option.setName('id') - .setDescription('The Node ID to monitor') - .setRequired(true) - .setMaxLength(44) - .setMinLength(44) - .setAutocomplete(true)) - .addStringOption(option => - option.setName('name') - .setDescription('A friendly name for the node')), - async execute(interaction, db) { - const node_id = interaction.options.getString('id'); - const node_name = interaction.options.getString('name'); - const user = interaction.user; - const channel = interaction.channel; - const eph = !channel.isDMBased() ? true : false; // make the message ephemeral / visible only to user if not in dm - var reply_string = `` - - const status = await db.add_node(user.id, node_id, node_name); // returns false if the user is already monitoring this node/name combination - - if (status) { - // Successfully added or updated node - - if ('modifiedCount' in status) { - // result was a record update - reply_string = `${icons.SUCCESS} Updated \`${node_id}\` name to \`${node_name}\`.` - } else { - // result was a new record - const monitoring = `${icons.WATCH} Monitoring ${prettify_node(node_name, node_id)}. Reporting changes ` - - try { - // if this interaction is from a channel, verify their dms are open by sending one - if (eph) { - await user.send(monitoring + 'here.'); - } - } catch (err) { // when the bot can't send a dm, an exception is thrown - if (err instanceof DiscordAPIError) { - console.log(err); - - // delete the db entry - await db.delete_node(user.id, node_id) - - reply_string = `${icons.ERROR} Error: I cannot send you a Direct Message. Please resolve that and try again.`; - - } else - throw err; // this is some other kind of error, pass it on - } - - reply_string = monitoring + (eph ? 'in your DMs.' : 'here'); - } - - } else { - // User is already monitoring this node - reply_string = `${icons.ERROR} Error: You are already monitoring ${prettify_node(node_name, node_id)}.` - } - - await interaction.reply({ content: reply_string, ephemeral: eph }); - console.log(`User ${user.id} interaction from ${eph ? 'channel' : 'dm' }: monitor ${node_id}: ${reply_string}`) - }, - async autocomplete(interaction, db) { - const user = interaction.user; - const focusedValue = interaction.options.getFocused(); - - // Get list of nodes monitored from db - const monitored_nodes = await db.list_user_nodes(user.id) - const choices = monitored_nodes.map( entry => ({id: entry.node, text: `${prettify_node(entry.name, entry.node, false)}`})); - const filtered = choices.filter(choice => choice.text.toLowerCase().includes(focusedValue.toLowerCase())); - - await interaction.respond( - filtered.map(choice => ({ name: choice.id, value: choice.id })), // setting name: choice.text should work, but it doesn't. Asked on SO: https://stackoverflow.com/q/74532512/1486966 - ); - }, -}; diff --git a/bot/commands/unmonitor_node.js b/bot/commands/unmonitor_node.js deleted file mode 100644 index c276821..0000000 --- a/bot/commands/unmonitor_node.js +++ /dev/null @@ -1,51 +0,0 @@ -const { SlashCommandBuilder } = require('discord.js'); -const { prettify_node, icons } = require('../utils.js') - -const ID_LEN = 44; - -module.exports = { - data: new SlashCommandBuilder() - .setName('unmonitor_node') - .setDescription('Stop monitoring a validator') - .addStringOption(option => - option.setName('id') - .setDescription('The Node ID to stop monitoring') - .setRequired(true) - .setMaxLength(ID_LEN) - .setMinLength(ID_LEN) - .setAutocomplete(true)), - async execute(interaction, db) { - const node_id = interaction.options.getString('id'); - const user = interaction.user; - const channel = interaction.channel; - const eph = !channel.isDMBased() ? true : false; // make the message ephemeral / visible only to user if not in dm - var reply_string = '' - - // Get list of users subscriptions - const result = await db.delete_node(user.id, node_id) - if (result.deletedCount) { - const deleted = result.deleted[0]; - // Deleted node successfully - reply_string = `${icons.DELETE} You are no longer monitoring ${prettify_node(deleted.name, node_id)}.` - } else { - // Node wasn't monitored - reply_string = `${icons.ERROR} Error: You are not monitoring ${prettify_node(null, node_id)}.` - } - - await interaction.reply({ content: reply_string, ephemeral: eph }); - console.log(`User ${user.id} interaction from ${eph ? 'channel' : 'dm' }: unmonitor ${node_id}: ${reply_string}`); - }, - async autocomplete(interaction, db) { - const user = interaction.user; - const focusedValue = interaction.options.getFocused(); - - // Get list of nodes monitored from db - const monitored_nodes = await db.list_user_nodes(user.id) - const choices = monitored_nodes.map( entry => ({id: entry.node, text: `${prettify_node(entry.name, entry.node, false, ID_LEN)}`})); - const filtered = choices.filter(choice => choice.text.toLowerCase().includes(focusedValue.toLowerCase())); - - await interaction.respond( - filtered.map(choice => ({ name: choice.id, value: choice.id })), // setting name: choice.text should work, but it doesn't. Asked on SO: https://stackoverflow.com/q/74532512/1486966 - ); - }, -}; diff --git a/bot/db.js b/bot/db.js deleted file mode 100644 index 76d478d..0000000 --- a/bot/db.js +++ /dev/null @@ -1,132 +0,0 @@ -const { MongoClient } = require('mongodb'); - -// Initialize mongodb -console.log(`Connecting to mongo at ${process.env.MONGO_URI}`) -const client = new MongoClient(process.env.MONGO_URI); -const db = client.db('xx'); -const mainnet = db.collection('mainnet'); -const stats = client.db('stats'); -const actions = stats.collection('actions'); - -// Record formats: -// xx monitor record - one row for each node monitored -// { user: discord_id, -// node: node_id, -// name: node_name, -// user_set_name: bool - true if user set the name, false otherwise -// status: string - based on status object below, -// changed: timestamp of last state change, -// } -// -// user action record - one row for each user action taken -// { user: discord_id, -// time: timestamp, -// action: usually the command name, -// data: data for action -// } - - -const status = Object.freeze({ - ONLINE: 'online', - OFFLINE: 'offline', - ERROR: 'error', - UNELECTED: 'unelected', - UNKNOWN: null -}); -const sutats = Object.freeze(Object.entries(status).reduce((acc, [key, value]) => (acc[value] = key, acc), {})) // reverse of status - get state by string -const status_icon = Object.freeze({ - ONLINE: '🟢', - OFFLINE: '🔴', - ERROR: '⛔', - UNELECTED: '⬇️', - UNKNOWN: '❓' -}); -const status_xx = Object.freeze({ - 'online': status.ONLINE, - 'offline': status.OFFLINE, - 'error': status.ERROR, - 'not currently a validator': status.UNELECTED, - '': status.UNKNOWN -}); - - -async function log_action(user_id, action, data) { - // Add a record for an action taken by a user - - const new_doc = {user: user_id, time: new Date(), action: action, data: data} - const options = {}; - const result = await actions.insertOne(new_doc); - return result; -} - - -async function add_node(user_id, node_id, node_name=null) { - // Add a node to the monitered node list - - // check if user is already monitoring this node - const query = {user: user_id, node: node_id}; - const options = {}; - const result = await mainnet.findOne(query, options); - if (result) { - // User is already monitoring this node - // check if node name is set and the same - if (node_name && node_name !== result.name) { - // update node name - const update = { $set: {name: node_name, user_set_name: true}} - return await mainnet.updateOne(query, update); - } - return false; - } else { - const new_doc = {user: user_id, node: node_id, name: node_name, user_set_name: Boolean(node_name), status: status.UNKNOWN, changed: null} - const result = await mainnet.insertOne(new_doc); - return result; - } -}; - -async function update_node_status(node_id, status, changed) { - // notify any users monitoring the provided node of a status change - - const query = {node: node_id, status: {$ne : status}}; - const options = { projection: { _id: false }}; - const result = await mainnet.find(query, options).toArray(); - - if (result.length) { - // update the value in the database - const update = { $set: {status: status, changed: changed}} - mainnet.updateMany(query, update); - - return result; - } -} - -async function update_node_name(node_id, new_name){ - // update all nodes with the new name, where user_set_name = false - - const query = {node: node_id, user_set_name: {$ne: true}}; - const update = { $set: {name: new_name, user_set_name: false}}; - mainnet.updateMany(query, update); - -} - -async function list_user_nodes(user_id) { - // Get list of user's subscriptions - - const query = {user: user_id}; - const options = { projection: { _id: false }}; - const result = await mainnet.find(query, options).toArray(); - return result; -} - -async function delete_node(user_id, node_id) { - // Delete the given node from the user record. - - const query = {user: user_id, node: node_id}; - const options = {}; - const deleted = await mainnet.find(query, options).toArray(); - var result = await mainnet.deleteMany(query, options); - result.deleted = deleted - return result; -} - - -module.exports = { log_action, add_node, update_node_status, update_node_name, list_user_nodes, delete_node, status, sutats, status_icon, status_xx } \ No newline at end of file diff --git a/bot/events/interactionCreate.js b/bot/events/interactionCreate.js deleted file mode 100644 index bbc6902..0000000 --- a/bot/events/interactionCreate.js +++ /dev/null @@ -1,36 +0,0 @@ -const { Events } = require('discord.js'); -const db = require('../db.js') - -module.exports = { - name: Events.InteractionCreate, - async execute(interaction) { - - const command = interaction.client.commands.get(interaction.commandName); - - if (!command) { - console.error(`No command matching ${interaction.commandName} was found.`); - return; - } - - try { - - // fetch the channel if it isn't cached (dms are not usually cached) - if (!interaction.channel) { - await interaction.client.channels.fetch(interaction.channelId); - } - - if (interaction.isChatInputCommand()) { - // log action in db - const user_id = interaction.user.id; - await db.log_action(user_id, interaction.commandName, interaction.options.data); - await command.execute(interaction, db); - } - else if (interaction.isAutocomplete()) { - await command.autocomplete(interaction, db); - } - } catch (error) { - console.error(`Error executing ${interaction.commandName}`); - console.error(error); - } - }, -}; diff --git a/bot/events/ready.js b/bot/events/ready.js deleted file mode 100644 index 4ec68a6..0000000 --- a/bot/events/ready.js +++ /dev/null @@ -1,23 +0,0 @@ -const { Events, ActivityType } = require('discord.js'); - -module.exports = { - name: Events.ClientReady, - once: true, - execute(client) { - console.log(`Ready! Logged in as ${client.user.tag}`); - - // configure client with info from env - // Set bot username - if (process.env.BOT_USERNAME) { - client.user.setUsername(process.env.BOT_USERNAME); - } - - // Set bot status - if (process.env.BOT_STATUS) { - client.user.setActivity(process.env.BOT_STATUS, { type: ActivityType.Listening }); - } - - // start poller now that client is ready - require('../poller.js')(client) - }, -}; diff --git a/bot/index.js b/bot/index.js deleted file mode 100644 index a82d026..0000000 --- a/bot/index.js +++ /dev/null @@ -1,23 +0,0 @@ -var env = process.env.NODE_ENV || 'development'; - -// If in development, load & expand variables manually -if (env === 'development') { - var dotenv = require('dotenv').config({ path: '../.env' }); - var dotenvExpand = require('dotenv-expand'); - dotenvExpand.expand(dotenv); - - // set mongodb uri to localhost - process.env.MONGO_URI = `mongodb://${process.env.MONGO_INITDB_ROOT_USERNAME}:${process.env.MONGO_INITDB_ROOT_PASSWORD}@localhost:${process.env.MONGO_PORT}/` -} - - -// start discord.js -require('./client.js') -const db = require('./db.js'); - -// client.js: loads all the event handlers for discord -// once discord.js client is ready, magic starts in events/ready.js -// -// events/ready.js: fires off the poller that downloads the current nodes list, -// compares it to the database of monitored nodes, and sends dms when -// node status changes have happened. \ No newline at end of file diff --git a/bot/messager.js b/bot/messager.js deleted file mode 100644 index 47b6f8e..0000000 --- a/bot/messager.js +++ /dev/null @@ -1,19 +0,0 @@ -const base64url = require('base64url'); -const db = require('./db.js') -const { prettify_node, icons } = require('./utils.js') - -async function send_dm(client, user_id, message) { - client.users.fetch(user_id).then( dm => { - dm.send(message); - }) -} - -async function dm_status_change(client, node, status_new){ - var message = db.status_icon[db.sutats[node.status]] + ` ${icons.TRANSIT} ` + db.status_icon[db.sutats[status_new]]; // old -> new status icon - message += ` ${prettify_node(node.name, node.node)} ` // pretty node name - message += `is now ${status_new == db.status.ERROR ? 'in ' : ''}${db.sutats[status_new]}`; // new status - - send_dm(client, node.user, message) -} - -module.exports = { send_dm, dm_status_change } \ No newline at end of file diff --git a/bot/package.json b/bot/package.json deleted file mode 100644 index fe7c2db..0000000 --- a/bot/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "discord-xx-validator-status-bot", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "start": "node index.js", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "@polkadot/api": "^9.10.5", - "@xxnetwork/types": "^1.0.4", - "async": "^3.2.4", - "base64url": "^3.0.1", - "commander": "^9.4.1", - "discord.js": "^14.6.0", - "moment": "^2.29.4", - "mongodb": "^4.11.0", - "request": "^2.88.2" - }, - "devDependencies": { - "dotenv": "^16.0.3", - "dotenv-expand": "^9.0.0" - } -} diff --git a/bot/poller.js b/bot/poller.js deleted file mode 100644 index 639302c..0000000 --- a/bot/poller.js +++ /dev/null @@ -1,88 +0,0 @@ -// Polls the dashboard API and gets the entire list of nodes every ENDPOINT_POLLING seconds -let request = require('request'); -const async = require('async'); -const db = require('./db.js'); -const { dm_status_change } = require('./messager.js'); - -const endpoint = process.env.ENDPOINT; -const endpoint_retries = process.env.ENDPOINT_RETRIES; -const endpoint_polling = process.env.ENDPOINT_POLLING * 1000; - -request = request.defaults({ - endpoint, - headers: { - 'accept': 'application/json; charset=utf-8' - } -}); - -console.log("*** API Polling Started ***") - -module.exports = function(client) { - - async.forever( // https://caolan.github.io/async/v3/docs.html#forever - function(next) { - poll(next); - }, - function(err) { - if (err) { - console.log(err); - } else { - console.log("*** API Polling Stopped ***"); - } - } - ) - - function poll(next) { - const start_time = new Date() - request({ - method: 'GET', - uri: endpoint - }, async function (error, response, body) { - if (error) { - return whilstCallback(error) - } else if (response.statusCode !== 200) { - return whilstCallback(`non-200 response:\nresponse: ${response}\nbody: ${body}`) - } else { - // Process the results - const json_body = JSON.parse(body) - parse_nodes(json_body.nodes) - - // wait for the rest of the polling interval - const time_to_wait = endpoint_polling - (new Date() - start_time) - console.log(`downloaded node data: ${json_body.nodes.length} nodes (${body.length} bytes), waiting ${time_to_wait/1000}s until next poll`) - await new Promise(resolve => setTimeout(resolve, time_to_wait)); - next() - } - }); - } - - async function parse_nodes(nodes) { - // take a list of nodes from the API and notify on changes - - // step through each node result and send its status to the monitoring db - nodes.forEach( async (xx_node) => { - - var new_name = xx_node.name - var status_new = db.status_xx[xx_node.status] - var node_id = xx_node.id - var changed = new Date(); - - // update database with new name, as appropriate - if (xx_node.name) { - db.update_node_name(node_id, new_name); - } - - // update database with new status - var result = await db.update_node_status(xx_node.id, status_new, changed) - - // notify users of status change - if (result) { - console.log(`notifying ${result.length} users of node ${node_id} status change to ${status_new} at ${changed}`) - result.forEach( async (entry) => { - // Send a notification to the user - dm_status_change(client, entry, status_new); - }); - } - }); - } -} diff --git a/bot/utils.js b/bot/utils.js deleted file mode 100644 index 78fb4ba..0000000 --- a/bot/utils.js +++ /dev/null @@ -1,30 +0,0 @@ -const { inlineCode } = require('discord.js'); - -// truncate a string to set length, using ellipsis in the center -function truncate(s, length=44) { - length = length < 5? 5 : length; // should not truncate anything shorter than 5 characters - const trunc = s.length > length ? `${s.substring(0, Math.ceil(length/2) - 1)}…${s.substring(s.length - Math.floor(length/2))}` : s; - return trunc -} - -// take a pretty name and an id and combine; if no name provided, just return id -function prettify_node(name, id, codify = true, maxlen = 44) { - if (!name) return codify ? inlineCode(id) : id; // just return id if no name is given - const MAX_LEN = maxlen - 3; // arbitrary, can be increased - const MAX_NAME_LEN = Math.ceil(MAX_LEN / 2); // name shouldn't be much longer than half the max length - const name_new = truncate(name, MAX_NAME_LEN); - const MAX_ID_LEN = MAX_LEN - name_new.length; // id takes up the rest of the space - const pretty = `${name_new} / ${truncate(id, MAX_ID_LEN)}`; - return codify? inlineCode(pretty) : pretty; -} - -const icons = Object.freeze({ - WATCH: '👀', - ERROR: '💢', - SUCCESS: '🙌', - DELETE: '🗑️', - TRANSIT: '➜', - LINK: '🔗' -}); - -module.exports = { prettify_node, icons }; \ No newline at end of file diff --git a/bot/mongo-only-compose.yml b/mongo-only-compose.yml similarity index 100% rename from bot/mongo-only-compose.yml rename to mongo-only-compose.yml diff --git a/bot/package-lock.json b/package-lock.json similarity index 53% rename from bot/package-lock.json rename to package-lock.json index 97941f4..4a5ed78 100644 --- a/bot/package-lock.json +++ b/package-lock.json @@ -1,33 +1,55 @@ { - "name": "discord-xx-validator-status-bot", - "version": "1.0.0", + "name": "discord-xx-monitor-bot", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "discord-xx-validator-status-bot", - "version": "1.0.0", + "name": "discord-xx-monitor-bot", + "version": "2.0.0", "license": "ISC", "dependencies": { - "@polkadot/api": "^9.10.5", - "@xxnetwork/types": "^1.0.4", - "async": "^3.2.4", + "@commander-js/extra-typings": "^11.0.0", + "@polkadot/api": "^9.14.2", "base64url": "^3.0.1", - "commander": "^9.4.1", - "discord.js": "^14.6.0", + "cron": "^2.3.1", + "discord.js": "^14.11.0", "moment": "^2.29.4", - "mongodb": "^4.11.0", - "request": "^2.88.2" + "mongodb": "^4.11.0" }, "devDependencies": { + "@polkadot/types": "^9.14.2", + "@types/cron": "^2.0.1", + "@types/node": "^20.3.1", + "@xxnetwork/types": "^1.0.4", "dotenv": "^16.0.3", - "dotenv-expand": "^9.0.0" + "dotenv-expand": "^9.0.0", + "env-cmd": "^10.1.0", + "ts-node": "^10.9.1", + "typescript": "^5.1.3" + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "optional": true, + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" } }, + "node_modules/@aws-crypto/crc32/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "optional": true + }, "node_modules/@aws-crypto/ie11-detection": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-2.0.2.tgz", - "integrity": "sha512-5XDMQY98gMAf/WRTic5G++jfmS/VLM0rwpiOpaainKi4L0nqWMSB1SzsrEG5rjFZGYN6ZAefO+/Yta2dFM0kMw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", "optional": true, "dependencies": { "tslib": "^1.11.1" @@ -40,16 +62,16 @@ "optional": true }, "node_modules/@aws-crypto/sha256-browser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-2.0.0.tgz", - "integrity": "sha512-rYXOQ8BFOaqMEHJrLHul/25ckWH6GTJtdLSajhlqGMx0PmSueAuvboCuZCTqEKlxR8CQOwRarxYMZZSYlhRA1A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", "optional": true, "dependencies": { - "@aws-crypto/ie11-detection": "^2.0.0", - "@aws-crypto/sha256-js": "^2.0.0", - "@aws-crypto/supports-web-crypto": "^2.0.0", - "@aws-crypto/util": "^2.0.0", - "@aws-sdk/types": "^3.1.0", + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@aws-sdk/util-utf8-browser": "^3.0.0", "tslib": "^1.11.1" @@ -62,13 +84,13 @@ "optional": true }, "node_modules/@aws-crypto/sha256-js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-2.0.0.tgz", - "integrity": "sha512-VZY+mCY4Nmrs5WGfitmNqXzaE873fcIZDu54cbaDaaamsaTOP1DBImV9F4pICc3EHjQXujyE8jig+PFCaew9ig==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", "optional": true, "dependencies": { - "@aws-crypto/util": "^2.0.0", - "@aws-sdk/types": "^3.1.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", "tslib": "^1.11.1" } }, @@ -79,9 +101,9 @@ "optional": true }, "node_modules/@aws-crypto/supports-web-crypto": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-2.0.2.tgz", - "integrity": "sha512-6mbSsLHwZ99CTOOswvCRP3C+VCWnzBf+1SnbWxzzJ9lR0mA0JnY2JEAhp8rqmTE0GPFy88rrM27ffgp62oErMQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", "optional": true, "dependencies": { "tslib": "^1.11.1" @@ -94,12 +116,12 @@ "optional": true }, "node_modules/@aws-crypto/util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-2.0.2.tgz", - "integrity": "sha512-Lgu5v/0e/BcrZ5m/IWqzPUf3UYFTy/PpeED+uc9SWUR1iZQL8XXbGQg10UfllwwBryO3hFF5dizK+78aoXC1eA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", "optional": true, "dependencies": { - "@aws-sdk/types": "^3.110.0", + "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-utf8-browser": "^3.0.0", "tslib": "^1.11.1" } @@ -111,504 +133,518 @@ "optional": true }, "node_modules/@aws-sdk/abort-controller": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.208.0.tgz", - "integrity": "sha512-mQkDR+8VLCafg9KI4TgftftBOL170ricyb+HgV8n5jLDrEG+TfOfud8e6us2lIFESEuMpohC+/8yIcf6JjKkMg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.347.0.tgz", + "integrity": "sha512-P/2qE6ntYEmYG4Ez535nJWZbXqgbkJx8CMz7ChEuEg3Gp3dvVYEKg+iEUEvlqQ2U5dWP5J3ehw5po9t86IsVPQ==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.211.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.211.0.tgz", - "integrity": "sha512-KhXo1v78szdvLyF0SHRXR2I7SNkFeC0iay9amspAsF2jMz3CPu2EqWu4ymqO7lSSaAGEkKaUE9ZvD7uNn5oo7A==", - "optional": true, - "dependencies": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/client-sts": "3.211.0", - "@aws-sdk/config-resolver": "3.209.0", - "@aws-sdk/credential-provider-node": "3.211.0", - "@aws-sdk/fetch-http-handler": "3.208.0", - "@aws-sdk/hash-node": "3.208.0", - "@aws-sdk/invalid-dependency": "3.208.0", - "@aws-sdk/middleware-content-length": "3.208.0", - "@aws-sdk/middleware-endpoint": "3.208.0", - "@aws-sdk/middleware-host-header": "3.208.0", - "@aws-sdk/middleware-logger": "3.208.0", - "@aws-sdk/middleware-recursion-detection": "3.208.0", - "@aws-sdk/middleware-retry": "3.209.0", - "@aws-sdk/middleware-serde": "3.208.0", - "@aws-sdk/middleware-signing": "3.208.0", - "@aws-sdk/middleware-stack": "3.208.0", - "@aws-sdk/middleware-user-agent": "3.208.0", - "@aws-sdk/node-config-provider": "3.209.0", - "@aws-sdk/node-http-handler": "3.208.0", - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/smithy-client": "3.209.0", - "@aws-sdk/types": "3.208.0", - "@aws-sdk/url-parser": "3.208.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.209.0", - "@aws-sdk/util-defaults-mode-node": "3.209.0", - "@aws-sdk/util-endpoints": "3.211.0", - "@aws-sdk/util-user-agent-browser": "3.208.0", - "@aws-sdk/util-user-agent-node": "3.209.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "tslib": "^2.3.1" + "version": "3.348.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.348.0.tgz", + "integrity": "sha512-1fcJFUQTsAXjkaAn/kn9ty790uHbCpukkuqJ/0QNPFYaa6vu93xx7FnzOvRK4XvaojwZ/C+yxp0fNQ+GjXG0vg==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.348.0", + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/credential-provider-node": "3.348.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-signing": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.348.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.211.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.211.0.tgz", - "integrity": "sha512-Wuo3ZYPy9L+OixlZ7/wM1BbPBdC22xO/a8z/J1sgQZiRDl80Ax+jf1u17D91xdZJGH0hTU5AlvEY7mHP0y/hAw==", - "optional": true, - "dependencies": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/config-resolver": "3.209.0", - "@aws-sdk/fetch-http-handler": "3.208.0", - "@aws-sdk/hash-node": "3.208.0", - "@aws-sdk/invalid-dependency": "3.208.0", - "@aws-sdk/middleware-content-length": "3.208.0", - "@aws-sdk/middleware-endpoint": "3.208.0", - "@aws-sdk/middleware-host-header": "3.208.0", - "@aws-sdk/middleware-logger": "3.208.0", - "@aws-sdk/middleware-recursion-detection": "3.208.0", - "@aws-sdk/middleware-retry": "3.209.0", - "@aws-sdk/middleware-serde": "3.208.0", - "@aws-sdk/middleware-stack": "3.208.0", - "@aws-sdk/middleware-user-agent": "3.208.0", - "@aws-sdk/node-config-provider": "3.209.0", - "@aws-sdk/node-http-handler": "3.208.0", - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/smithy-client": "3.209.0", - "@aws-sdk/types": "3.208.0", - "@aws-sdk/url-parser": "3.208.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.209.0", - "@aws-sdk/util-defaults-mode-node": "3.209.0", - "@aws-sdk/util-endpoints": "3.211.0", - "@aws-sdk/util-user-agent-browser": "3.208.0", - "@aws-sdk/util-user-agent-node": "3.209.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "tslib": "^2.3.1" + "version": "3.348.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.348.0.tgz", + "integrity": "sha512-5S23gVKBl0fhZ96RD8LdPhMKeh8E5fmebyZxMNZuWliSXz++Q9ZCrwPwQbkks3duPOTcKKobs3IoqP82HoXMvQ==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.348.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.211.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.211.0.tgz", - "integrity": "sha512-oJ+5ROykVsXpBFpWUfSUYHz/RcTjsZPri6CIY+wQmEFDAOxTsgxd7l8VkqX1r/U/QiK/xDXuK+Z7MurywXS+rQ==", - "optional": true, - "dependencies": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/config-resolver": "3.209.0", - "@aws-sdk/fetch-http-handler": "3.208.0", - "@aws-sdk/hash-node": "3.208.0", - "@aws-sdk/invalid-dependency": "3.208.0", - "@aws-sdk/middleware-content-length": "3.208.0", - "@aws-sdk/middleware-endpoint": "3.208.0", - "@aws-sdk/middleware-host-header": "3.208.0", - "@aws-sdk/middleware-logger": "3.208.0", - "@aws-sdk/middleware-recursion-detection": "3.208.0", - "@aws-sdk/middleware-retry": "3.209.0", - "@aws-sdk/middleware-serde": "3.208.0", - "@aws-sdk/middleware-stack": "3.208.0", - "@aws-sdk/middleware-user-agent": "3.208.0", - "@aws-sdk/node-config-provider": "3.209.0", - "@aws-sdk/node-http-handler": "3.208.0", - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/smithy-client": "3.209.0", - "@aws-sdk/types": "3.208.0", - "@aws-sdk/url-parser": "3.208.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.209.0", - "@aws-sdk/util-defaults-mode-node": "3.209.0", - "@aws-sdk/util-endpoints": "3.211.0", - "@aws-sdk/util-user-agent-browser": "3.208.0", - "@aws-sdk/util-user-agent-node": "3.209.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "tslib": "^2.3.1" + "version": "3.348.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.348.0.tgz", + "integrity": "sha512-tvHpcycx4EALvk38I9rAOdPeHvBDezqIB4lrE7AvnOJljlvCcdQ2gXa9GDrwrM7zuYBIZMBRE/njTMrCwoOdAA==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.348.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.211.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.211.0.tgz", - "integrity": "sha512-39/PMIKLEaRUztx3m4I0x9SCnqTStaQuqIabAK/wk0uy+O2p32sv7eacRrGjZWHngqdsK7S1s/LSFErYzzIvkw==", - "optional": true, - "dependencies": { - "@aws-crypto/sha256-browser": "2.0.0", - "@aws-crypto/sha256-js": "2.0.0", - "@aws-sdk/config-resolver": "3.209.0", - "@aws-sdk/credential-provider-node": "3.211.0", - "@aws-sdk/fetch-http-handler": "3.208.0", - "@aws-sdk/hash-node": "3.208.0", - "@aws-sdk/invalid-dependency": "3.208.0", - "@aws-sdk/middleware-content-length": "3.208.0", - "@aws-sdk/middleware-endpoint": "3.208.0", - "@aws-sdk/middleware-host-header": "3.208.0", - "@aws-sdk/middleware-logger": "3.208.0", - "@aws-sdk/middleware-recursion-detection": "3.208.0", - "@aws-sdk/middleware-retry": "3.209.0", - "@aws-sdk/middleware-sdk-sts": "3.208.0", - "@aws-sdk/middleware-serde": "3.208.0", - "@aws-sdk/middleware-signing": "3.208.0", - "@aws-sdk/middleware-stack": "3.208.0", - "@aws-sdk/middleware-user-agent": "3.208.0", - "@aws-sdk/node-config-provider": "3.209.0", - "@aws-sdk/node-http-handler": "3.208.0", - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/smithy-client": "3.209.0", - "@aws-sdk/types": "3.208.0", - "@aws-sdk/url-parser": "3.208.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.209.0", - "@aws-sdk/util-defaults-mode-node": "3.209.0", - "@aws-sdk/util-endpoints": "3.211.0", - "@aws-sdk/util-user-agent-browser": "3.208.0", - "@aws-sdk/util-user-agent-node": "3.209.0", - "@aws-sdk/util-utf8-browser": "3.188.0", - "@aws-sdk/util-utf8-node": "3.208.0", - "fast-xml-parser": "4.0.11", - "tslib": "^2.3.1" + "version": "3.348.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.348.0.tgz", + "integrity": "sha512-4iaQlWAOHMEF4xjR/FB/ws3aUjXjJHwbsIcqbdYAxsKijDYYTZYCPc/gM0NE1yi28qlNYNhMzHipe5xTYbU2Eg==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/credential-provider-node": "3.348.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-sdk-sts": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-signing": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.348.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "fast-xml-parser": "4.2.4", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/config-resolver": { - "version": "3.209.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.209.0.tgz", - "integrity": "sha512-wLXI1Jg9xx9wE8vdIfOgSKnoBWbn9j3IvW4+7PnM/nf5xC30/Jp4j+JndEG/BKyDQF7HJQTIeRpSkwKaqJhCRA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.347.0.tgz", + "integrity": "sha512-2ja+Sf/VnUO7IQ3nKbDQ5aumYKKJUaTm/BuVJ29wNho8wYHfuf7wHZV0pDTkB8RF5SH7IpHap7zpZAj39Iq+EA==", "optional": true, "dependencies": { - "@aws-sdk/signature-v4": "3.208.0", - "@aws-sdk/types": "3.208.0", - "@aws-sdk/util-config-provider": "3.208.0", - "@aws-sdk/util-middleware": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-config-provider": "3.310.0", + "@aws-sdk/util-middleware": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.211.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.211.0.tgz", - "integrity": "sha512-YbTioDEGvGFYaHeeQrQUQLHnqvWYNdDn5acEAD76DMnoV+B04OVKWYphFd6KBZClIkXnH0T8stPnOE7La6rWjg==", + "version": "3.348.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.348.0.tgz", + "integrity": "sha512-VQQVEP844mAwn5iEIzc/hBOuSzMGBL61sqEGqqgxhe6Sjnd8NfGNlOjV6fOxlUHhOelumqBMXgn6liIZbfcqFQ==", "optional": true, "dependencies": { - "@aws-sdk/client-cognito-identity": "3.211.0", - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/client-cognito-identity": "3.348.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.208.0.tgz", - "integrity": "sha512-FB+KUSpZc03wVTXxGnMmgtaP0sJOv0D7oyogHb7wcf5b7RjjwqoaeUcJHTdKRZaW6e1foLk3/L9uebxiWefDbQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.347.0.tgz", + "integrity": "sha512-UnEM+LKGpXKzw/1WvYEQsC6Wj9PupYZdQOE+e2Dgy2dqk/pVFy4WueRtFXYDT2B41ppv3drdXUuKZRIDVqIgNQ==", "optional": true, "dependencies": { - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-imds": { - "version": "3.209.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.209.0.tgz", - "integrity": "sha512-EjA1nWduIHjALjNF6O2lpKVOoTIlfGHgvqCxjFf7XNqBTTKWCxEflcmUgqXwo9A7TU0mTTyr7nLGMAsNE2CR3w==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.347.0.tgz", + "integrity": "sha512-7scCy/DCDRLIhlqTxff97LQWDnRwRXji3bxxMg+xWOTTaJe7PWx+etGSbBWaL42vsBHFShQjSLvJryEgoBktpw==", "optional": true, "dependencies": { - "@aws-sdk/node-config-provider": "3.209.0", - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/types": "3.208.0", - "@aws-sdk/url-parser": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.211.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.211.0.tgz", - "integrity": "sha512-kFekBDGX3tMsbEBjpCHt2dp5hx7xBN0d7v+fNXky4fB61bNUxcLNpXkTgDIqRyMzEje3Jov9Be9Qgqb8ud0Fiw==", - "optional": true, - "dependencies": { - "@aws-sdk/credential-provider-env": "3.208.0", - "@aws-sdk/credential-provider-imds": "3.209.0", - "@aws-sdk/credential-provider-sso": "3.211.0", - "@aws-sdk/credential-provider-web-identity": "3.208.0", - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/shared-ini-file-loader": "3.209.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "version": "3.348.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.348.0.tgz", + "integrity": "sha512-0IEH5mH/cz2iLyr/+pSa3sCsQcGADiLSEn6yivsXdfz1zDqBiv+ffDoL0+Pvnp+TKf8sA6OlX8PgoMoEBvBdKw==", + "optional": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/credential-provider-process": "3.347.0", + "@aws-sdk/credential-provider-sso": "3.348.0", + "@aws-sdk/credential-provider-web-identity": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.211.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.211.0.tgz", - "integrity": "sha512-RWDitzHmZOfrfTZCnL8nOLQgYgawAAw8IF5pqeNjcN9TZ/pR64B9pusTYD7a+uVDB8kb9vMU767g89ts2pqmfQ==", - "optional": true, - "dependencies": { - "@aws-sdk/credential-provider-env": "3.208.0", - "@aws-sdk/credential-provider-imds": "3.209.0", - "@aws-sdk/credential-provider-ini": "3.211.0", - "@aws-sdk/credential-provider-process": "3.209.0", - "@aws-sdk/credential-provider-sso": "3.211.0", - "@aws-sdk/credential-provider-web-identity": "3.208.0", - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/shared-ini-file-loader": "3.209.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "version": "3.348.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.348.0.tgz", + "integrity": "sha512-ngRWphm9e36i58KqVi7Z8WOub+k0cSl+JZaAmgfFm0+dsfBG5uheo598OeiwWV0DqlilvaQZFaMVQgG2SX/tHg==", + "optional": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/credential-provider-ini": "3.348.0", + "@aws-sdk/credential-provider-process": "3.347.0", + "@aws-sdk/credential-provider-sso": "3.348.0", + "@aws-sdk/credential-provider-web-identity": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.209.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.209.0.tgz", - "integrity": "sha512-G0urC5p1kgUfgpK8lncdisSewa8onnoQAVdf2Uh51hOqc7UufGce+ouvLH8J2iMkMaL1MSyu8fqwfZNyDtH37g==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.347.0.tgz", + "integrity": "sha512-yl1z4MsaBdXd4GQ2halIvYds23S67kElyOwz7g8kaQ4kHj+UoYWxz3JVW/DGusM6XmQ9/F67utBrUVA0uhQYyw==", "optional": true, "dependencies": { - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/shared-ini-file-loader": "3.209.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.211.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.211.0.tgz", - "integrity": "sha512-S8ciHRypUCi0Uz0D80yVGkWmvpCBCvkEaj+IO0LdYX05GDnH/B44DA8UQ0pfAJqLy5BeSO5snKVRKSPzxNtUGw==", + "version": "3.348.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.348.0.tgz", + "integrity": "sha512-5cQao705376KgGkLv9xgkQ3T5H7KdNddWuyoH2wDcrHd1BA2Lnrell3Yyh7R6jQeV7uCQE/z0ugUOKhDqNKIqQ==", "optional": true, "dependencies": { - "@aws-sdk/client-sso": "3.211.0", - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/shared-ini-file-loader": "3.209.0", - "@aws-sdk/token-providers": "3.211.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sso": "3.348.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/token-providers": "3.348.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.208.0.tgz", - "integrity": "sha512-7wtrdEr8uvDr5t0stimrXGsW4G+TQyluZ9OucCCY0HXgNihmnk1BIu+COuOSxRtFXHwCh4rIPaVE1ABG2Mq24g==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.347.0.tgz", + "integrity": "sha512-DxoTlVK8lXjS1zVphtz/Ab+jkN/IZor9d6pP2GjJHNoAIIzXfRwwj5C8vr4eTayx/5VJ7GRP91J8GJ2cKly8Qw==", "optional": true, "dependencies": { - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-providers": { - "version": "3.211.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.211.0.tgz", - "integrity": "sha512-duo3zSI8usGxA23skzQqVDaKB7k3McJYbFG2nzPTYD+RI4w5Sbs66SUWvTmtSrdZJWmzDsDNKW9fOMtnNARVVw==", - "optional": true, - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.211.0", - "@aws-sdk/client-sso": "3.211.0", - "@aws-sdk/client-sts": "3.211.0", - "@aws-sdk/credential-provider-cognito-identity": "3.211.0", - "@aws-sdk/credential-provider-env": "3.208.0", - "@aws-sdk/credential-provider-imds": "3.209.0", - "@aws-sdk/credential-provider-ini": "3.211.0", - "@aws-sdk/credential-provider-node": "3.211.0", - "@aws-sdk/credential-provider-process": "3.209.0", - "@aws-sdk/credential-provider-sso": "3.211.0", - "@aws-sdk/credential-provider-web-identity": "3.208.0", - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/shared-ini-file-loader": "3.209.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "version": "3.348.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.348.0.tgz", + "integrity": "sha512-lpq1aHjFyExqD/6L8BK0OaROpCJuhnexGrABYljGI6yaLsyHbQpdE2+Y/WaxuRAK9wyP5s+7KNJ1ZK1ktrk5uQ==", + "optional": true, + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.348.0", + "@aws-sdk/client-sso": "3.348.0", + "@aws-sdk/client-sts": "3.348.0", + "@aws-sdk/credential-provider-cognito-identity": "3.348.0", + "@aws-sdk/credential-provider-env": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/credential-provider-ini": "3.348.0", + "@aws-sdk/credential-provider-node": "3.348.0", + "@aws-sdk/credential-provider-process": "3.347.0", + "@aws-sdk/credential-provider-sso": "3.348.0", + "@aws-sdk/credential-provider-web-identity": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, + "node_modules/@aws-sdk/eventstream-codec": { + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-codec/-/eventstream-codec-3.347.0.tgz", + "integrity": "sha512-61q+SyspjsaQ4sdgjizMyRgVph2CiW4aAtfpoH69EJFJfTxTR/OqnZ9Jx/3YiYi0ksrvDenJddYodfWWJqD8/w==", + "optional": true, + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-hex-encoding": "3.310.0", + "tslib": "^2.5.0" + } + }, "node_modules/@aws-sdk/fetch-http-handler": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.208.0.tgz", - "integrity": "sha512-GuwkwOeyLKCbSbnFlyHdlKd7u54cnQUI8NfVDAxpZvomY3PV476Tzg8XEyOYE67r5rR6XMqn6IK1PmFAACY+ew==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.347.0.tgz", + "integrity": "sha512-sQ5P7ivY8//7wdxfA76LT1sF6V2Tyyz1qF6xXf9sihPN5Q1Y65c+SKpMzXyFSPqWZ82+SQQuDliYZouVyS6kQQ==", "optional": true, "dependencies": { - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/querystring-builder": "3.208.0", - "@aws-sdk/types": "3.208.0", - "@aws-sdk/util-base64": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/querystring-builder": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/hash-node": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.208.0.tgz", - "integrity": "sha512-X5u6nD9+wzaA6qhqbobxsIgiyDJMW8NgqjZgHoc5x1wz4unHUCEuSBZy1kbIZ6+EPZ9bQHQZ21gKgf1j5vhsvQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.347.0.tgz", + "integrity": "sha512-96+ml/4EaUaVpzBdOLGOxdoXOjkPgkoJp/0i1fxOJEvl8wdAQSwc3IugVK9wZkCxy2DlENtgOe6DfIOhfffm/g==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-buffer-from": "3.310.0", + "@aws-sdk/util-utf8": "3.310.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/invalid-dependency": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.208.0.tgz", - "integrity": "sha512-mUpbtijk14KntYy+w5FSvmsfj/Dqa8HylYeCKniKBKkQ1avjEz7CdizVoxyZrR3rldnLE3gItr0FEDRUhtfkAA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.347.0.tgz", + "integrity": "sha512-8imQcwLwqZ/wTJXZqzXT9pGLIksTRckhGLZaXT60tiBOPKuerTsus2L59UstLs5LP8TKaVZKFFSsjRIn9dQdmQ==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/is-array-buffer": { - "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.201.0.tgz", - "integrity": "sha512-UPez5qLh3dNgt0DYnPD/q0mVJY84rA17QE26hVNOW3fAji8W2wrwrxdacWOxyXvlxWsVRcKmr+lay1MDqpAMfg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.310.0.tgz", + "integrity": "sha512-urnbcCR+h9NWUnmOtet/s4ghvzsidFmspfhYaHAmSRdy9yDjdjBJMFjjsn85A1ODUktztm+cVncXjQ38WCMjMQ==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-content-length": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.208.0.tgz", - "integrity": "sha512-8bLh7lHtmKQQ2fk0fGiP7pcVJglB/dz7Q9OooxFYK+eybqxfIDDUgKphA8AFT5W34tJRh5nhT3QTJ6zrOTQM3w==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.347.0.tgz", + "integrity": "sha512-i4qtWTDImMaDUtwKQPbaZpXsReiwiBomM1cWymCU4bhz81HL01oIxOxOBuiM+3NlDoCSPr3KI6txZSz/8cqXCQ==", "optional": true, "dependencies": { - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-endpoint": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.208.0.tgz", - "integrity": "sha512-pVa/cyB6ronfTVAoKUUTFbAPslDPU43DWOKXY/bACC3ys1lFo1CWjz4dLSQARxEEW3iZ1yZTy0zoHXnNrw5CFQ==", - "optional": true, - "dependencies": { - "@aws-sdk/middleware-serde": "3.208.0", - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/signature-v4": "3.208.0", - "@aws-sdk/types": "3.208.0", - "@aws-sdk/url-parser": "3.208.0", - "@aws-sdk/util-config-provider": "3.208.0", - "@aws-sdk/util-middleware": "3.208.0", - "tslib": "^2.3.1" + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.347.0.tgz", + "integrity": "sha512-unF0c6dMaUL1ffU+37Ugty43DgMnzPWXr/Jup/8GbK5fzzWT5NQq6dj9KHPubMbWeEjQbmczvhv25JuJdK8gNQ==", + "optional": true, + "dependencies": { + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-middleware": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.208.0.tgz", - "integrity": "sha512-3oyXK81TLWOZ2T/9Ltpbj/Z7R4QWSf+FCQRpY48ND2im/ALkgFRk/tmDTOshv+TQzW1q2lOSEeq4vK6yOCar7g==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.347.0.tgz", + "integrity": "sha512-kpKmR9OvMlnReqp5sKcJkozbj1wmlblbVSbnQAIkzeQj2xD5dnVR3Nn2ogQKxSmU1Fv7dEroBtrruJ1o3fY38A==", "optional": true, "dependencies": { - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.208.0.tgz", - "integrity": "sha512-mwSpuWruB8RrgUAAW7w/lvadnMDesl/bZ2IELBgJri+2rIqLGbAtygJBiG0Y3e8/IeOHuKuGkN1rFYZ4SKr7/A==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.347.0.tgz", + "integrity": "sha512-NYC+Id5UCkVn+3P1t/YtmHt75uED06vwaKyxDy0UmB2K66PZLVtwWbLpVWrhbroaw1bvUHYcRyQ9NIfnVcXQjA==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.208.0.tgz", - "integrity": "sha512-Dgpf5NEOYXvkQuGcbxvDovTh4HwO4ULJReGko67NJjgdZZyFS1fNykVPncxenRpsN9SJBigswYs3lwPVpqijzA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.347.0.tgz", + "integrity": "sha512-qfnSvkFKCAMjMHR31NdsT0gv5Sq/ZHTUD4yQsSLpbVQ6iYAS834lrzXt41iyEHt57Y514uG7F/Xfvude3u4icQ==", "optional": true, "dependencies": { - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-retry": { - "version": "3.209.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.209.0.tgz", - "integrity": "sha512-PGHbpGw74HxmtqsMEH+xn2oC5/BPdHVyapB66x83n+sywt1ejTiarbQhNs70YzcSsTrJfbhbrFP1V9AzRmMaQA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.347.0.tgz", + "integrity": "sha512-CpdM+8dCSbX96agy4FCzOfzDmhNnGBM/pxrgIVLm5nkYTLuXp/d7ubpFEUHULr+4hCd5wakHotMt7yO29NFaVw==", "optional": true, "dependencies": { - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/service-error-classification": "3.208.0", - "@aws-sdk/types": "3.208.0", - "@aws-sdk/util-middleware": "3.208.0", - "tslib": "^2.3.1", + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/service-error-classification": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-middleware": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "tslib": "^2.5.0", "uuid": "^8.3.2" }, "engines": { @@ -625,423 +661,439 @@ } }, "node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.208.0.tgz", - "integrity": "sha512-lFVodZHYLF7puXgNZ1m5ycKbyCPp79nqI+pkRXl066ZtZWzCW8+JKCaLjF3jfXlnvg6foPDJdxUvt0VU5EddGg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.347.0.tgz", + "integrity": "sha512-38LJ0bkIoVF3W97x6Jyyou72YV9Cfbml4OaDEdnrCOo0EssNZM5d7RhjMvQDwww7/3OBY/BzeOcZKfJlkYUXGw==", "optional": true, "dependencies": { - "@aws-sdk/middleware-signing": "3.208.0", - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/signature-v4": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/middleware-signing": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-serde": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.208.0.tgz", - "integrity": "sha512-3h2yP6qyf/IhfdvyFeNX7w4BF37vOZvfUDBq+wb1QEc7DCAskoUKWtCCKJ9HDq3IJQp8hzqY82eawUir6flqlQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.347.0.tgz", + "integrity": "sha512-x5Foi7jRbVJXDu9bHfyCbhYDH5pKK+31MmsSJ3k8rY8keXLBxm2XEEg/AIoV9/TUF9EeVvZ7F1/RmMpJnWQsEg==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-signing": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.208.0.tgz", - "integrity": "sha512-cMSWhg8xOrxZw04EYKEQQQ7RT+03rigS4KS3Uy6x/M+jFyoM+sRiY/7376sJCwlpvKH2xJIVpwPbKk/uz4j4DA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.347.0.tgz", + "integrity": "sha512-zVBF/4MGKnvhAE/J+oAL/VAehiyv+trs2dqSQXwHou9j8eA8Vm8HS2NdOwpkZQchIxTuwFlqSusDuPEdYFbvGw==", "optional": true, "dependencies": { - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/signature-v4": "3.208.0", - "@aws-sdk/types": "3.208.0", - "@aws-sdk/util-middleware": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/signature-v4": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-middleware": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-stack": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.208.0.tgz", - "integrity": "sha512-bvFPUa+RTB7PSRCUsO6bRlEtiEadrDES+dpNmInMNQ9kmbd4OhNOCb664hhtiglIIXX5cd8mSPEo+w/RV0kEEQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.347.0.tgz", + "integrity": "sha512-Izidg4rqtYMcKuvn2UzgEpPLSmyd8ub9+LQ2oIzG3mpIzCBITq7wp40jN1iNkMg+X6KEnX9vdMJIYZsPYMCYuQ==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.208.0.tgz", - "integrity": "sha512-6RNf+TOZpiCy7xUcDSh8ji/x8ht1oAM+qIhm6hsEPLdI1cTvbPZrwowO9Y6L0J68V9OkEgLYiq77KKKYT7QQSw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.347.0.tgz", + "integrity": "sha512-wJbGN3OE1/daVCrwk49whhIr9E0j1N4gWwN/wi4WuyYIA+5lMUfVp0aGIOvZR+878DxuFz2hQ4XcZVT4K2WvQw==", "optional": true, "dependencies": { - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/node-config-provider": { - "version": "3.209.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.209.0.tgz", - "integrity": "sha512-jNrUn8qTN9BIxHCcLTv2s2h8Riaz4kjwDhubVQNyI0WGZ+PYKATnZjA+Guzbnq2WMzZmwrMIE5GoOiVsPD8xYQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.347.0.tgz", + "integrity": "sha512-faU93d3+5uTTUcotGgMXF+sJVFjrKh+ufW+CzYKT4yUHammyaIab/IbTPWy2hIolcEGtuPeVoxXw8TXbkh/tuw==", "optional": true, "dependencies": { - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/shared-ini-file-loader": "3.209.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/node-http-handler": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.208.0.tgz", - "integrity": "sha512-2t0b9Id7WekluqxQdPugAZhe/wdzW0L53rfMEfDS3R0INNSq1sEfddIfCzJrmfWDCrCOGIDNyxo/w7Ki3NclzQ==", + "version": "3.348.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.348.0.tgz", + "integrity": "sha512-wxdgc4tO5F6lN4wHr0CZ4TyIjDW/ORp4SJZdWYNs2L5J7+/SwqgJY2lxRlGi0i7Md+apAdE3sT3ukVQ/9pVfPg==", "optional": true, "dependencies": { - "@aws-sdk/abort-controller": "3.208.0", - "@aws-sdk/protocol-http": "3.208.0", - "@aws-sdk/querystring-builder": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/abort-controller": "3.347.0", + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/querystring-builder": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/property-provider": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.208.0.tgz", - "integrity": "sha512-aUhfuwXjZ5TGzLhBstuAMmbnxHXeSGhzoIS8yy465ifgc95p6cHFZf+ZibgwgCMaGrKlTDCia2zwwpKQHN+4cw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.347.0.tgz", + "integrity": "sha512-t3nJ8CYPLKAF2v9nIHOHOlF0CviQbTvbFc2L4a+A+EVd/rM4PzL3+3n8ZJsr0h7f6uD04+b5YRFgKgnaqLXlEg==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/protocol-http": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.208.0.tgz", - "integrity": "sha512-Sr9dmaW0Z9X9s16NHZn94efLRpaqLyLqABFPgjqE8cYP6eLX/VrmZGNR62GFVxCiyEEpVxy4Ddk1YkbRwnuonA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.347.0.tgz", + "integrity": "sha512-2YdBhc02Wvy03YjhGwUxF0UQgrPWEy8Iq75pfS42N+/0B/+eWX1aQgfjFxIpLg7YSjT5eKtYOQGlYd4MFTgj9g==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/querystring-builder": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.208.0.tgz", - "integrity": "sha512-1Rpauh5hWlK++KjsHQjHcSN7yE05hj1FVb0HaeLrFIJB5rQYWXK7DpOUhmv5SOmU+q6cIM2kNCrSxH31+WglMw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.347.0.tgz", + "integrity": "sha512-phtKTe6FXoV02MoPkIVV6owXI8Mwr5IBN3bPoxhcPvJG2AjEmnetSIrhb8kwc4oNhlwfZwH6Jo5ARW/VEWbZtg==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", - "@aws-sdk/util-uri-escape": "3.201.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-uri-escape": "3.310.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/querystring-parser": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.208.0.tgz", - "integrity": "sha512-dVVLdP3il9bJX74/BNBjFn59XrEVBUZ4xSKYH6t7dgSz9uSu8DcT4pPzwaq+/94dVewCW3zq2jVA1iw1rK7JVQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.347.0.tgz", + "integrity": "sha512-5VXOhfZz78T2W7SuXf2avfjKglx1VZgZgp9Zfhrt/Rq+MTu2D+PZc5zmJHhYigD7x83jLSLogpuInQpFMA9LgA==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/service-error-classification": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.208.0.tgz", - "integrity": "sha512-ZZWV3AOTd8UDcfXCNoQ8v4sHaTgFxGaXWO0NHHgqFbVYr1d+8EXQiOy/v8JsY1jrfoXBWXptTOcioCTeM0xBpw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.347.0.tgz", + "integrity": "sha512-xZ3MqSY81Oy2gh5g0fCtooAbahqh9VhsF8vcKjVX8+XPbGC8y+kej82+MsMg4gYL8gRFB9u4hgYbNgIS6JTAvg==", "optional": true, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/shared-ini-file-loader": { - "version": "3.209.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.209.0.tgz", - "integrity": "sha512-hji3B/q3zFuElaUQM/ZZUFbCFBsaVjpWATgiDTnSYP+MShWvvwm/WigeC2aCNos1bs/8HVizOy9cmvK63vLZbw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.347.0.tgz", + "integrity": "sha512-Xw+zAZQVLb+xMNHChXQ29tzzLqm3AEHsD8JJnlkeFjeMnWQtXdUfOARl5s8NzAppcKQNlVe2gPzjaKjoy2jz1Q==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/signature-v4": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.208.0.tgz", - "integrity": "sha512-+c5A8RsN4Lk3TXFiQ3ZsW7sJ4zYPPmYQ55ITSfjock5hzgM1vW43Mgvjjq6foW5L7SNfdhLH+NrhpgFwSF/GeA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.347.0.tgz", + "integrity": "sha512-58Uq1do+VsTHYkP11dTK+DF53fguoNNJL9rHRWhzP+OcYv3/mBMLoS2WPz/x9FO5mBg4ESFsug0I6mXbd36tjw==", "optional": true, "dependencies": { - "@aws-sdk/is-array-buffer": "3.201.0", - "@aws-sdk/types": "3.208.0", - "@aws-sdk/util-hex-encoding": "3.201.0", - "@aws-sdk/util-middleware": "3.208.0", - "@aws-sdk/util-uri-escape": "3.201.0", - "tslib": "^2.3.1" + "@aws-sdk/eventstream-codec": "3.347.0", + "@aws-sdk/is-array-buffer": "3.310.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-hex-encoding": "3.310.0", + "@aws-sdk/util-middleware": "3.347.0", + "@aws-sdk/util-uri-escape": "3.310.0", + "@aws-sdk/util-utf8": "3.310.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/smithy-client": { - "version": "3.209.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.209.0.tgz", - "integrity": "sha512-+d9lPAFOu3hZdLfyzMurRU6xZ+eqwKbF6HY7mDL4hGafRb/uw28HBncSwyUk5s7MIND9+RnvY4F/MwBq9wznXg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.347.0.tgz", + "integrity": "sha512-PaGTDsJLGK0sTjA6YdYQzILRlPRN3uVFyqeBUkfltXssvUzkm8z2t1lz2H4VyJLAhwnG5ZuZTNEV/2mcWrU7JQ==", "optional": true, "dependencies": { - "@aws-sdk/middleware-stack": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.211.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.211.0.tgz", - "integrity": "sha512-dxdUT+JKCl9krmBQde1HeV6rwYP+ZTBkfx5vIa3PdfDI7XljRBf1XdE0mS18eSURfQA7v969Y5sJ6/rFyjT/QA==", + "version": "3.348.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.348.0.tgz", + "integrity": "sha512-nTjoJkUsJUrJTZuqaeMD9PW2//Rdg2HgfDjiyC4jmAXtayWYCi11mqauurMaUHJ3p5qJ8f5xzxm6vBTbrftPag==", "optional": true, "dependencies": { - "@aws-sdk/client-sso-oidc": "3.211.0", - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/shared-ini-file-loader": "3.209.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sso-oidc": "3.348.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/types": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.208.0.tgz", - "integrity": "sha512-5AuOPtY1Hdf4xoEo+voRijl3OnFm8IB+oITXl+SN2iASJv+XPnRNw/QVbIxfGeWgWhmK31F+XdjTYsjT2rx8Qw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.347.0.tgz", + "integrity": "sha512-GkCMy79mdjU9OTIe5KT58fI/6uqdf8UmMdWqVHmFJ+UpEzOci7L/uw4sOXWo7xpPzLs6cJ7s5ouGZW4GRPmHFA==", "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/url-parser": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.208.0.tgz", - "integrity": "sha512-zhU231xkZbUh68Z/TGNRW30MGTZQVigGuMiJU6eOtL2aOulnKqI1Yjs/QejrTtPWsqSihWvxOUZ2cVRPyeOvrA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.347.0.tgz", + "integrity": "sha512-lhrnVjxdV7hl+yCnJfDZOaVLSqKjxN20MIOiijRiqaWGLGEAiSqBreMhL89X1WKCifxAs4zZf9YB9SbdziRpAA==", "optional": true, "dependencies": { - "@aws-sdk/querystring-parser": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/querystring-parser": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/util-base64": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.208.0.tgz", - "integrity": "sha512-PQniZph5A6N7uuEOQi+1hnMz/FSOK/8kMFyFO+4DgA1dZ5pcKcn5wiFwHkcTb/BsgVqQa3Jx0VHNnvhlS8JyTg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.310.0.tgz", + "integrity": "sha512-v3+HBKQvqgdzcbL+pFswlx5HQsd9L6ZTlyPVL2LS9nNXnCcR3XgGz9jRskikRUuUvUXtkSG1J88GAOnJ/apTPg==", "optional": true, "dependencies": { - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/util-buffer-from": "3.310.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-body-length-browser": { - "version": "3.188.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz", - "integrity": "sha512-8VpnwFWXhnZ/iRSl9mTf+VKOX9wDE8QtN4bj9pBfxwf90H1X7E8T6NkiZD3k+HubYf2J94e7DbeHs7fuCPW5Qg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.310.0.tgz", + "integrity": "sha512-sxsC3lPBGfpHtNTUoGXMQXLwjmR0zVpx0rSvzTPAuoVILVsp5AU/w5FphNPxD5OVIjNbZv9KsKTuvNTiZjDp9g==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/util-body-length-node": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.208.0.tgz", - "integrity": "sha512-3zj50e5g7t/MQf53SsuuSf0hEELzMtD8RX8C76f12OSRo2Bca4FLLYHe0TZbxcfQHom8/hOaeZEyTyMogMglqg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.310.0.tgz", + "integrity": "sha512-2tqGXdyKhyA6w4zz7UPoS8Ip+7sayOg9BwHNidiGm2ikbDxm1YrCfYXvCBdwaJxa4hJfRVz+aL9e+d3GqPI9pQ==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-buffer-from": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.208.0.tgz", - "integrity": "sha512-7L0XUixNEFcLUGPeBF35enCvB9Xl+K6SQsmbrPk1P3mlV9mguWSDQqbOBwY1Ir0OVbD6H/ZOQU7hI/9RtRI0Zw==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.310.0.tgz", + "integrity": "sha512-i6LVeXFtGih5Zs8enLrt+ExXY92QV25jtEnTKHsmlFqFAuL3VBeod6boeMXkN2p9lbSVVQ1sAOOYZOHYbYkntw==", "optional": true, "dependencies": { - "@aws-sdk/is-array-buffer": "3.201.0", - "tslib": "^2.3.1" + "@aws-sdk/is-array-buffer": "3.310.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-config-provider": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.208.0.tgz", - "integrity": "sha512-DSRqwrERUsT34ug+anlMBIFooBEGwM8GejC7q00Y/9IPrQy50KnG5PW2NiTjuLKNi7pdEOlwTSEocJE15eDZIg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.310.0.tgz", + "integrity": "sha512-xIBaYo8dwiojCw8vnUcIL4Z5tyfb1v3yjqyJKJWV/dqKUFOOS0U591plmXbM+M/QkXyML3ypon1f8+BoaDExrg==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-defaults-mode-browser": { - "version": "3.209.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.209.0.tgz", - "integrity": "sha512-c+AlHqsgeDr9+87fS1wfnyVzEH3myt56GvNt0puzIv0QQqfpobMnfN8/Fy0cqMpf1eQNYY4a6lFlkComsXi5dw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.347.0.tgz", + "integrity": "sha512-+JHFA4reWnW/nMWwrLKqL2Lm/biw/Dzi/Ix54DAkRZ08C462jMKVnUlzAI+TfxQE3YLm99EIa0G7jiEA+p81Qw==", "optional": true, "dependencies": { - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/types": "3.208.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", "bowser": "^2.11.0", - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">= 10.0.0" } }, "node_modules/@aws-sdk/util-defaults-mode-node": { - "version": "3.209.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.209.0.tgz", - "integrity": "sha512-RljPVLog6EX052DQjx4XQ95n7ZiAbmn7Vd6YSn1x93U797umaC5CnrT7a/WusTQACtxBDFWcosRgO1ZGDXuRKQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.347.0.tgz", + "integrity": "sha512-A8BzIVhAAZE5WEukoAN2kYebzTc99ZgncbwOmgCCbvdaYlk5tzguR/s+uoT4G0JgQGol/4hAMuJEl7elNgU6RQ==", "optional": true, "dependencies": { - "@aws-sdk/config-resolver": "3.209.0", - "@aws-sdk/credential-provider-imds": "3.209.0", - "@aws-sdk/node-config-provider": "3.209.0", - "@aws-sdk/property-provider": "3.208.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">= 10.0.0" } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.211.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.211.0.tgz", - "integrity": "sha512-FY0h897WFltaUBF5aedLCBP2OlxN0aIqrInAa7aYGz3HsUTl97liHTii34bZrMJQHxmfcKBXAsjV1jJGc2orLw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.347.0.tgz", + "integrity": "sha512-/WUkirizeNAqwVj0zkcrqdQ9pUm1HY5kU+qy7xTR0OebkuJauglkmSTMD+56L1JPunWqHhlwCMVRaz5eaJdSEQ==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-hex-encoding": { - "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.201.0.tgz", - "integrity": "sha512-7t1vR1pVxKx0motd3X9rI3m/xNp78p3sHtP5yo4NP4ARpxyJ0fokBomY8ScaH2D/B+U5o9ARxldJUdMqyBlJcA==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.310.0.tgz", + "integrity": "sha512-sVN7mcCCDSJ67pI1ZMtk84SKGqyix6/0A1Ab163YKn+lFBQRMKexleZzpYzNGxYzmQS6VanP/cfU7NiLQOaSfA==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.208.0.tgz", - "integrity": "sha512-iua1A2+P7JJEDHVgvXrRJSvsnzG7stYSGQnBVphIUlemwl6nN5D+QrgbjECtrbxRz8asYFHSzhdhECqN+tFiBg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-middleware": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.208.0.tgz", - "integrity": "sha512-oXilrYpXwaPyMw1uNjL1wmR54zeFzIWx2ve1MSMheIYr26deFP3RpMfKkGXwiOvXzZ9pzTcA8shNLhg1frO/zg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.347.0.tgz", + "integrity": "sha512-8owqUA3ePufeYTUvlzdJ7Z0miLorTwx+rNol5lourGQZ9JXsVMo23+yGA7nOlFuXSGkoKpMOtn6S0BT2bcfeiw==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, + "node_modules/@aws-sdk/util-retry": { + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.347.0.tgz", + "integrity": "sha512-NxnQA0/FHFxriQAeEgBonA43Q9/VPFQa8cfJDuT2A1YZruMasgjcltoZszi1dvoIRWSZsFTW42eY2gdOd0nffQ==", + "optional": true, + "dependencies": { + "@aws-sdk/service-error-classification": "3.347.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/@aws-sdk/util-uri-escape": { - "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.201.0.tgz", - "integrity": "sha512-TeTWbGx4LU2c5rx0obHeDFeO9HvwYwQtMh1yniBz00pQb6Qt6YVOETVQikRZ+XRQwEyCg/dA375UplIpiy54mA==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.310.0.tgz", + "integrity": "sha512-drzt+aB2qo2LgtDoiy/3sVG8w63cgLkqFIa2NFlGpUgHFWTXkqtbgf4L5QdjRGKWhmZsnqkbtL7vkSWEcYDJ4Q==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.208.0.tgz", - "integrity": "sha512-Z5n9Kg2pBstzzQgRymQRgb4pM0bNPLGQejB3ZmCAphaxvuTBfu2E6KO55h5WwkFHUuh0i5u2wn1BI9R66S8CgQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.347.0.tgz", + "integrity": "sha512-ydxtsKVtQefgbk1Dku1q7pMkjDYThauG9/8mQkZUAVik55OUZw71Zzr3XO8J8RKvQG8lmhPXuAQ0FKAyycc0RA==", "optional": true, "dependencies": { - "@aws-sdk/types": "3.208.0", + "@aws-sdk/types": "3.347.0", "bowser": "^2.11.0", - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.209.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.209.0.tgz", - "integrity": "sha512-lWfvnSX8rckMGaalrKZmBlPW7F0QOviG7XbLffwToN4HnYUyXcZXIE4EzOQzuOvDsOUlos/xLkUj6krdIAApcA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.347.0.tgz", + "integrity": "sha512-6X0b9qGsbD1s80PmbaB6v1/ZtLfSx6fjRX8caM7NN0y/ObuLoX8LhYnW6WlB2f1+xb4EjaCNgpP/zCf98MXosw==", "optional": true, "dependencies": { - "@aws-sdk/node-config-provider": "3.209.0", - "@aws-sdk/types": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" @@ -1055,32 +1107,32 @@ } } }, - "node_modules/@aws-sdk/util-utf8-browser": { - "version": "3.188.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.188.0.tgz", - "integrity": "sha512-jt627x0+jE+Ydr9NwkFstg3cUvgWh56qdaqAMDsqgRlKD21md/6G226z/Qxl7lb1VEW2LlmCx43ai/37Qwcj2Q==", + "node_modules/@aws-sdk/util-utf8": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.310.0.tgz", + "integrity": "sha512-DnLfFT8uCO22uOJc0pt0DsSNau1GTisngBCDw8jQuWT5CqogMJu4b/uXmwEqfj8B3GX6Xsz8zOd6JpRlPftQoA==", "optional": true, "dependencies": { - "tslib": "^2.3.1" + "@aws-sdk/util-buffer-from": "3.310.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/util-utf8-node": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-node/-/util-utf8-node-3.208.0.tgz", - "integrity": "sha512-jKY87Acv0yWBdFxx6bveagy5FYjz+dtV8IPT7ay1E2WPWH1czoIdMAkc8tSInK31T6CRnHWkLZ1qYwCbgRfERQ==", + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", "optional": true, "dependencies": { - "@aws-sdk/util-buffer-from": "3.208.0", "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" } }, "node_modules/@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", + "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", "dependencies": { "regenerator-runtime": "^0.13.11" }, @@ -1088,60 +1140,136 @@ "node": ">=6.9.0" } }, - "node_modules/@discordjs/builders": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.3.0.tgz", - "integrity": "sha512-Pvca6Nw8Hp+n3N+Wp17xjygXmMvggbh5ywUsOYE2Et4xkwwVRwgzxDJiMUuYapPtnYt4w/8aKlf5khc8ipLvhg==", + "node_modules/@commander-js/extra-typings": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@commander-js/extra-typings/-/extra-typings-11.0.0.tgz", + "integrity": "sha512-06ol6Kn5gPjFY6v0vWOZ84nQwyqhZdaeZCHYH3vhwewjpOEjniF1KHZxh18887G3poWiJ8qyq5pb6ANuiddfPQ==", + "peerDependencies": { + "commander": "11.0.x" + } + }, + "node_modules/@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, "dependencies": { - "@discordjs/util": "^0.1.0", - "@sapphire/shapeshift": "^3.7.0", - "discord-api-types": "^0.37.12", + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@discordjs/builders": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.6.3.tgz", + "integrity": "sha512-CTCh8NqED3iecTNuiz49mwSsrc2iQb4d0MjMdmS/8pb69Y4IlzJ/DIy/p5GFlgOrFbNO2WzMHkWKQSiJ3VNXaw==", + "dependencies": { + "@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.1", - "tslib": "^2.4.0" + "ts-mixer": "^6.0.3", + "tslib": "^2.5.0" }, "engines": { "node": ">=16.9.0" } }, "node_modules/@discordjs/collection": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.2.0.tgz", - "integrity": "sha512-VvrrtGb7vbfPHzbhGq9qZB5o8FOB+kfazrxdt0OtxzSkoBuw9dURMkCwWizZ00+rDpiK2HmLHBZX+y6JsG9khw==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.1.tgz", + "integrity": "sha512-aWEc9DCf3TMDe9iaJoOnO2+JVAjeRNuRxPZQA6GVvBf+Z3gqUuWYBy2NWh4+5CLYq5uoc3MOvUQ5H5m8CJBqOA==", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/@discordjs/formatters": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.1.tgz", + "integrity": "sha512-M7X4IGiSeh4znwcRGcs+49B5tBkNDn4k5bmhxJDAUhRxRHTiFAOTVUNQ6yAKySu5jZTnCbSvTYHW3w0rAzV1MA==", + "dependencies": { + "discord-api-types": "^0.37.41" + }, "engines": { "node": ">=16.9.0" } }, "node_modules/@discordjs/rest": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.3.0.tgz", - "integrity": "sha512-U6X5J+r/MxYpPTlHFuPxXEf92aKsBaD2teBC7sWkKILIr30O8c9+XshfL7KFBCavnAqS/qE+PF9fgRilO3N44g==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.7.1.tgz", + "integrity": "sha512-Ofa9UqT0U45G/eX86cURQnX7gzOJLG2oC28VhIk/G6IliYgQF7jFByBJEykPSHE4MxPhqCleYvmsrtfKh1nYmQ==", "dependencies": { - "@discordjs/collection": "^1.2.0", - "@discordjs/util": "^0.1.0", + "@discordjs/collection": "^1.5.1", + "@discordjs/util": "^0.3.0", "@sapphire/async-queue": "^1.5.0", - "@sapphire/snowflake": "^3.2.2", - "discord-api-types": "^0.37.12", - "file-type": "^18.0.0", - "tslib": "^2.4.0", - "undici": "^5.11.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" }, "engines": { "node": ">=16.9.0" } }, "node_modules/@discordjs/util": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.1.0.tgz", - "integrity": "sha512-e7d+PaTLVQav6rOc2tojh2y6FE8S7REkqLldq1XF4soCx74XB/DIjbVbVLtBemf0nLW77ntz0v+o5DytKwFNLQ==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.3.1.tgz", + "integrity": "sha512-HxXKYKg7vohx2/OupUN/4Sd02Ev3PBJ5q0gtjdcvXb0ErCva8jNHWfe/v5sU3UKjIB/uxOhc+TDOnhqffj9pRA==", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/@discordjs/ws": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-0.8.3.tgz", + "integrity": "sha512-hcYtppanjHecbdNyCKQNH2I4RP9UrphDgmRgLYrATEQF1oo4sYSve7ZmGsBEXSzH72MO2tBPdWSThunbxUVk0g==", + "dependencies": { + "@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" + }, "engines": { "node": ">=16.9.0" } }, + "node_modules/@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, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@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 + }, + "node_modules/@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, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@noble/hashes": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", - "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", "funding": [ { "type": "individual", @@ -1150,9 +1278,9 @@ ] }, "node_modules/@noble/secp256k1": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.0.tgz", - "integrity": "sha512-kbacwGSsH/CTout0ZnZWxnW1B+jH/7r/WAAKLBtrRJ/+CUH7lgmQzl3GTrQua3SGKWNSDsS6lmjnDpIJ5Dxyaw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", "funding": [ { "type": "individual", @@ -1161,26 +1289,26 @@ ] }, "node_modules/@polkadot/api": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-9.10.5.tgz", - "integrity": "sha512-nCtQX9+ZNSEN8Cn09ylZs8ckwHfB+ofbf+opW3JeRFm1K5AScH1Hx6jP9YpTa+ii9sDEXzMdUSN90JBYLtzW7w==", - "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/api-augment": "9.10.5", - "@polkadot/api-base": "9.10.5", - "@polkadot/api-derive": "9.10.5", - "@polkadot/keyring": "^10.2.1", - "@polkadot/rpc-augment": "9.10.5", - "@polkadot/rpc-core": "9.10.5", - "@polkadot/rpc-provider": "9.10.5", - "@polkadot/types": "9.10.5", - "@polkadot/types-augment": "9.10.5", - "@polkadot/types-codec": "9.10.5", - "@polkadot/types-create": "9.10.5", - "@polkadot/types-known": "9.10.5", - "@polkadot/util": "^10.2.1", - "@polkadot/util-crypto": "^10.2.1", - "eventemitter3": "^4.0.7", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-9.14.2.tgz", + "integrity": "sha512-R3eYFj2JgY1zRb+OCYQxNlJXCs2FA+AU4uIEiVcXnVLmR3M55tkRNEwYAZmiFxx0pQmegGgPMc33q7TWGdw24A==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@polkadot/api-augment": "9.14.2", + "@polkadot/api-base": "9.14.2", + "@polkadot/api-derive": "9.14.2", + "@polkadot/keyring": "^10.4.2", + "@polkadot/rpc-augment": "9.14.2", + "@polkadot/rpc-core": "9.14.2", + "@polkadot/rpc-provider": "9.14.2", + "@polkadot/types": "9.14.2", + "@polkadot/types-augment": "9.14.2", + "@polkadot/types-codec": "9.14.2", + "@polkadot/types-create": "9.14.2", + "@polkadot/types-known": "9.14.2", + "@polkadot/util": "^10.4.2", + "@polkadot/util-crypto": "^10.4.2", + "eventemitter3": "^5.0.0", "rxjs": "^7.8.0" }, "engines": { @@ -1188,31 +1316,31 @@ } }, "node_modules/@polkadot/api-augment": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-9.10.5.tgz", - "integrity": "sha512-6uCjnprSTCG90limSiuMToBRalDfiPp2CeZM/tY7HxHBnv5n+I4WpPyr2RhuYyLJdJTHXhNw90YiMIR7V/0yBw==", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-9.14.2.tgz", + "integrity": "sha512-19MmW8AHEcLkdcUIo3LLk0eCQgREWqNSxkUyOeWn7UiNMY1AhDOOwMStUBNCvrIDK6VL6GGc1sY7rkPCLMuKSw==", "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/api-base": "9.10.5", - "@polkadot/rpc-augment": "9.10.5", - "@polkadot/types": "9.10.5", - "@polkadot/types-augment": "9.10.5", - "@polkadot/types-codec": "9.10.5", - "@polkadot/util": "^10.2.1" + "@babel/runtime": "^7.20.13", + "@polkadot/api-base": "9.14.2", + "@polkadot/rpc-augment": "9.14.2", + "@polkadot/types": "9.14.2", + "@polkadot/types-augment": "9.14.2", + "@polkadot/types-codec": "9.14.2", + "@polkadot/util": "^10.4.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/api-base": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-9.10.5.tgz", - "integrity": "sha512-UGNt/Qq9xwpQR2HbM5qLLH/F2J22lzNtzjhFkXofnohZxgVEERpgtX3kw07tdQZNgAGL7E0lhMGJjvg6M+YQdw==", - "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/rpc-core": "9.10.5", - "@polkadot/types": "9.10.5", - "@polkadot/util": "^10.2.1", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-9.14.2.tgz", + "integrity": "sha512-ky9fmzG1Tnrjr/SBZ0aBB21l0TFr+CIyQenQczoUyVgiuxVaI/2Bp6R2SFrHhG28P+PW2/RcYhn2oIAR2Z2fZQ==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@polkadot/rpc-core": "9.14.2", + "@polkadot/types": "9.14.2", + "@polkadot/util": "^10.4.2", "rxjs": "^7.8.0" }, "engines": { @@ -1220,19 +1348,19 @@ } }, "node_modules/@polkadot/api-derive": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-9.10.5.tgz", - "integrity": "sha512-2I4D1icij36UsPbWs+jrVnBKVsKqdIe7bynrTD9Wg+abHNkqt7wJOianiSbFqq8P9zXcruwpnuXzGljgwqzbGw==", - "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/api": "9.10.5", - "@polkadot/api-augment": "9.10.5", - "@polkadot/api-base": "9.10.5", - "@polkadot/rpc-core": "9.10.5", - "@polkadot/types": "9.10.5", - "@polkadot/types-codec": "9.10.5", - "@polkadot/util": "^10.2.1", - "@polkadot/util-crypto": "^10.2.1", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-9.14.2.tgz", + "integrity": "sha512-yw9OXucmeggmFqBTMgza0uZwhNjPxS7MaT7lSCUIRKckl1GejdV+qMhL3XFxPFeYzXwzFpdPG11zWf+qJlalqw==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@polkadot/api": "9.14.2", + "@polkadot/api-augment": "9.14.2", + "@polkadot/api-base": "9.14.2", + "@polkadot/rpc-core": "9.14.2", + "@polkadot/types": "9.14.2", + "@polkadot/types-codec": "9.14.2", + "@polkadot/util": "^10.4.2", + "@polkadot/util-crypto": "^10.4.2", "rxjs": "^7.8.0" }, "engines": { @@ -1240,60 +1368,60 @@ } }, "node_modules/@polkadot/keyring": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-10.2.2.tgz", - "integrity": "sha512-bgteLizHfcmsOm22Mu442N3dWt/7IzrLXK26EFRNe3kCa2p90sPqTrkTxAHshxmfjljSLP2EIaP7f9GpesiiWQ==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-10.4.2.tgz", + "integrity": "sha512-7iHhJuXaHrRTG6cJDbZE9G+c1ts1dujp0qbO4RfAPmT7YUvphHvAtCKueN9UKPz5+TYDL+rP/jDEaSKU8jl/qQ==", "dependencies": { - "@babel/runtime": "^7.20.7", - "@polkadot/util": "10.2.2", - "@polkadot/util-crypto": "10.2.2" + "@babel/runtime": "^7.20.13", + "@polkadot/util": "10.4.2", + "@polkadot/util-crypto": "10.4.2" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "@polkadot/util": "10.2.2", - "@polkadot/util-crypto": "10.2.2" + "@polkadot/util": "10.4.2", + "@polkadot/util-crypto": "10.4.2" } }, "node_modules/@polkadot/networks": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-10.2.2.tgz", - "integrity": "sha512-BH6iiH2VnNtVbmce3BKYOjeYmKtfMj8opeBnDMSKvuRlw+SXOeFi8zprngBzwPUKybQDQzdT6w06Uy9KbsGDpQ==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-10.4.2.tgz", + "integrity": "sha512-FAh/znrEvWBiA/LbcT5GXHsCFUl//y9KqxLghSr/CreAmAergiJNT0MVUezC7Y36nkATgmsr4ylFwIxhVtuuCw==", "dependencies": { - "@babel/runtime": "^7.20.7", - "@polkadot/util": "10.2.2", - "@substrate/ss58-registry": "^1.36.0" + "@babel/runtime": "^7.20.13", + "@polkadot/util": "10.4.2", + "@substrate/ss58-registry": "^1.38.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/rpc-augment": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-9.10.5.tgz", - "integrity": "sha512-ip6jH7XcyvAwd6EUlbHFHglmNt42h0890lKDaDMIKIsC+U2HDNnMHvW16xH0cOGV98LdGiRltHLtCnl7u+EFZg==", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-9.14.2.tgz", + "integrity": "sha512-mOubRm3qbKZTbP9H01XRrfTk7k5it9WyzaWAg72DJBQBYdgPUUkGSgpPD/Srkk5/5GAQTWVWL1I2UIBKJ4TJjQ==", "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/rpc-core": "9.10.5", - "@polkadot/types": "9.10.5", - "@polkadot/types-codec": "9.10.5", - "@polkadot/util": "^10.2.1" + "@babel/runtime": "^7.20.13", + "@polkadot/rpc-core": "9.14.2", + "@polkadot/types": "9.14.2", + "@polkadot/types-codec": "9.14.2", + "@polkadot/util": "^10.4.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/rpc-core": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-9.10.5.tgz", - "integrity": "sha512-HcsQDOw3+vChhp7KcOxsQKod5O8BUISjbGSuHuBKtDCc75MPVr250UTtgi5cvJ3q7OFrYfDM3i0rqIPSa/zykQ==", - "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/rpc-augment": "9.10.5", - "@polkadot/rpc-provider": "9.10.5", - "@polkadot/types": "9.10.5", - "@polkadot/util": "^10.2.1", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-9.14.2.tgz", + "integrity": "sha512-krA/mtQ5t9nUQEsEVC1sjkttLuzN6z6gyJxK2IlpMS3S5ncy/R6w4FOpy+Q0H18Dn83JBo0p7ZtY7Y6XkK48Kw==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@polkadot/rpc-augment": "9.14.2", + "@polkadot/rpc-provider": "9.14.2", + "@polkadot/types": "9.14.2", + "@polkadot/util": "^10.4.2", "rxjs": "^7.8.0" }, "engines": { @@ -1301,40 +1429,42 @@ } }, "node_modules/@polkadot/rpc-provider": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-9.10.5.tgz", - "integrity": "sha512-R9J9JXx3J//cSVKqQKSTC3HPCv14ZyONVdjiHWLsZymX6okb1ORnhms8JeRMRD4h4FnLePOuKsE9IwEmOUiIUg==", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-9.14.2.tgz", + "integrity": "sha512-YTSywjD5PF01V47Ru5tln2LlpUwJiSOdz6rlJXPpMaY53hUp7+xMU01FVAQ1bllSBNisSD1Msv/mYHq84Oai2g==", "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/keyring": "^10.2.1", - "@polkadot/types": "9.10.5", - "@polkadot/types-support": "9.10.5", - "@polkadot/util": "^10.2.1", - "@polkadot/util-crypto": "^10.2.1", - "@polkadot/x-fetch": "^10.2.1", - "@polkadot/x-global": "^10.2.1", - "@polkadot/x-ws": "^10.2.1", - "@substrate/connect": "0.7.18", - "eventemitter3": "^4.0.7", - "mock-socket": "^9.1.5", - "nock": "^13.2.9" + "@babel/runtime": "^7.20.13", + "@polkadot/keyring": "^10.4.2", + "@polkadot/types": "9.14.2", + "@polkadot/types-support": "9.14.2", + "@polkadot/util": "^10.4.2", + "@polkadot/util-crypto": "^10.4.2", + "@polkadot/x-fetch": "^10.4.2", + "@polkadot/x-global": "^10.4.2", + "@polkadot/x-ws": "^10.4.2", + "eventemitter3": "^5.0.0", + "mock-socket": "^9.2.1", + "nock": "^13.3.0" }, "engines": { "node": ">=14.0.0" + }, + "optionalDependencies": { + "@substrate/connect": "0.7.19" } }, "node_modules/@polkadot/types": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-9.10.5.tgz", - "integrity": "sha512-+NR+mnLl8bcyDTAHUDm1RH3tm7pCeWQKmg6ihLlPzbihyCoCcLxlL5t9ZkRm+3Q9nVhdC4UEIu1befcZ4jncMA==", - "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/keyring": "^10.2.1", - "@polkadot/types-augment": "9.10.5", - "@polkadot/types-codec": "9.10.5", - "@polkadot/types-create": "9.10.5", - "@polkadot/util": "^10.2.1", - "@polkadot/util-crypto": "^10.2.1", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-9.14.2.tgz", + "integrity": "sha512-hGLddTiJbvowhhUZJ3k+olmmBc1KAjWIQxujIUIYASih8FQ3/YJDKxaofGOzh0VygOKW3jxQBN2VZPofyDP9KQ==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@polkadot/keyring": "^10.4.2", + "@polkadot/types-augment": "9.14.2", + "@polkadot/types-codec": "9.14.2", + "@polkadot/types-create": "9.14.2", + "@polkadot/util": "^10.4.2", + "@polkadot/util-crypto": "^10.4.2", "rxjs": "^7.8.0" }, "engines": { @@ -1342,83 +1472,83 @@ } }, "node_modules/@polkadot/types-augment": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-9.10.5.tgz", - "integrity": "sha512-kuJtsadIal4O/BDAMCkf3z+m+BDTRawMkxvHoN/NUiHZcQhtXhSx5xe6X3SwYSv8YCTLYqNXQzak0YBb0v0p1w==", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-9.14.2.tgz", + "integrity": "sha512-WO9d7RJufUeY3iFgt2Wz762kOu1tjEiGBR5TT4AHtpEchVHUeosVTrN9eycC+BhleqYu52CocKz6u3qCT/jKLg==", "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/types": "9.10.5", - "@polkadot/types-codec": "9.10.5", - "@polkadot/util": "^10.2.1" + "@babel/runtime": "^7.20.13", + "@polkadot/types": "9.14.2", + "@polkadot/types-codec": "9.14.2", + "@polkadot/util": "^10.4.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/types-codec": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-9.10.5.tgz", - "integrity": "sha512-+RUgF1MzPNlQ3Sk61+b2kK9NasXS9NNLxgMwjs/iHaFkK9XjRUcM3qN2UlWkFcqMaUkTnuIrc8lT2wJlHYfR7g==", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-9.14.2.tgz", + "integrity": "sha512-AJ4XF7W1no4PENLBRU955V6gDxJw0h++EN3YoDgThozZ0sj3OxyFupKgNBZcZb2V23H8JxQozzIad8k+nJbO1w==", "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/util": "^10.2.1", - "@polkadot/x-bigint": "^10.2.1" + "@babel/runtime": "^7.20.13", + "@polkadot/util": "^10.4.2", + "@polkadot/x-bigint": "^10.4.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/types-create": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-9.10.5.tgz", - "integrity": "sha512-A7n4XG3gE1+d6YAfSq4CDJ1HSd1zvoiPCOY7snxlnpKJCbOHLHq2tWerWtZDvp9IduHS/lXcnywxlhOZLuSQXg==", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-9.14.2.tgz", + "integrity": "sha512-nSnKpBierlmGBQT8r6/SHf6uamBIzk4WmdMsAsR4uJKJF1PtbIqx2W5PY91xWSiMSNMzjkbCppHkwaDAMwLGaw==", "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/types-codec": "9.10.5", - "@polkadot/util": "^10.2.1" + "@babel/runtime": "^7.20.13", + "@polkadot/types-codec": "9.14.2", + "@polkadot/util": "^10.4.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/types-known": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-9.10.5.tgz", - "integrity": "sha512-FHNvwEIGAFRVaqWXOSLWlaXlDk23Ug+yfQ0IPucLvQLFEvSQtE7VK2+RKxgT3gXHodX7xh0yBTBBJBV7MWplRg==", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-9.14.2.tgz", + "integrity": "sha512-iM8WOCgguzJ3TLMqlm4K1gKQEwWm2zxEKT1HZZ1irs/lAbBk9MquDWDvebryiw3XsLB8xgrp3RTIBn2Q4FjB2A==", "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/networks": "^10.2.1", - "@polkadot/types": "9.10.5", - "@polkadot/types-codec": "9.10.5", - "@polkadot/types-create": "9.10.5", - "@polkadot/util": "^10.2.1" + "@babel/runtime": "^7.20.13", + "@polkadot/networks": "^10.4.2", + "@polkadot/types": "9.14.2", + "@polkadot/types-codec": "9.14.2", + "@polkadot/types-create": "9.14.2", + "@polkadot/util": "^10.4.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/types-support": { - "version": "9.10.5", - "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-9.10.5.tgz", - "integrity": "sha512-o5wIkWqNV0QsPMrZ0uKM2K2hJ4IP9KhFQzoU+97lE2Yb3TDUCA6XWP9VqyobYjaxXd9DmPdSjzqb2hzhMwunbw==", + "version": "9.14.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-9.14.2.tgz", + "integrity": "sha512-VWCOPgXDK3XtXT7wMLyIWeNDZxUbNcw/8Pn6n6vMogs7o/n4h6WGbGMeTIQhPWyn831/RmkVs5+2DUC+2LlOhw==", "dependencies": { - "@babel/runtime": "^7.20.6", - "@polkadot/util": "^10.2.1" + "@babel/runtime": "^7.20.13", + "@polkadot/util": "^10.4.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/util": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-10.2.2.tgz", - "integrity": "sha512-P4i5toXqp1NSkbPy74jGIGyIyQ/EvdOj57mywf0319yLrZfXPJ0lfWc0+H5LXuCYkII75Spf0Z4qlDsyBNpHcw==", - "dependencies": { - "@babel/runtime": "^7.20.7", - "@polkadot/x-bigint": "10.2.2", - "@polkadot/x-global": "10.2.2", - "@polkadot/x-textdecoder": "10.2.2", - "@polkadot/x-textencoder": "10.2.2", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-10.4.2.tgz", + "integrity": "sha512-0r5MGICYiaCdWnx+7Axlpvzisy/bi1wZGXgCSw5+ZTyPTOqvsYRqM2X879yxvMsGfibxzWqNzaiVjToz1jvUaA==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@polkadot/x-bigint": "10.4.2", + "@polkadot/x-global": "10.4.2", + "@polkadot/x-textdecoder": "10.4.2", + "@polkadot/x-textencoder": "10.4.2", "@types/bn.js": "^5.1.1", "bn.js": "^5.2.1" }, @@ -1427,18 +1557,18 @@ } }, "node_modules/@polkadot/util-crypto": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-10.2.2.tgz", - "integrity": "sha512-RqUwIZZ6f4ckKIy6IP41g07WRccDs+X9y6cI+CXAfYkuXcAR5HHtuXHhlRd5LVjHidYiSmisZTd6toz5tAl7qQ==", - "dependencies": { - "@babel/runtime": "^7.20.7", - "@noble/hashes": "1.1.5", - "@noble/secp256k1": "1.7.0", - "@polkadot/networks": "10.2.2", - "@polkadot/util": "10.2.2", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-10.4.2.tgz", + "integrity": "sha512-RxZvF7C4+EF3fzQv8hZOLrYCBq5+wA+2LWv98nECkroChY3C2ZZvyWDqn8+aonNULt4dCVTWDZM0QIY6y4LUAQ==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@polkadot/networks": "10.4.2", + "@polkadot/util": "10.4.2", "@polkadot/wasm-crypto": "^6.4.1", - "@polkadot/x-bigint": "10.2.2", - "@polkadot/x-randomvalues": "10.2.2", + "@polkadot/x-bigint": "10.4.2", + "@polkadot/x-randomvalues": "10.4.2", "@scure/base": "1.1.1", "ed2curve": "^0.3.0", "tweetnacl": "^1.0.3" @@ -1447,7 +1577,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "@polkadot/util": "10.2.2" + "@polkadot/util": "10.4.2" } }, "node_modules/@polkadot/util-crypto/node_modules/tweetnacl": { @@ -1552,24 +1682,24 @@ } }, "node_modules/@polkadot/x-bigint": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-10.2.2.tgz", - "integrity": "sha512-hSY2t32PgEtp5CBsoM2BVapGvibp2SJsPLiFMxmBt2hW37q145sryr62vkdnEoi76n1ef022W7HRWk3xshdRTQ==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-10.4.2.tgz", + "integrity": "sha512-awRiox+/XSReLzimAU94fPldowiwnnMUkQJe8AebYhNocAj6SJU00GNoj6j6tAho6yleOwrTJXZaWFBaQVJQNg==", "dependencies": { - "@babel/runtime": "^7.20.7", - "@polkadot/x-global": "10.2.2" + "@babel/runtime": "^7.20.13", + "@polkadot/x-global": "10.4.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/x-fetch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-10.2.2.tgz", - "integrity": "sha512-x1TtCyzV2V2FGuHwRb56uBdpwr6Q5EJhwJVxY2B4NcHPd+pjQY5NGMwiYQ7/r2Rnlm/sLjlOwIfHU5+mv6sWBA==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-10.4.2.tgz", + "integrity": "sha512-Ubb64yaM4qwhogNP+4mZ3ibRghEg5UuCYRMNaCFoPgNAY8tQXuDKrHzeks3+frlmeH9YRd89o8wXLtWouwZIcw==", "dependencies": { - "@babel/runtime": "^7.20.7", - "@polkadot/x-global": "10.2.2", + "@babel/runtime": "^7.20.13", + "@polkadot/x-global": "10.4.2", "@types/node-fetch": "^2.6.2", "node-fetch": "^3.3.0" }, @@ -1578,59 +1708,59 @@ } }, "node_modules/@polkadot/x-global": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-10.2.2.tgz", - "integrity": "sha512-xSwEEDGkJS4C+5qOnm/tGo7NM23O+MGip+Cuu3/QFqcWRkvUGQcA/YulixcXPw+vNtOz6h9BSnCSIwsGXIWV3w==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-10.4.2.tgz", + "integrity": "sha512-g6GXHD/ykZvHap3M6wh19dO70Zm43l4jEhlxf5LtTo5/0/UporFCXr2YJYZqfbn9JbQwl1AU+NroYio+vtJdiA==", "dependencies": { - "@babel/runtime": "^7.20.7" + "@babel/runtime": "^7.20.13" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/x-randomvalues": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-10.2.2.tgz", - "integrity": "sha512-CC7FpEkcqfa07BdsUYCCNR0Y7UylxtsHzytwl/u/9JYwF1+EvVuiUGdSQPiCK9oBE6tES0mE2Grr8N4/MCBHIg==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-10.4.2.tgz", + "integrity": "sha512-mf1Wbpe7pRZHO0V3V89isPLqZOy5XGX2bCqsfUWHgb1NvV1MMx5TjVjdaYyNlGTiOkAmJKlOHshcfPU2sYWpNg==", "dependencies": { - "@babel/runtime": "^7.20.7", - "@polkadot/x-global": "10.2.2" + "@babel/runtime": "^7.20.13", + "@polkadot/x-global": "10.4.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/x-textdecoder": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-10.2.2.tgz", - "integrity": "sha512-tmQS8qv5y2dYULjkTilpLu2CNQhRFu3CZb7yUDu/QmQaK4uhlqR7DXMTxHawW+hL75ZSKdmzjpY8jnCCexg8Hw==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-10.4.2.tgz", + "integrity": "sha512-d3ADduOKUTU+cliz839+KCFmi23pxTlabH7qh7Vs1GZQvXOELWdqFOqakdiAjtMn68n1KVF4O14Y+OUm7gp/zA==", "dependencies": { - "@babel/runtime": "^7.20.7", - "@polkadot/x-global": "10.2.2" + "@babel/runtime": "^7.20.13", + "@polkadot/x-global": "10.4.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/x-textencoder": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-10.2.2.tgz", - "integrity": "sha512-NfdbQFWiAm1FX+vcpgGwT7YpxxJ7dRFsB0IFuPh5sUXftVYo9tewNLnxCw5UsCNMN8BEqvJG/FSVeuFtg2Aa0Q==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-10.4.2.tgz", + "integrity": "sha512-mxcQuA1exnyv74Kasl5vxBq01QwckG088lYjc3KwmND6+pPrW2OWagbxFX5VFoDLDAE+UJtnUHsjdWyOTDhpQA==", "dependencies": { - "@babel/runtime": "^7.20.7", - "@polkadot/x-global": "10.2.2" + "@babel/runtime": "^7.20.13", + "@polkadot/x-global": "10.4.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/x-ws": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-10.2.2.tgz", - "integrity": "sha512-elwKDtYQrHf7ozFb+pJvDHWsKb8Fauk0mQX0QTHkD68szFgUz501wMW6xNPnYiXqPvhP9qTf34TlLNCkbMuyyQ==", + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-10.4.2.tgz", + "integrity": "sha512-3gHSTXAWQu1EMcMVTF5QDKHhEHzKxhAArweEyDXE7VsgKUP/ixxw4hVZBrkX122iI5l5mjSiooRSnp/Zl3xqDQ==", "dependencies": { - "@babel/runtime": "^7.20.7", - "@polkadot/x-global": "10.2.2", + "@babel/runtime": "^7.20.13", + "@polkadot/x-global": "10.4.2", "@types/websocket": "^1.0.5", "websocket": "^1.0.34" }, @@ -1648,12 +1778,12 @@ } }, "node_modules/@sapphire/shapeshift": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.7.0.tgz", - "integrity": "sha512-A6vI1zJoxhjWo4grsxpBRBgk96SqSdjLX5WlzKp9H+bJbkM07mvwcbtbVAmUZHbi/OG3HLfiZ1rlw4BhH6tsBQ==", + "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.uniqwith": "^4.5.0" + "lodash": "^4.17.21" }, "engines": { "node": ">=v14.0.0", @@ -1661,9 +1791,9 @@ } }, "node_modules/@sapphire/snowflake": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.2.2.tgz", - "integrity": "sha512-ula2O0kpSZtX9rKXNeQMrHwNd7E4jPDJYUXmEGTFdMRfyfMw+FPyh04oKMjAiDuOi64bYgVkOV3MjK+loImFhQ==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz", + "integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" @@ -1680,10 +1810,36 @@ } ] }, + "node_modules/@smithy/protocol-http": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-1.0.1.tgz", + "integrity": "sha512-9OrEn0WfOVtBNYJUjUAn9AOiJ4lzERCJJ/JeZs8E6yajTGxBaFRxUnNBHiNqoDJVg076hY36UmEnPx7xXrvUSg==", + "optional": true, + "dependencies": { + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.0.0.tgz", + "integrity": "sha512-kc1m5wPBHQCTixwuaOh9vnak/iJm21DrSf9UK6yDE5S3mQQ4u11pqAUiKWnlrZnYkeLfAI9UEHj9OaMT1v5Umg==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@substrate/connect": { - "version": "0.7.18", - "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.7.18.tgz", - "integrity": "sha512-T1CaZJhe+uaeyM/cBdmD/oMWnaGf+tJdfG+3Os4H5YR0NVKXWsHpSfBryBP5wEce2hQhRiNnzQ+9ny8siKqRgg==", + "version": "0.7.19", + "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.7.19.tgz", + "integrity": "sha512-+DDRadc466gCmDU71sHrYOt1HcI2Cbhm7zdCFjZfFVHXhC/E8tOdrVSglAH2HDEHR0x2SiHRxtxOGC7ak2Zjog==", + "optional": true, "dependencies": { "@substrate/connect-extension-protocol": "^1.0.1", "@substrate/smoldot-light": "0.7.9", @@ -1693,27 +1849,59 @@ "node_modules/@substrate/connect-extension-protocol": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-1.0.1.tgz", - "integrity": "sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg==" + "integrity": "sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg==", + "optional": true + }, + "node_modules/@substrate/connect/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "optional": true }, "node_modules/@substrate/smoldot-light": { "version": "0.7.9", "resolved": "https://registry.npmjs.org/@substrate/smoldot-light/-/smoldot-light-0.7.9.tgz", "integrity": "sha512-HP8iP7sFYlpSgjjbo0lqHyU+gu9lL2hbDNce6dWk5/10mFFF9jKIFGfui4zCecUY808o/Go9pan/31kMJoLbug==", + "optional": true, "dependencies": { "pako": "^2.0.4", "ws": "^8.8.1" } }, "node_modules/@substrate/ss58-registry": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.36.0.tgz", - "integrity": "sha512-YfQIpe2bIvGg/XWNByycznbOiAknMvpYaUpQJ2sLmNT/OwPx7XjEXk7dLShccuiQDoOQt3trTtF3Frz/Tjv6Fg==" + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.40.0.tgz", + "integrity": "sha512-QuU2nBql3J4KCnOWtWDw4n1K4JU0T79j54ZZvm/9nhsX6AIar13FyhsaBfs6QkJ2ixTQAnd7TocJIoJRWbqMZA==" }, "node_modules/@tokenizer/token": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@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 + }, + "node_modules/@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 + }, + "node_modules/@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 + }, "node_modules/@types/bn.js": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", @@ -1722,15 +1910,31 @@ "@types/node": "*" } }, + "node_modules/@types/cron": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/cron/-/cron-2.0.1.tgz", + "integrity": "sha512-WHa/1rtNtD2Q/H0+YTTZoty+/5rcE66iAFX2IY+JuUoOACsevYyFkSYu/2vdw+G5LrmO7Lxowrqm0av4k3qWNQ==", + "dev": true, + "dependencies": { + "@types/luxon": "*", + "@types/node": "*" + } + }, + "node_modules/@types/luxon": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.0.tgz", + "integrity": "sha512-uKRI5QORDnrGFYgcdAVnHvEIvEZ8noTpP/Bg+HeUzZghwinDlIS87DEenV5r1YoOF9G4x600YsUXLWZ19rmTmg==", + "dev": true + }, "node_modules/@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", + "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==" }, "node_modules/@types/node-fetch": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", - "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", + "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", "dependencies": { "@types/node": "*", "form-data": "^3.0.0" @@ -1772,75 +1976,63 @@ } }, "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", + "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", "dependencies": { "@types/node": "*" } }, + "node_modules/@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==", + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@xxnetwork/types": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@xxnetwork/types/-/types-1.0.4.tgz", "integrity": "sha512-nEYV5SSUHZ1N3Rj8uS+zHd1IW3x94YBHebnljGzkGmf3farLpm7+iJtdaicB9Xb66wfE3cbpiJ5MrnfQQSaLUg==", + "dev": true, "dependencies": { "@polkadot/api": "^9.10.3" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "node_modules/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, + "bin": { + "acorn": "bin/acorn" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" + "engines": { + "node": ">=0.4.0" } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "node_modules/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, "engines": { - "node": ">=0.8" + "node": ">=0.4.0" } }, - "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1868,14 +2060,6 @@ "node": ">=6.0.0" } }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -1933,11 +2117,6 @@ "node": ">=10.16.0" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1950,17 +2129,41 @@ } }, "node_modules/commander": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", + "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", + "peer": true, "engines": { - "node": "^12.20.0 || >=14" + "node": ">=16" } }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + "node_modules/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 + }, + "node_modules/cron": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/cron/-/cron-2.3.1.tgz", + "integrity": "sha512-1eRRlIT0UfIqauwbG9pkg3J6CX9A6My2ytJWqAXoK0T9oJnUZTzGBNPxao0zjodIbPgf8UQWjE62BMb9eVllSQ==", + "dependencies": { + "luxon": "^3.2.1" + } + }, + "node_modules/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, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } }, "node_modules/d": { "version": "1.0.1", @@ -1971,21 +2174,10 @@ "type": "^1.0.1" } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/data-uri-to-buffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", - "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", + "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" } @@ -2022,28 +2214,39 @@ "node": ">=0.10" } }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/discord-api-types": { - "version": "0.37.18", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.18.tgz", - "integrity": "sha512-mJ+9C8gmG5csssVZPH06Y8IGiJykljFyZc6n6F+T3vKo6yNBI5TtLIbwt6t9hJzsR5f1ITzRZ6cuPrTvRCUxqA==" + "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==" }, "node_modules/discord.js": { - "version": "14.6.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.6.0.tgz", - "integrity": "sha512-On1K7xpJZRe0KsziIaDih2ksYPhgxym/ZqV45i1f3yig4vUotikqs7qp5oXiTzQ/UTiNRCixUWFTh7vA1YBCqw==", - "dependencies": { - "@discordjs/builders": "^1.3.0", - "@discordjs/collection": "^1.2.0", - "@discordjs/rest": "^1.3.0", - "@discordjs/util": "^0.1.0", - "@sapphire/snowflake": "^3.2.2", - "@types/ws": "^8.5.3", - "discord-api-types": "^0.37.12", + "version": "14.11.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.11.0.tgz", + "integrity": "sha512-CkueWYFQ28U38YPR8HgsBR/QT35oPpMbEsTNM30Fs8loBIhnA4s70AwQEoy6JvLcpWWJO7GY0y2BUzZmuBMepQ==", + "dependencies": { + "@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.4.0", - "undici": "^5.11.0", - "ws": "^8.9.0" + "tslib": "^2.5.0", + "undici": "^5.22.0", + "ws": "^8.13.0" }, "engines": { "node": ">=16.9.0" @@ -2067,15 +2270,6 @@ "node": ">=12" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/ed2curve": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/ed2curve/-/ed2curve-0.3.0.tgz", @@ -2089,6 +2283,31 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" }, + "node_modules/env-cmd": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-10.1.0.tgz", + "integrity": "sha512-mMdWTT9XKN7yNth/6N6g2GuKuJTsKMDHlQFUDacb/heQRRWOTIZ42t1rMHnQu4jYxU1ajdTeJM+9eEETlqToMA==", + "dev": true, + "dependencies": { + "commander": "^4.0.0", + "cross-spawn": "^7.0.0" + }, + "bin": { + "env-cmd": "bin/env-cmd.js" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/env-cmd/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/es5-ext": { "version": "0.10.62", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", @@ -2123,9 +2342,9 @@ } }, "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, "node_modules/ext": { "version": "1.7.0", @@ -2140,43 +2359,31 @@ "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ] - }, "node_modules/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==" }, - "node_modules/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==" - }, "node_modules/fast-xml-parser": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.11.tgz", - "integrity": "sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.4.tgz", + "integrity": "sha512-fbfMDvgBNIdDJLdLOwacjFAPYt67tr31H9ZhWSm45CDAxvd0I6WTlSOUo7K2P/K5sA5JgMKG64PI3DMcaFdWpQ==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], "optional": true, "dependencies": { "strnum": "^1.0.5" }, "bin": { "fxparser": "src/cli/cli.js" - }, - "funding": { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } }, "node_modules/fetch-blob": { @@ -2202,9 +2409,9 @@ } }, "node_modules/file-type": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.0.0.tgz", - "integrity": "sha512-jjMwFpnW8PKofLE/4ohlhqwDk5k0NC6iy0UHAJFKoY1fQeGMN0GDdLgHQrvCbSpMwbqzoCZhRI5dETCZna5qVA==", + "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", @@ -2217,27 +2424,6 @@ "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -2249,49 +2435,6 @@ "node": ">=12.20.0" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -2326,45 +2469,17 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "node_modules/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==" + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -2375,10 +2490,19 @@ "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" }, - "node_modules/lodash.uniqwith": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniqwith/-/lodash.uniqwith-4.5.0.tgz", - "integrity": "sha512-7lYL8bLopMoy4CTICbxygAUq6CdRJ36vFc80DucPueUee+d5NBRxz3FdT9Pes/HEx5mPoT9jwnsEJWz1N7uq7Q==" + "node_modules/luxon": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz", + "integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/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 }, "node_modules/memory-pager": { "version": "1.5.0", @@ -2406,9 +2530,9 @@ } }, "node_modules/mock-socket": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.1.5.tgz", - "integrity": "sha512-3DeNIcsQixWHHKk6NdoBhWI4t1VMj5/HzfnI1rE/pLl5qKx7+gd4DNA07ehTaZ6MoUU053si6Hd+YtiM/tQZfg==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.2.1.tgz", + "integrity": "sha512-aw9F9T9G2zpGipLLhSNh6ZpgUyUl4frcVmRN08uE1NWPWg43Wx6+sGPDbQ7E5iFZZDJW5b5bypMeAEHqTbIFag==", "engines": { "node": ">= 8" } @@ -2470,9 +2594,9 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, "node_modules/nock": { - "version": "13.2.9", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.9.tgz", - "integrity": "sha512-1+XfJNYF1cjGB+TKMWi29eZ0b82QOvQs2YoLNzbpWGqFMtRQHTa57osqdGj4FrFPgkO4D4AZinzUJR9VvW3QUA==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.1.tgz", + "integrity": "sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw==", "dependencies": { "debug": "^4.1.0", "json-stringify-safe": "^5.0.1", @@ -2502,9 +2626,9 @@ } }, "node_modules/node-fetch": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz", - "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", + "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -2528,18 +2652,20 @@ "node-gyp-build-test": "build-test.js" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, "node_modules/pako": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "optional": true + }, + "node_modules/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, + "engines": { + "node": ">=8" + } }, "node_modules/peek-readable": { "version": "5.0.0", @@ -2553,11 +2679,6 @@ "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, "node_modules/propagate": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", @@ -2566,11 +2687,6 @@ "node": ">= 8" } }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -2579,18 +2695,10 @@ "node": ">=6" } }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -2620,41 +2728,10 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dependencies": { "tslib": "^2.1.0" } @@ -2678,11 +2755,6 @@ } ] }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, "node_modules/saslprep": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", @@ -2695,6 +2767,27 @@ "node": ">=6" } }, + "node_modules/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, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "engines": { + "node": ">=8" + } + }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -2726,30 +2819,6 @@ "memory-pager": "^1.0.2" } }, - "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -2804,18 +2873,6 @@ "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/tr46": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", @@ -2828,30 +2885,57 @@ } }, "node_modules/ts-mixer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.2.tgz", - "integrity": "sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A==" - }, - "node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", + "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, "dependencies": { - "safe-buffer": "^5.0.1" + "@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" }, - "engines": { - "node": "*" + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + "node_modules/tslib": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", + "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" }, "node_modules/type": { "version": "1.2.0", @@ -2866,23 +2950,28 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/undici": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.12.0.tgz", - "integrity": "sha512-zMLamCG62PGjd9HHMpo05bSLvvwWOZgGeiWlN/vlqu3+lRo3elxktVGEyLMX+IO7c2eflLjcW74AlkhEZm15mg==", - "dependencies": { - "busboy": "^1.6.0" + "node_modules/typescript": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", + "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=12.18" + "node": ">=14.17" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/undici": { + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", + "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", "dependencies": { - "punycode": "^2.1.0" + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=14.0" } }, "node_modules/utf-8-validate": { @@ -2902,27 +2991,11 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true }, "node_modules/web-streams-polyfill": { "version": "3.2.1", @@ -2981,16 +3054,31 @@ "node": ">=12" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -3008,6 +3096,15 @@ "engines": { "node": ">=0.10.32" } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } } } } diff --git a/package.json b/package.json new file mode 100644 index 0000000..83010f3 --- /dev/null +++ b/package.json @@ -0,0 +1,36 @@ +{ + "name": "discord-xx-monitor-bot", + "version": "2.0.0", + "type": "module", + "description": "", + "main": "built/index.js", + "scripts": { + "start": "node built/index.js", + "build": "tsc --build", + "clean": "tsc --build --clean", + "dev": "NODE_ENV=development bash -c 'env-cmd npm run build && npm run start'" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@commander-js/extra-typings": "^11.0.0", + "@polkadot/api": "^9.14.2", + "base64url": "^3.0.1", + "cron": "^2.3.1", + "discord.js": "^14.11.0", + "moment": "^2.29.4", + "mongodb": "^4.11.0" + }, + "devDependencies": { + "@polkadot/types": "^9.14.2", + "@types/cron": "^2.0.1", + "@types/node": "^20.3.1", + "@xxnetwork/types": "^1.0.4", + "dotenv": "^16.0.3", + "dotenv-expand": "^9.0.0", + "env-cmd": "^10.1.0", + "ts-node": "^10.9.1", + "typescript": "^5.1.3" + } +} diff --git a/bot/res/xx_logo_color.png b/res/xx_logo_color.png similarity index 100% rename from bot/res/xx_logo_color.png rename to res/xx_logo_color.png diff --git a/bot/res/xx_logo_color.svg b/res/xx_logo_color.svg similarity index 100% rename from bot/res/xx_logo_color.svg rename to res/xx_logo_color.svg diff --git a/src/@types/discord.d.ts b/src/@types/discord.d.ts new file mode 100644 index 0000000..a1298b7 --- /dev/null +++ b/src/@types/discord.d.ts @@ -0,0 +1,9 @@ +import { Collection } from "discord.js"; + +// from https://stackoverflow.com/questions/69500556/discord-js-guide-property-commands-does-not-exist-on-type-clientboolean + +declare module "discord.js" { + export interface Client { + commands: Collection; + } +} \ No newline at end of file diff --git a/src/bot-utils.ts b/src/bot-utils.ts new file mode 100755 index 0000000..4b1fa70 --- /dev/null +++ b/src/bot-utils.ts @@ -0,0 +1,169 @@ +// Script from https://discordjs.guide/creating-your-bot/command-deployment.html#command-registration, modified +import { Command, Option, Argument } from "@commander-js/extra-typings"; +import { REST, Routes, Client, GatewayIntentBits, Events } from "discord.js"; +import { DiscordClient } from "./discord/types.js"; +import fs from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// manually expand the environmental variables +var dotenv = (await import("dotenv")).config({ path: ".env" }); +var dotenvExpand = await import("dotenv-expand"); +dotenvExpand.expand(dotenv); + +// Discord token & application id are required. +if (!process.env.DISCORD_TOKEN) { + throw new Error("DISCORD_TOKEN environment variable missing."); +} +if (!process.env.APP_ID) { + throw new Error("APP_ID environment variable missing."); +} +if (!process.env.DEV_GUILD_ID) { + throw new Error("DEV_GUILD_ID environment variable missing."); +} + +const clientId = process.env.APP_ID; +const token = process.env.DISCORD_TOKEN; + +// client commands +async function init_client(): Promise { + const client = new Client({ + intents: [GatewayIntentBits.Guilds], + }) as DiscordClient; + client.once(Events.ClientReady, (...args) => { + console.log(`Ready! Logged in as ${client.user!.tag}`); + }); + + await client.login(process.env.DISCORD_TOKEN); + return client; +} + +// deploy commands +async function deploy(guildId?: string) { + const rest = new REST({ version: "10" }).setToken(token); + + const commands = new Array(); + // Grab all the command files from the commands directory + const commandsPath = join(__dirname, "discord", "commands"); + const commandFiles = fs + .readdirSync(commandsPath) + .filter((file) => file.endsWith(".js")); + + // Grab the SlashCommandBuilder#toJSON() output of each command's data for deployment + for (const file of commandFiles) { + const filePath = join(commandsPath, file); + const command = await import(filePath); + if ("data" in command && "execute" in command) { + commands.push(command.data.toJSON()); + } else { + console.log( + `[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.` + ); + } + } + + console.log( + `Prepared ${commands.length} application (/) commands for deployment.` + ); + + (async () => { + try { + // Deploying commands + const route = guildId + ? Routes.applicationGuildCommands(clientId, guildId) + : Routes.applicationCommands(clientId); + const data = await rest.put(route, { body: commands }) as any; + + console.log( + `Successfully reloaded ${data.length} application (/) commands.` + ); + } catch (error) { + // And of course, make sure you catch and log any errors! + console.error(error); + } + })(); +} + +// command parsing +const program = new Command(); + +program + .name("bot-utils") + .description("Utilities to deploy the xx monitor bot to discord servers"); + +program + .command("deploy") + .description("Deploy commands to server(s)") + .addOption( + new Option("--server ", "Deploy to the given server id").default( + process.env.DEV_GUILD_ID, + "env DEV_GUILD_ID" + ) + ) + .addOption( + new Option( + "--global", + "Deploy to all bot-joined servers - this will duplicate guild-issued commands! see https://stackoverflow.com/a/70167704/1486966" + ).conflicts(["server", "reset"]) + ) + .addOption( + new Option( + "--reset", + "Resets the global and guild commands if you have deployed to both" + ) + ) + .action(async (options) => { + if (options.reset) { + // reset the commands in server and globally; see https://stackoverflow.com/a/70167704/1486966 + console.log("Resetting commands..."); + const client = await init_client(); + console.log( + "Resetting commands globally (may take ~1 hour to update)..." + ); + client.application!.commands.set([]); + console.log( + `Resetting commands in server # ${process.env.DEV_GUILD_ID} (takes effect immediately)...` + ); + const guild = client.guilds.cache.get(process.env.DEV_GUILD_ID!); + guild!.commands.set([]); + client.destroy(); + } else if (options.global) { + // deploy commands globally + console.log("Deploying commands globally"); + await deploy(); + } else if (options.server) { + // deploy commands to a single server + console.log(`Deploying commands to server id ${options.server}`); + await deploy(options.server); + } + console.log("Complete"); + }); + +program + .command("username") + .description("Set bot username (rate limited to 2x/hour)") + .addArgument(new Argument("")) + .action(async (username) => { + console.log(`Setting username to ${username}`); + const client = await init_client(); + await client.user!.setUsername(username); + console.log("Complete"); + client.destroy(); + }); + +program + .command("avatar") + .description("Set bot avatar") + .addArgument(new Argument("")) + .action(async (path) => { + console.log(`Setting avatar to ${path}`); + const client = await init_client(); + await client.user!.setAvatar(path); + console.log("Complete"); + client.destroy(); + }); + +program.parse(); diff --git a/src/cmix/index.ts b/src/cmix/index.ts new file mode 100644 index 0000000..6dcde1b --- /dev/null +++ b/src/cmix/index.ts @@ -0,0 +1,75 @@ +import { CronJob } from "cron"; +import { Database } from "../db/index.js"; +import { dmStatusChange } from "../messager.js"; +import { StatusCmix } from "../db/index.js"; +import type { Client } from "discord.js"; +import type { CmixNode } from "./types.js"; +import type { MonitorRecord } from "../db/types.js"; + +// Polls the dashboard API and gets the entire list of nodes every ENDPOINT_POLLING seconds + +const endpoint: string = process.env.ENDPOINT!; +const endpoint_retries = process.env.ENDPOINT_RETRIES; +const cmix_poll_cron: string = process.env.ENDPOINT_CRON!; +const timezone: string = process.env.TZ!; + +export async function startPolling(db: Database, client: Client) { + console.log("*** API Polling Started ***"); + + new CronJob( + cmix_poll_cron, + function () { + poll(db, client); + }, + null, + true, + timezone + ); +} + +async function poll(db: Database, client: Client) { + const response: Response = await fetch(endpoint, { + headers: { accept: "application/json; charset=utf-8" }, + }); + const results = await response.json(); + if (response.status !== 200) { + console.log(`non-200 response:\nresponse: ${response}\nbody: ${results}}`); + } else { + // Process the results + console.log(`parsing ${results.nodes.length} nodes`); + + // step through each node result and send its status to the monitoring db + results.nodes.forEach(async (node: CmixNode) => { + const name: string = node.name; + const status = node.status as keyof typeof StatusCmix; + const status_new: StatusCmix = node.status + ? StatusCmix[status] + : StatusCmix.unknown; // when status is an empty string, status is Status.UNKNOWN + const node_id: string = node.id; + const changed: Date = new Date(); + + // update database with new name, as appropriate + if (node.name) { + db.updateNodeName(node_id, name); + } + + // update database with new status + var result: MonitorRecord[] | undefined = await db.updateNodeStatus( + node.id, + status_new, + changed + ); + + // notify users of status change + if (result) { + console.log( + `notifying ${result.length} users of node ${node_id} status change to ${status_new} at ${changed}` + ); + result.forEach(async (entry) => { + // Send a notification to the user + dmStatusChange(client, entry, status_new); + }); + } + }); + } +} diff --git a/src/cmix/types.ts b/src/cmix/types.ts new file mode 100644 index 0000000..9e661fe --- /dev/null +++ b/src/cmix/types.ts @@ -0,0 +1,27 @@ +export interface CmixNode { + name: string; + url: string; + location: string; + geoBin: string; + gpsLocation: string; + team: string; + network: string; + email: string; + twitter: string; + discord: string; + instagram: string; + medium: string; + other: string; + forum: string; + id: string; + base64url: string; + applicationId: number; + description: string; + uptime: number; + roundFailureAvg: number; + realtimeFailureAvg: number; + precompFailureAvg: number; + status: string; + whois: string; + walletAddress: string; +} diff --git a/src/custom-derives/index.ts b/src/custom-derives/index.ts new file mode 100644 index 0000000..2c3e227 --- /dev/null +++ b/src/custom-derives/index.ts @@ -0,0 +1,19 @@ +// Copyright 2017-2023 @polkadot/apps authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +// from https://github.com/xx-labs/web-wallet/blob/fcdcd4f5ddeeb69c272e4550fde3353ecd0328b7/packages/custom-derives/src/index.ts + +import type { DeriveCustom } from "@polkadot/types/types"; + +import * as stakingOriginal from "@polkadot/api-derive/staking"; + +import * as stakingOverride from "./staking/index.js"; + +const derive: DeriveCustom = { + staking: { + ...stakingOriginal, + ...stakingOverride, + }, +}; + +export default derive; diff --git a/src/custom-derives/staking/index.ts b/src/custom-derives/staking/index.ts new file mode 100644 index 0000000..6fe4f66 --- /dev/null +++ b/src/custom-derives/staking/index.ts @@ -0,0 +1,6 @@ +// Copyright 2017-2023 @polkadot/apps authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +// from https://github.com/xx-labs/web-wallet/blob/fcdcd4f5ddeeb69c272e4550fde3353ecd0328b7/packages/custom-derives/src/staking/index.ts + +export * from "./stakerRewards"; diff --git a/src/custom-derives/staking/stakerRewards.ts b/src/custom-derives/staking/stakerRewards.ts new file mode 100644 index 0000000..508b5f6 --- /dev/null +++ b/src/custom-derives/staking/stakerRewards.ts @@ -0,0 +1,333 @@ +// Copyright 2017-2023 @polkadot/api-derive authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +// from https://github.com/xx-labs/web-wallet/blob/fcdcd4f5ddeeb69c272e4550fde3353ecd0328b7/packages/custom-derives/src/staking/stakerRewards.ts + +import type { Observable } from "rxjs"; +import type { DeriveStakingQuery } from "@polkadot/api-derive/staking/types"; +import type { + DeriveApi, + DeriveEraPoints, + DeriveEraPrefs, + DeriveEraRewards, + DeriveEraValPoints, + DeriveEraValPrefs, + DeriveStakerExposure, + DeriveStakerReward, + DeriveStakerRewardValidator, +} from "@polkadot/api-derive/types"; +import type { AccountId, EraIndex } from "@polkadot/types/interfaces"; +import type { PalletStakingStakingLedger } from "@polkadot/types/lookup"; +import type { BN } from "@polkadot/util"; + +import { combineLatest, map, of, switchMap } from "rxjs"; + +import { firstMemo, memo } from "@polkadot/api-derive/util"; +import { BN_BILLION, BN_ZERO, objectSpread } from "@polkadot/util"; + +type ErasResult = [DeriveEraPoints[], DeriveEraPrefs[], DeriveEraRewards[]]; + +function parseRewards( + api: DeriveApi, + stashId: AccountId, + [erasPoints, erasPrefs, erasRewards]: ErasResult, + exposures: DeriveStakerExposure[] +): DeriveStakerReward[] { + return exposures.map( + ({ + era, + isEmpty, + isValidator, + nominating, + validators: eraValidators, + }): DeriveStakerReward => { + const { eraPoints, validators: allValPoints } = erasPoints.find((p) => + p.era.eq(era) + ) || { eraPoints: BN_ZERO, validators: {} as DeriveEraValPoints }; + const { eraReward } = erasRewards.find((r) => r.era.eq(era)) || { + eraReward: api.registry.createType("Balance"), + }; + const { validators: allValPrefs } = erasPrefs.find((p) => + p.era.eq(era) + ) || { validators: {} as DeriveEraValPrefs }; + const validators: Record = {}; + const stakerId = stashId.toString(); + + Object.entries(eraValidators).forEach(([validatorId, exposure]): void => { + const valPoints = allValPoints[validatorId] || BN_ZERO; + const valComm = + allValPrefs[validatorId]?.commission.unwrap() || BN_ZERO; + const expTotal = + exposure.total?.unwrap().add(exposure.custody?.unwrap()) || BN_ZERO; + let avail = BN_ZERO; + let value: BN | undefined; + + if (!(expTotal.isZero() || valPoints.isZero() || eraPoints.isZero())) { + avail = eraReward.mul(valPoints).div(eraPoints); + + const valCut = valComm.mul(avail).div(BN_BILLION); + let staked: BN; + + if (validatorId === stakerId) { + staked = exposure.own.unwrap(); + } else { + const stakerExp = exposure.others.find(({ who }) => + who.eq(stakerId) + ); + + staked = stakerExp ? stakerExp.value.unwrap() : BN_ZERO; + } + + value = avail + .sub(valCut) + .imul(staked) + .div(expTotal) + .iadd(validatorId === stakerId ? valCut : BN_ZERO); + } + + validators[validatorId] = { + total: api.registry.createType("Balance", avail), + value: api.registry.createType("Balance", value), + }; + }); + + return { + era, + eraReward, + isEmpty, + isValidator, + nominating, + validators, + }; + } + ); +} + +function allUniqValidators( + rewards: DeriveStakerReward[][] +): [string[], string[][]] { + return rewards.reduce( + ([all, perStash]: [string[], string[][]], rewards) => { + const uniq: string[] = []; + + perStash.push(uniq); + rewards.forEach(({ validators }) => + Object.keys(validators).forEach((validatorId): void => { + if (!uniq.includes(validatorId)) { + uniq.push(validatorId); + + if (!all.includes(validatorId)) { + all.push(validatorId); + } + } + }) + ); + + return [all, perStash]; + }, + [[], []] + ); +} + +function removeClaimed( + validators: string[], + queryValidators: DeriveStakingQuery[], + reward: DeriveStakerReward +): void { + const rm: string[] = []; + + Object.keys(reward.validators).forEach((validatorId): void => { + const index = validators.indexOf(validatorId); + + if (index !== -1) { + const valLedger = queryValidators[index].stakingLedger; + + // If a validator is no longer bonded, api.derive.staking.queryMulti returns an "emtpy" StakingLedger + // object instead of undefined. The stash in this is set to 0x0000....., so we can filter those out + if ( + validatorId !== valLedger.stash.toString() || + valLedger?.claimedRewards.some((e) => reward.era.eq(e)) + ) { + rm.push(validatorId); + } + } + }); + + rm.forEach((validatorId): void => { + delete reward.validators[validatorId]; + }); +} + +function filterRewards( + eras: EraIndex[], + valInfo: [string, DeriveStakingQuery][], + { + rewards, + stakingLedger, + }: { + rewards: DeriveStakerReward[]; + stakingLedger: PalletStakingStakingLedger; + } +): DeriveStakerReward[] { + const filter = eras.filter( + (e) => !stakingLedger.claimedRewards.some((s) => s.eq(e)) + ); + const validators = valInfo.map(([v]) => v); + const queryValidators = valInfo.map(([, q]) => q); + + return rewards + .filter(({ isEmpty }) => !isEmpty) + .filter((reward): boolean => { + if (!filter.some((e) => reward.era.eq(e))) { + return false; + } + + removeClaimed(validators, queryValidators, reward); + + return true; + }) + .filter(({ validators }) => Object.keys(validators).length !== 0) + .map((reward) => + objectSpread({}, reward, { + nominators: reward.nominating.filter( + (n) => reward.validators[n.validatorId] + ), + }) + ); +} + +export function _stakerRewardsEras( + instanceId: string, + api: DeriveApi +): (eras: EraIndex[], withActive?: boolean) => Observable { + return memo( + instanceId, + (eras: EraIndex[], withActive = false): Observable => + combineLatest([ + api.derive.staking._erasPoints(eras, withActive), + api.derive.staking._erasPrefs(eras, withActive), + api.derive.staking._erasRewards(eras, withActive), + ]) + ); +} + +export function _stakerRewards( + instanceId: string, + api: DeriveApi +): ( + accountIds: (Uint8Array | string)[], + eras: EraIndex[], + withActive?: boolean +) => Observable { + return memo( + instanceId, + ( + accountIds: (Uint8Array | string)[], + eras: EraIndex[], + withActive = false + ): Observable => + combineLatest([ + api.derive.staking.queryMulti(accountIds, { withLedger: true }), + api.derive.staking._stakerExposures(accountIds, eras, withActive), + api.derive.staking._stakerRewardsEras(eras, withActive), + ]).pipe( + switchMap( + ([queries, exposures, erasResult]): Observable< + DeriveStakerReward[][] + > => { + const allRewards = queries.map( + ({ stakingLedger, stashId }, index): DeriveStakerReward[] => + !stashId || !stakingLedger + ? [] + : parseRewards(api, stashId, erasResult, exposures[index]) + ); + + if (withActive) { + return of(allRewards); + } + + const [allValidators, stashValidators] = + allUniqValidators(allRewards); + + return api.derive.staking + .queryMulti(allValidators, { withLedger: true }) + .pipe( + map((queriedVals): DeriveStakerReward[][] => + queries.map( + ({ stakingLedger }, index): DeriveStakerReward[] => + filterRewards( + eras, + stashValidators[index].map( + (validatorId): [string, DeriveStakingQuery] => [ + validatorId, + queriedVals.find((q) => + q.accountId.eq(validatorId) + ) as DeriveStakingQuery, + ] + ), + { + rewards: allRewards[index], + stakingLedger, + } + ) + ) + ) + ); + } + ) + ) + ); +} + +export const stakerRewards = firstMemo( + (api: DeriveApi, accountId: Uint8Array | string, withActive?: boolean) => + api.derive.staking + .erasHistoric(withActive) + .pipe( + switchMap((eras) => + api.derive.staking._stakerRewards([accountId], eras, withActive) + ) + ) +); + +export function stakerRewardsMultiEras( + instanceId: string, + api: DeriveApi +): ( + accountIds: (Uint8Array | string)[], + eras: EraIndex[] +) => Observable { + return memo( + instanceId, + ( + accountIds: (Uint8Array | string)[], + eras: EraIndex[] + ): Observable => + accountIds.length && eras.length + ? api.derive.staking._stakerRewards(accountIds, eras, false) + : of([]) + ); +} + +export function stakerRewardsMulti( + instanceId: string, + api: DeriveApi +): ( + accountIds: (Uint8Array | string)[], + withActive?: boolean +) => Observable { + return memo( + instanceId, + ( + accountIds: (Uint8Array | string)[], + withActive = false + ): Observable => + api.derive.staking + .erasHistoric(withActive) + .pipe( + switchMap((eras) => + api.derive.staking.stakerRewardsMultiEras(accountIds, eras) + ) + ) + ); +} diff --git a/src/db/index.ts b/src/db/index.ts new file mode 100644 index 0000000..9b4854e --- /dev/null +++ b/src/db/index.ts @@ -0,0 +1,191 @@ +import type { + Document, + Filter, + FindOptions, + InsertOneResult, + UpdateResult, + WithId, + OptionalId, + UpdateFilter, + DeleteResult, + Db, + Collection, +} from "mongodb"; +import type { LogActionRecord, MonitorRecord } from "./types.js"; +import { Status } from "./types.js"; +import { MongoClient } from "mongodb"; + +export { Status, StatusIcon, StatusCmix } from "./types.js"; + +export class Database { + private client: MongoClient; + private db: Db; + private mainnet: Collection; + private stats: Db; + private actions: Collection; + + constructor(client: MongoClient) { + // Initialize mongodb + this.client = client; + this.db = this.client.db("xx"); + this.mainnet = this.db.collection("mainnet"); + this.stats = this.client.db("stats"); + this.actions = this.stats.collection("actions"); + } + + public static async connect(uri: string): Promise { + const client = await MongoClient.connect(uri); + console.log(`Connected to mongo at ${uri}`); + return new Database(client); + } + + public async logAction( + user_id: string, + action: string, + data: string + ): Promise> { + // Add a record for an action taken by a user + + const new_doc: LogActionRecord = { + user: user_id, + time: new Date(), + action: action, + data: data, + }; + const options: FindOptions = {}; + const result: InsertOneResult = await this.actions.insertOne( + new_doc + ); + return result; + } + + public async addNode( + user_id: string, + node_id: string, + node_name: string | null + ): Promise { + // Add a node to the monitered node list + + // check if user is already monitoring this node + const query: Filter = { + user: user_id, + node: node_id, + }; + const options: FindOptions = {}; + const result: WithId | null = await this.mainnet.findOne( + query, + options + ); + if (result) { + // User is already monitoring this node + // check if node name is set and the same + if (node_name && node_name !== result.name) { + // update node name + const update: Partial = { + $set: { + name: node_name, + user_set_name: true, + }, + }; + return await this.mainnet.updateOne(query, update); + } + return false; + } else { + const new_doc: MonitorRecord = { + user: user_id, + node: node_id, + name: node_name, + user_set_name: Boolean(node_name), + status: Status.UNKNOWN, + changed: null, + }; + return await this.mainnet.insertOne(new_doc); + } + } + + public async updateNodeStatus( + node_id: string, + status: string, + changed: Date + ): Promise { + // notify any users monitoring the provided node of a status change + + const query: Filter = { + node: node_id, + status: { + $ne: status, + }, + }; + const options: FindOptions = { + projection: { + _id: false, + }, + }; + const result: WithId[] = await this.mainnet + .find(query, options) + .toArray(); + + if (result.length) { + // update the value in the database + const update: UpdateFilter = { + $set: { + status: status, + changed: changed, + }, + }; + this.mainnet.updateMany(query, update); + + return result as MonitorRecord[]; + } + } + + public async updateNodeName(node_id: string, new_name: string): Promise { + // update all nodes with the new name, where user_set_name = false + + const query: Filter = { + node: node_id, + user_set_name: { + $ne: true, + }, + }; + const update: UpdateFilter = { + $set: { + name: new_name, + user_set_name: false, + }, + }; + return this.mainnet.updateMany(query, update); + } + + public async listUserNodes(user_id: string): Promise[]> { + // Get list of user's subscriptions + + const query: Filter = { + user: user_id, + }; + const options: FindOptions = { + projection: { + _id: false, + }, + }; + return await this.mainnet.find(query, options).toArray(); + } + + public async deleteNode( + user_id: string, + node_id: string + ): Promise<[DeleteResult, WithId[]]> { + // Delete the given node from the user record. + + const query: Filter = { + user: user_id, + node: node_id, + }; + const options: FindOptions = {}; + const deleted: WithId[] = await this.mainnet + .find(query, options) + .toArray(); + const result: DeleteResult = await this.mainnet.deleteMany(query, options); + return [result, deleted]; + } +} diff --git a/src/db/types.ts b/src/db/types.ts new file mode 100644 index 0000000..e1764ca --- /dev/null +++ b/src/db/types.ts @@ -0,0 +1,41 @@ +import type { Document, OptionalId } from "mongodb"; + +export enum Status { + ONLINE = "online", + OFFLINE = "offline", + ERROR = "error", + UNELECTED = "unelected", + UNKNOWN = "unknown", +} + +export enum StatusIcon { + ONLINE = "🟢", + OFFLINE = "🔴", + ERROR = "⛔", + UNELECTED = "⬇️", + UNKNOWN = "❓", +} + +export enum StatusCmix { + "online" = Status.ONLINE, + "offline" = Status.OFFLINE, + "error" = Status.ERROR, + "not currently a validator" = Status.UNELECTED, + "unknown" = Status.UNKNOWN, +} + +export interface MonitorRecord extends OptionalId { + user: string; // discord_id + node: string; // node_id + name: string | null; // node_name + user_set_name: boolean; // true if user set the name, false otherwise + status: string; // based on status object below, + changed: Date | null; // timestamp of last state change, +} + +export interface LogActionRecord extends OptionalId { + user: string; // discord_id + time: Date; // timestamp + action: string; // usually the command name + data: string; // data for action +} diff --git a/src/discord/commands/list_monitored_nodes.ts b/src/discord/commands/list_monitored_nodes.ts new file mode 100644 index 0000000..d911a97 --- /dev/null +++ b/src/discord/commands/list_monitored_nodes.ts @@ -0,0 +1,222 @@ +import { + SlashCommandBuilder, + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + MessageFlags, + BaseInteraction, +} from "discord.js"; +import type { + ChatInputCommandInteraction, + BaseGuildTextChannel, +} from "discord.js"; +import moment from "moment"; +import base64url from "base64url"; +import { prettifyNode, Icons } from "../../utils.js"; +import { Database, Status, StatusIcon } from "../../db/index.js"; +import type { DeleteResult, Document, WithId } from "mongodb"; + +function buildResponseButtons( + db: Database, + nodes: WithId[], + unmonitor_buttons: boolean = true +) { + let rows = new Array>(); + const MAX_BUTTON_TEXT_LEN = 80; // 80 is value from exception thrown when string is too long + + nodes.forEach((node) => { + const row = new ActionRowBuilder(); // let's build on this puppy + + // node status - disabled (just used to show node id) + const button_style = + node.status === Status.UNKNOWN + ? ButtonStyle.Secondary + : node.status === Status.ONLINE + ? ButtonStyle.Success + : ButtonStyle.Danger; + row.addComponents( + new ButtonBuilder() + .setCustomId(`${node.node}-status`) + .setDisabled(true) + .setLabel((node.status as string).toUpperCase()) + .setStyle(button_style) + ); + + // node id button - disabled + row.addComponents( + new ButtonBuilder() + .setCustomId(`${node.node}-text`) + .setDisabled(true) + .setLabel( + prettifyNode(node.name, node.node, false, MAX_BUTTON_TEXT_LEN) + ) + .setStyle(ButtonStyle.Primary) + ); + + // unmonitor button + if (unmonitor_buttons) { + row.addComponents( + new ButtonBuilder() + .setCustomId(node.node) + .setLabel("Unmonitor") + .setStyle(ButtonStyle.Danger) + ); + } + + // dashboard link + const url = `${process.env.DASHBOARD_URL}/${base64url.fromBase64( + node.node + )}`; + row.addComponents( + new ButtonBuilder() + .setURL(url) + .setLabel("Dashboard") + .setStyle(ButtonStyle.Link) + ); + + rows.push(row); + }); + + return rows; +} + +function buildResponseText(db: Database, nodes: WithId[]) { + let reply_string = ""; + + // Print a list of nodes + nodes.forEach((node) => { + const url = `${process.env.DASHBOARD_URL}/${base64url.fromBase64( + node.node + )}`; + const changed = node.changed + ? ` since ${moment(node.changed).fromNow()}` + : ""; + const status: keyof typeof Status = node.status + ? node.status.toUpperCase() + : Status.UNKNOWN.toUpperCase(); // edge case for empty string status in the database + + let line = StatusIcon[status].toString(); // node status icon + line += ` ${prettifyNode(node.name, node.node)}`; // node name & id + line += ` _(${status}${changed})_`; // status text & time since change + line += ` [${Icons.LINK}](${url})`; // link to dashboard page for node + + reply_string += line + "\n"; + }); + + return reply_string; +} + +async function buildResponse( + db: Database, + user_id: string, + fancy: boolean = true, + unmonitor_buttons: boolean = true +) { + // Get a list of user's monitored nodes + const nodes = await db.listUserNodes(user_id); + + // User isn't monitoring any nodes + if (nodes.length <= 0) { + return { + text: `${Icons.ERROR} You aren't monitoring any nodes.`, + components: [], + }; + } + + const reply_string = `You are monitoring ${nodes.length} node${ + nodes.length > 1 ? "s" : "" + }:\n`; + + // User is monitoring 1-5 nodes AND the fancy flag is set - show buttons + if (nodes.length > 0 && nodes.length <= 5 && fancy) { + return { + text: reply_string, + components: buildResponseButtons(db, nodes, unmonitor_buttons), + }; + } + // Build a codeblock if we have results > 5 or fancy flag is unset + else { + return { + text: `${reply_string}${buildResponseText(db, nodes)}`, + components: [], + }; + } +} + +export const data = new SlashCommandBuilder() + .setName("list_monitored_nodes") + .setDescription("Display a list of validators that you are monitoring") + .addStringOption((option) => + option + .setName("format") + .setDescription( + "Choose the format of the validator list. Default is Text." + ) + .addChoices( + { name: "Text", value: "text" }, + { name: "Buttons", value: "buttons" } + ) + ); + +export async function execute( + interaction: ChatInputCommandInteraction, + db: Database +) { + const user = interaction.user; + const format = interaction.options.getString("format"); + const fancy = format == "buttons" ? true : false; + const channel = ( + interaction.channel + ? interaction.channel + : await interaction.client.channels.fetch(interaction.channelId) + ) as BaseGuildTextChannel; + const eph = channel ? (!channel.isDMBased() ? true : false) : false; // make the message ephemeral / visible only to user if not in dm + + let { text, components } = await buildResponse(db, user.id, fancy); // build fancy list (if plain not set by user) + await interaction.reply({ + content: text, + components: components, + ephemeral: eph, + flags: MessageFlags.SuppressEmbeds, + }); + + // if we have button components, make sure we have the right callback + if (components.length) { + // button event handling - https://discordjs.guide/interactions/buttons.html#updating-the-button-message + + const filter = (i: BaseInteraction) => i.user.id === user.id; + const collector = channel.createMessageComponentCollector({ + filter, + time: 45000, + dispose: true, + }); + + collector.on("collect", async (i) => { + // if button was clicked, delete it from user and update message + const [result, deleted]: [DeleteResult, WithId[]] = + await db.deleteNode(user.id, i.customId); + if (deleted.length) { + // Deleted node successfully + let reply_string = `${ + Icons.DELETE + } You are no longer monitoring ${prettifyNode( + deleted[0].name, + i.customId + )}.`; + let { text, components } = await buildResponse(db, user.id); + await i.update({ content: text, components: components }); + await interaction.followUp({ content: reply_string, ephemeral: eph }); + } + }); + + collector.on("end", async () => { + // Disable the unmonitor buttons because we're done listening for them + let { text, components } = await buildResponse(db, user.id, true, false); + await interaction.editReply({ content: text, components: components }); + }); + } + + console.log( + `User ${user.id} interaction from ${eph ? "channel" : "dm"}: listed nodes` + ); +} diff --git a/src/discord/commands/monitor_node.ts b/src/discord/commands/monitor_node.ts new file mode 100644 index 0000000..494e966 --- /dev/null +++ b/src/discord/commands/monitor_node.ts @@ -0,0 +1,107 @@ +import { SlashCommandBuilder, DiscordAPIError } from "discord.js"; +import type { + AutocompleteInteraction, + ChatInputCommandInteraction, +} from "discord.js"; +import { prettifyNode, Icons } from "../../utils.js"; +import type { Database } from "../../db/index.js"; + +export const data = new SlashCommandBuilder() + .setName("monitor_node") + .setDescription("Register a new validator node to monitor") + .addStringOption((option) => + option + .setName("id") + .setDescription("The Node ID to monitor") + .setRequired(true) + .setMaxLength(44) + .setMinLength(44) + .setAutocomplete(true) + ) + .addStringOption((option) => + option.setName("name").setDescription("A friendly name for the node") + ); + +export async function execute( + interaction: ChatInputCommandInteraction, + db: Database +) { + const node_id = interaction.options.getString("id", true); + const node_name = interaction.options.getString("name", false); + const user = interaction.user; + const channel = interaction.channel + ? interaction.channel + : await interaction.client.channels.fetch(interaction.channelId); + const eph = channel ? (!channel.isDMBased() ? true : false) : false; // make the message ephemeral / visible only to user if not in dm + let reply_string = ``; + + const status = await db.addNode(user.id, node_id, node_name); // returns false if the user is already monitoring this node/name combination + + if (status) { + // Successfully added or updated node + + if ("modifiedCount" in status) { + // result was a record update + reply_string = `${Icons.SUCCESS} Updated \`${node_id}\` name to \`${node_name}\`.`; + } else { + // result was a new record + const monitoring = `${Icons.WATCH} Monitoring ${prettifyNode( + node_name, + node_id + )}. Reporting changes `; + + try { + // if this interaction is from a channel, verify their dms are open by sending one + if (eph) { + await user.send(monitoring + "here."); + } + } catch (err) { + // when the bot can't send a dm, an exception is thrown + if (err instanceof DiscordAPIError) { + console.log(err); + + // delete the db entry + await db.deleteNode(user.id, node_id); + + reply_string = `${Icons.ERROR} Error: I cannot send you a Direct Message. Please resolve that and try again.`; + } else throw err; // this is some other kind of error, pass it on + } + + reply_string = monitoring + (eph ? "in your DMs." : "here"); + } + } else { + // User is already monitoring this node + reply_string = `${ + Icons.ERROR + } Error: You are already monitoring ${prettifyNode(node_name, node_id)}.`; + } + + await interaction.reply({ content: reply_string, ephemeral: eph }); + console.log( + `User ${user.id} interaction from ${ + eph ? "channel" : "dm" + }: monitor ${node_id}: ${reply_string}` + ); +} + +export async function autocomplete( + interaction: AutocompleteInteraction, + db: Database +) { + const user = interaction.user; + const focusedValue = interaction.options.getFocused(); + + // Get list of nodes monitored from db + const monitored_nodes = await db.listUserNodes(user.id); + const choices = monitored_nodes.map((entry) => ({ + id: entry.node, + text: `${prettifyNode(entry.name, entry.node, false)}`, + })); + const filtered = choices.filter((choice) => + choice.text.toLowerCase().includes(focusedValue.toLowerCase()) + ); + + await interaction.respond( + filtered.map((choice) => ({ name: choice.id, value: choice.id })) // setting name: choice.text should work, but it doesn't. Asked on SO: https://stackoverflow.com/q/74532512/1486966 + ); +} diff --git a/src/discord/commands/unmonitor_node.ts b/src/discord/commands/unmonitor_node.ts new file mode 100644 index 0000000..2341134 --- /dev/null +++ b/src/discord/commands/unmonitor_node.ts @@ -0,0 +1,78 @@ +import { SlashCommandBuilder } from "discord.js"; +import type { + AutocompleteInteraction, + ChatInputCommandInteraction, +} from "discord.js"; +import { prettifyNode, Icons, XX_ID_LEN } from "../../utils.js"; +import type { Database } from "../../db/index.js"; +import type { Document, DeleteResult, WithId } from "mongodb"; + +export const data = new SlashCommandBuilder() + .setName("unmonitor_node") + .setDescription("Stop monitoring a validator") + .addStringOption((option) => + option + .setName("id") + .setDescription("The Node ID to stop monitoring") + .setRequired(true) + .setMaxLength(XX_ID_LEN) + .setMinLength(XX_ID_LEN) + .setAutocomplete(true) + ); + +export async function execute( + interaction: ChatInputCommandInteraction, + db: Database +) { + const node_id = interaction.options.getString("id", true); + const user = interaction.user; + const channel = interaction.channel + ? interaction.channel + : await interaction.client.channels.fetch(interaction.channelId); + const eph = channel ? (!channel.isDMBased() ? true : false) : false; // make the message ephemeral / visible only to user if not in dm + let reply_string = ""; + + // Get list of users subscriptions + const [result, deleted]: [DeleteResult, WithId[]] = + await db.deleteNode(user.id, node_id); + if (deleted.length) { + // Deleted node successfully + reply_string = `${ + Icons.DELETE + } You are no longer monitoring ${prettifyNode(deleted[0].name, node_id)}.`; + } else { + // Node wasn't monitored + reply_string = `${ + Icons.ERROR + } Error: You are not monitoring ${prettifyNode(null, node_id)}.`; + } + + await interaction.reply({ content: reply_string, ephemeral: eph }); + console.log( + `User ${user.id} interaction from ${ + eph ? "channel" : "dm" + }: unmonitor ${node_id}: ${reply_string}` + ); +} + +export async function autocomplete( + interaction: AutocompleteInteraction, + db: Database +) { + const user = interaction.user; + const focusedValue = interaction.options.getFocused(); + + // Get list of nodes monitored from db + const monitored_nodes = await db.listUserNodes(user.id); + const choices = monitored_nodes.map((entry) => ({ + id: entry.node, + text: `${prettifyNode(entry.name, entry.node, false, XX_ID_LEN)}`, + })); + const filtered = choices.filter((choice) => + choice.text.toLowerCase().includes(focusedValue.toLowerCase()) + ); + + await interaction.respond( + filtered.map((choice) => ({ name: choice.id, value: choice.id })) // setting name: choice.text should work, but it doesn't. Asked on SO: https://stackoverflow.com/q/74532512/1486966 + ); +} diff --git a/src/discord/events/interactionCreate.ts b/src/discord/events/interactionCreate.ts new file mode 100644 index 0000000..3680ba9 --- /dev/null +++ b/src/discord/events/interactionCreate.ts @@ -0,0 +1,40 @@ +import { Events } from "discord.js"; +import type { CommandInteraction } from "discord.js"; +import type { Database } from "../../db/index.js"; +import type { DiscordClient } from "../types.js"; + +export const name = Events.InteractionCreate; + +export async function execute(interaction: CommandInteraction, db: Database) { + const command = (interaction.client as DiscordClient).commands.get( + interaction.commandName + ); + + if (!command) { + console.error(`No command matching ${interaction.commandName} was found.`); + return; + } + + try { + // fetch the channel if it isn't cached (dms are not usually cached) + if (!interaction.channel) { + await interaction.client.channels.fetch(interaction.channelId); + } + + if (interaction.isChatInputCommand()) { + // log action in db + const user_id = interaction.user.id; + await db.logAction( + user_id, + interaction.commandName, + interaction.options.data.toString() + ); + await command.execute(interaction, db); + } else if (interaction.isAutocomplete()) { + await command.autocomplete(interaction, db); + } + } catch (error) { + console.error(`Error executing ${interaction.commandName}`); + console.error(error); + } +} diff --git a/src/discord/events/ready.ts b/src/discord/events/ready.ts new file mode 100644 index 0000000..4ce9fa7 --- /dev/null +++ b/src/discord/events/ready.ts @@ -0,0 +1,28 @@ +import { Events, ActivityType } from "discord.js"; +import { startPolling } from "../../cmix/index.js"; +import type { Database } from "../../db/index.js"; +import type { DiscordClient } from "../types.js"; + +export const name = Events.ClientReady; +export const once = true; + +export function execute(client: DiscordClient, db: Database) { + console.log(`Ready! Logged in as ${client.user!.tag}`); + + // configure client with info from env + // Set bot username + if (process.env.BOT_USERNAME) { + client.user!.setUsername(process.env.BOT_USERNAME); + } + + // Set bot status + if (process.env.BOT_STATUS) { + client.user!.setActivity(process.env.BOT_STATUS, { + type: ActivityType.Listening, + }); + } + + // start cmix poller + startPolling(db, client); + +} diff --git a/src/discord/index.ts b/src/discord/index.ts new file mode 100644 index 0000000..79bd941 --- /dev/null +++ b/src/discord/index.ts @@ -0,0 +1,57 @@ +import fs from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { Client, Collection, GatewayIntentBits } from "discord.js"; +import type { Database } from "../db/index.js"; +import type { DiscordClient } from "./types.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +export async function initDiscord(db: Database, token: string): Promise { + // Create a new client instance + const client = new Client({ + intents: [GatewayIntentBits.Guilds], + }) as DiscordClient; + + // Commands initialization - from https://discordjs.guide/creating-your-bot/command-handling.html#loading-command-files + client.commands = new Collection(); + + const commandsPath = join(__dirname, "commands"); + const commandFiles = fs + .readdirSync(commandsPath) + .filter((file) => file.endsWith(".js")); + + // Build collection of available commands from the commands directory + for (const file of commandFiles) { + const filePath = join(commandsPath, file); + const command = await import(filePath); + // Set a new item in the Collection with the key as the command name and the value as the exported module + if ("data" in command && "execute" in command) { + client.commands.set(command.data.name, command); + } else { + console.log( + `[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.` + ); + } + } + + // Events initialization - from https://discordjs.guide/creating-your-bot/event-handling.html#individual-event-files + const eventsPath = join(__dirname, "events"); + const eventFiles = fs + .readdirSync(eventsPath) + .filter((file) => file.endsWith(".js")); + + for (const file of eventFiles) { + const filePath = join(eventsPath, file); + const event = await import(filePath); + if (event.once) { + client.once(event.name, (...args) => event.execute(...args, db)); + } else { + client.on(event.name, (...args) => event.execute(...args, db)); + } + } + + // Log in to Discord with your client's token + client.login(token); +} diff --git a/src/discord/types.ts b/src/discord/types.ts new file mode 100644 index 0000000..72166b1 --- /dev/null +++ b/src/discord/types.ts @@ -0,0 +1,5 @@ +import { Client, Collection } from "discord.js"; + +export interface DiscordClient extends Client { + commands: Collection; +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..f9294e2 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,34 @@ +import { Database } from "./db/index.js"; +import { initDiscord } from "./discord/index.js"; + +var env = process.env.NODE_ENV || "development"; + +console.log(`NODE_ENV: ${env}`); +console.log(`NODE_EXTRA_CA_CERTS: ${process.env.NODE_EXTRA_CA_CERTS}`); + +// If in development, load & expand variables manually +if (env === "development") { + var dotenv = (await import("dotenv")).config({ path: ".env" }); + var dotenvExpand = await import("dotenv-expand"); + dotenvExpand.expand(dotenv); + + console.log(dotenv); + + console.log(`NODE_EXTRA_CA_CERTS: ${process.env.NODE_EXTRA_CA_CERTS}`); + + // set mongodb uri to localhost + process.env.MONGO_URI = `mongodb://${process.env.MONGO_INITDB_ROOT_USERNAME}:${process.env.MONGO_INITDB_ROOT_PASSWORD}@localhost:${process.env.MONGO_PORT}/`; +} + +// initialize database +const db: Database = await Database.connect(process.env.MONGO_URI!); + +// start discord.js +initDiscord(db, process.env.DISCORD_TOKEN!); + +// client.js: loads all the event handlers for discord +// once discord.js client is ready, magic starts in events/ready.js +// +// events/ready.js: fires off the poller that downloads the current nodes list, +// compares it to the database of monitored nodes, and sends dms when +// node status changes have happened. diff --git a/src/messager.ts b/src/messager.ts new file mode 100644 index 0000000..5b7273d --- /dev/null +++ b/src/messager.ts @@ -0,0 +1,23 @@ +import { Status, StatusIcon } from "./db/index.js"; +import type { MonitorRecord } from "./db/types.js"; +import { prettifyNode, Icons } from "./utils.js"; +import type { Client } from "discord.js"; + +export async function sendDM(client: Client, user_id: string, message: string) { + client.users.fetch(user_id).then((dm) => { + dm.send(message); + }); +} + +export async function dmStatusChange( + client: Client, + node: MonitorRecord, + status_new: string +) { + const status = status_new.toUpperCase() as keyof typeof Status; + var message = StatusIcon[status] + ` ${Icons.TRANSIT} ` + StatusIcon[status]; // old -> new status icon + message += ` ${prettifyNode(node.name, node.node)} `; // pretty node name + message += `is now ${status_new == Status.ERROR ? "in " : ""}${status}`; // new status + + sendDM(client, node.user, message); +} diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..4e42990 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,40 @@ +import { inlineCode } from "discord.js"; + +// truncate a string to set length, using ellipsis in the center +function truncate(text: string, length: number = 44): string { + length = length < 5 ? 5 : length; // do not truncate anything shorter than 5 characters + const trunc = + text.length > length + ? `${text.substring(0, Math.ceil(length / 2) - 1)}…${text.substring( + text.length - Math.floor(length / 2) + )}` + : text; + return trunc; +} + +// take a pretty name and an id and combine; if no name provided, just return id +export function prettifyNode( + name: string | null, + id: string, + codify: boolean = true, + maxlen: number = 44 +) { + if (!name) return codify ? inlineCode(id) : id; // just return id if no name is given + const MAX_LEN = maxlen - 3; // arbitrary, can be increased + const MAX_NAME_LEN = Math.ceil(MAX_LEN / 2); // name shouldn't be much longer than half the max length + const name_new = truncate(name, MAX_NAME_LEN); + const MAX_ID_LEN = MAX_LEN - name_new.length; // id takes up the rest of the space + const pretty = `${name_new} / ${truncate(id, MAX_ID_LEN)}`; + return codify ? inlineCode(pretty) : pretty; +} + +export enum Icons { + WATCH = "👀", + ERROR = "💢", + SUCCESS = "🙌", + DELETE = "🗑️", + TRANSIT = "➜", + LINK = "🔗", +} + +export const XX_ID_LEN = 44; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..90ed821 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,104 @@ +{ + "include": ["./src/**/*"], + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "esnext", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + "typeRoots": ["src/@types", "node_modules/@types"], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./built", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +}