diff --git a/.cspell/custom-dictionary-workspace.txt b/.cspell/custom-dictionary-workspace.txt index f5e0cc5..b862e6b 100644 --- a/.cspell/custom-dictionary-workspace.txt +++ b/.cspell/custom-dictionary-workspace.txt @@ -1,13 +1,15 @@ # Custom Dictionary Words Controlpanel cooldown +Cooldowns cpgg +ctrlpanel dagen discordjs Följande +Gåva gett Globalt -Gåva hoster inom inställningar @@ -33,5 +35,6 @@ Språkkod upsert uuidv Vermium +voca xyter Zyner diff --git a/.env.example b/.env.example index 9367980..f841aaa 100644 --- a/.env.example +++ b/.env.example @@ -1,12 +1,27 @@ # Do not use "around your text" ("") +# Timezone +TZ=Europe/Stockholm + +# Do not touch unless you know what you doing +PUID=1000 +PGID=1000 + # Discord DISCORD_TOKEN= DISCORD_CLIENT_ID= DISCORD_GUILD_ID= # Database -DATABASE_URL=mysql://username:password@mariadb:3306/database +MYSQL_ROOT_PASSWORD=root + +MYSQL_HOST=localhost +MYSQL_USER=username +MYSQL_PASSWORD=password +MYSQL_DATABASE=database + +# DO NOT TOUCH UNLESS YOU KNOW WHAT YOU ARE DOING +DATABASE_URL=mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@${MYSQL_HOST}/${MYSQL_DATABASE} # Encryption ENCRYPTION_ALGORITHM=aes-256-ctr @@ -27,4 +42,4 @@ REPUTATION_TIMEOUT=86400 # Bot Hoster BOT_HOSTER_NAME=Zyner -BOT_HOSTER_URL=https://xyter.zyner.org/customization/change-hoster \ No newline at end of file +BOT_HOSTER_URL=https://xyter.zyner.org/customization/change-hoster diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml deleted file mode 100644 index 1bfb931..0000000 --- a/.github/workflows/docker-image.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Docker Image CI - -on: - schedule: - - cron: "0 10 * * *" - push: - branches: - - "**" - tags: - - "v*.*.*" - pull_request: - branches: - - "**" - -jobs: - docker: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Docker meta - id: meta - uses: docker/metadata-action@v4 - with: - # list of Docker images to use as base name for tags - images: | - zyner/xyter - # generate Docker tags based on the following events/attributes - tags: | - type=schedule - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Login to Container registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and push - uses: docker/build-push-action@v3 - with: - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - platforms: linux/amd64 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 83a6465..137692c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,13 +1,13 @@ -# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions - -name: Node.js CI +name: CI on: push: - branches: [main, next] + branches: [main, next, dev] + tags: + - "v*" pull_request: - branches: [main, next] + branches: [main, next, dev] + workflow_dispatch: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -17,10 +17,82 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 with: - node-version: 19 - - run: npm ci - - run: npm run build --if-present - - run: npx semantic-release + node-version: 20 + + - name: Cache Node.js dependencies + uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + + - name: Install dependencies + run: npm ci + + - name: Build TypeScript source code + run: npm run build + + - name: Semantic Release + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npx semantic-release + + docker: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + # list of Docker images to use as base name for tags + images: | + zyner/xyter + # generate Docker tags based on the following events/attributes + tags: | + type=schedule + type=ref,event=branch + type=ref,event=pr + type=raw,value=latest,enable={{is_default_branch}} + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: 20 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to Docker Hub + if: github.event_name != 'pull_request' + run: docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to Container registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v3 + with: + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64 diff --git a/.gitignore b/.gitignore index 748aac2..ee90336 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,9 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +# NixOS +.direnv + +# Docker +docker-compose.override.yml diff --git a/.releaserc b/.releaserc index 5c4168a..90c204b 100644 --- a/.releaserc +++ b/.releaserc @@ -1,18 +1,20 @@ { - "branches": [ - "main", - { - "name": "next", - "prerelease": true - } - ], - "debug": true, - "ci": true, - "dryRun": false, - "plugins": [ - "@semantic-release/commit-analyzer", - "@semantic-release/npm", - "@semantic-release/git", - "@semantic-release/github" - ] + "branches": [ + "main", + { + "name": "next", + "prerelease": true + } + ], + "debug": true, + "ci": true, + "dryRun": false, + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/npm", + "@semantic-release/changelog", + "@semantic-release/git", + "@semantic-release/github" + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index e9ea9d9..3d3d927 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ { "editor.bracketPairColorization.enabled": true, "editor.cursorBlinking": "phase", - "editor.cursorSmoothCaretAnimation": true, + "editor.cursorSmoothCaretAnimation": "on", "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.fontLigatures": true, "editor.formatOnSave": true, @@ -10,7 +10,7 @@ "editor.minimap.renderCharacters": false, "editor.minimap.showSlider": "always", "editor.tabSize": 2, - "git.enableCommitSigning": true, + // "git.enableCommitSigning": true, "editor.wordWrapColumn": 100, "files.eol": "\n", "files.trimTrailingWhitespace": true, @@ -36,5 +36,8 @@ "conventionalCommits.scopes": ["git", "github", "prisma"], "[dockerfile]": { "editor.defaultFormatter": "foxundermoon.shell-format" + }, + "[sql]": { + "editor.defaultFormatter": "sqlfluff.vscode-sqlfluff" } } diff --git a/Dockerfile b/Dockerfile index 487ea90..52a5f39 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,36 @@ -FROM node:19-alpine3.16 AS builder +# Dependencies +FROM node:19-alpine3.17 AS dependencies -# Create app directory WORKDIR /app - -# A wildcard is used to ensure both package.json AND package-lock.json are copied -COPY package*.json ./ -COPY prisma ./prisma/ - -# Install app dependencies +COPY package.json package-lock.json ./ RUN npm install +# Build +FROM node:19-alpine3.17 AS build + +WORKDIR /app +COPY --from=dependencies /app/node_modules ./node_modules COPY . . -RUN npm run build +RUN npx prisma generate && npm run build -FROM node:19-alpine3.16 +# Deploy +FROM node:19-alpine3.17 as deploy -COPY --from=builder /app/node_modules ./node_modules -COPY --from=builder /app/package*.json ./ -COPY --from=builder /app/dist ./dist -COPY --from=builder /app/prisma ./prisma +WORKDIR /app +ENV NODE_ENV production + +# Add mysql precheck +RUN apk add --no-cache mysql-client +ADD docker-entrypoint.sh /docker-entrypoint.sh +RUN chmod +x /docker-entrypoint.sh + +# Copy files +COPY --from=build /app/package.json ./ +COPY --from=build /app/node_modules ./node_modules +COPY --from=build /app/prisma ./prisma +COPY --from=build /app/dist ./dist + +ENTRYPOINT [ "/docker-entrypoint.sh" ] CMD [ "npm", "run", "start:migrate:prod" ] diff --git a/dist/buttons/primary/index.js b/dist/buttons/primary/index.js deleted file mode 100644 index abbf3e0..0000000 --- a/dist/buttons/primary/index.js +++ /dev/null @@ -1,13 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.metadata = void 0; -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.metadata = { guildOnly: false, ephemeral: false }; -// Execute the function -const execute = (interaction) => { - logger_1.default.debug(interaction.customId, "primary button clicked!"); -}; -exports.execute = execute; diff --git a/dist/commands/config/index.js b/dist/commands/config/index.js deleted file mode 100644 index 0b3490b..0000000 --- a/dist/commands/config/index.js +++ /dev/null @@ -1,65 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const discord_js_1 = require("discord.js"); -// Modules -const audits_1 = __importDefault(require("./modules/audits")); -const cpgg_1 = __importDefault(require("./modules/cpgg")); -const credits_1 = __importDefault(require("./modules/credits")); -const embeds_1 = __importDefault(require("./modules/embeds")); -const points_1 = __importDefault(require("./modules/points")); -const shop_1 = __importDefault(require("./modules/shop")); -const welcome_1 = __importDefault(require("./modules/welcome")); -exports.builder = new discord_js_1.SlashCommandBuilder() - .setName("config") - .setDescription("Manage guild configurations.") - .setDMPermission(false) - // Modules - .addSubcommand(audits_1.default.builder) - .addSubcommand(cpgg_1.default.builder) - .addSubcommand(credits_1.default.builder) - .addSubcommand(embeds_1.default.builder) - .addSubcommand(points_1.default.builder) - .addSubcommand(shop_1.default.builder) - .addSubcommand(welcome_1.default.builder); -// Execute function -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - switch (interaction.options.getSubcommand()) { - case "audits": - yield audits_1.default.execute(interaction); - break; - case "cpgg": - yield cpgg_1.default.execute(interaction); - break; - case "credits": - yield credits_1.default.execute(interaction); - break; - case "embeds": - yield embeds_1.default.execute(interaction); - break; - case "points": - yield points_1.default.execute(interaction); - break; - case "shop": - yield shop_1.default.execute(interaction); - break; - case "welcome": - yield welcome_1.default.execute(interaction); - break; - default: - throw new Error("No module found for that specific command."); - } -}); -exports.execute = execute; diff --git a/dist/commands/config/modules/audits/index.js b/dist/commands/config/modules/audits/index.js deleted file mode 100644 index 9d3b0df..0000000 --- a/dist/commands/config/modules/audits/index.js +++ /dev/null @@ -1,89 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../helpers/checkPermission")); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -exports.default = { - builder: (command) => { - return command - .setName("audits") - .setDescription("Audits") - .addBooleanOption((option) => option - .setName("status") - .setDescription("Should audits be enabled?") - .setRequired(true)) - .addChannelOption((option) => option - .setName("channel") - .setDescription("Channel for audit messages.") - .addChannelTypes(discord_js_1.ChannelType.GuildText) - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - const { guild, options } = interaction; - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(guild); - const status = options.getBoolean("status"); - const channel = options.getChannel("channel"); - if (!guild) - throw new Error("Guild not found."); - if (!channel) - throw new Error("Channel not found."); - if (status === null) - throw new Error("Status not found."); - const createGuild = yield database_1.default.guild.upsert({ - where: { - id: guild.id, - }, - update: { - auditsEnabled: status, - auditsChannelId: channel.id, - }, - create: { - id: guild.id, - auditsEnabled: status, - auditsChannelId: channel.id, - }, - }); - logger_1.default.silly(createGuild); - const embedSuccess = new discord_js_1.EmbedBuilder() - .setTitle("[:hammer:] Audits") - .setDescription("Guild configuration updated successfully.") - .setColor(successColor) - .addFields({ - name: "🤖 Status", - value: `${createGuild.auditsEnabled - ? ":white_check_mark: Enabled" - : ":x: Disabled"}`, - inline: true, - }, { - name: "🌊 Channel", - value: `<#${createGuild.auditsChannelId}>`, - inline: true, - }) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - yield interaction.editReply({ - embeds: [embedSuccess], - }); - return; - }), -}; diff --git a/dist/commands/config/modules/cpgg/index.js b/dist/commands/config/modules/cpgg/index.js deleted file mode 100644 index 4890c04..0000000 --- a/dist/commands/config/modules/cpgg/index.js +++ /dev/null @@ -1,95 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../helpers/checkPermission")); -const encryption_1 = __importDefault(require("../../../../helpers/encryption")); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -exports.default = { - builder: (command) => { - return command - .setName("cpgg") - .setDescription("Controlpanel.gg") - .addStringOption((option) => option - .setName("scheme") - .setDescription(`Controlpanel.gg Scheme`) - .setRequired(true) - .setChoices({ name: "HTTPS (secure)", value: "https" }, { name: "HTTP (insecure)", value: "http" })) - .addStringOption((option) => option - .setName("domain") - .setDescription(`Controlpanel.gg Domain`) - .setRequired(true)) - .addStringOption((option) => option - .setName("token") - .setDescription(`Controlpanel.gg Application API`) - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const { options, guild } = interaction; - const tokenData = options.getString("token"); - const scheme = options.getString("scheme"); - const domain = options.getString("domain"); - const token = tokenData && encryption_1.default.encrypt(tokenData); - const url = scheme && domain && encryption_1.default.encrypt(`${scheme}://${domain}`); - if (!guild) - throw new Error("No guild found"); - if (!token) - throw new Error("Token not found"); - if (!url) - throw new Error("URL not found"); - const createGuild = yield database_1.default.guild.upsert({ - where: { - id: guild.id, - }, - update: { - apiCpggTokenIv: token.iv, - apiCpggTokenContent: token.content, - apiCpggUrlIv: url.iv, - apiCpggUrlContent: url.content, - }, - create: { - id: guild.id, - apiCpggTokenIv: token.iv, - apiCpggTokenContent: token.content, - apiCpggUrlIv: url.iv, - apiCpggUrlContent: url.content, - }, - }); - logger_1.default.silly(createGuild); - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`Updated API credentials.`); - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:tools:] CPGG") - .setDescription(`The following configuration will be used. - -**Scheme**: ${scheme} -**Domain**: ${domain} -**Token**: ends with ${tokenData === null || tokenData === void 0 ? void 0 : tokenData.slice(-4)}`) - .setColor(successColor) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - yield (interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [interactionEmbed], - })); - return; - }), -}; diff --git a/dist/commands/config/modules/credits/index.js b/dist/commands/config/modules/credits/index.js deleted file mode 100644 index bccb914..0000000 --- a/dist/commands/config/modules/credits/index.js +++ /dev/null @@ -1,140 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../helpers/checkPermission")); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -exports.default = { - builder: (command) => { - return command - .setName("credits") - .setDescription(`Configure this guild's credits module.`) - .addBooleanOption((option) => option - .setName("enabled") - .setDescription("Do you want to activate the credit module?") - .setRequired(true)) - .addNumberOption((option) => option - .setName("rate") - .setDescription("Credit rate per message.") - .setRequired(true) - .setMinValue(1)) - .addNumberOption((option) => option - .setName("minimum-length") - .setDescription("Minimum message length to receive credit.") - .setRequired(true)) - .addNumberOption((option) => option - .setName("work-rate") - .setDescription("The maximum amount of credit that can be obtained within a working day.") - .setRequired(true) - .setMinValue(1)) - .addNumberOption((option) => option - .setName("work-timeout") - .setDescription("How long you need to wait before you can work again provided in seconds.") - .setRequired(true)) - .addNumberOption((option) => option - .setName("timeout") - .setDescription("How long you need to wait before you can earn more credits.") - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const { guild, options } = interaction; - const enabled = options.getBoolean("enabled"); - const rate = options.getNumber("rate"); - const timeout = options.getNumber("timeout"); - const minimumLength = options.getNumber("minimum-length"); - const workRate = options.getNumber("work-rate"); - const workTimeout = options.getNumber("work-timeout"); - if (!guild) - throw new Error("Guild not found."); - if (typeof enabled !== "boolean") - throw new Error("Enabled option is not a boolean."); - if (typeof rate !== "number") - throw new Error("Rate is not a number."); - if (typeof workRate !== "number") - throw new Error("Work rate is not a number."); - if (typeof workTimeout !== "number") - throw new Error("Work timeout is not a number."); - if (typeof timeout !== "number") - throw new Error("Timeout is not a number."); - if (typeof minimumLength !== "number") - throw new Error("Minimum length is not a number."); - const createGuild = yield database_1.default.guild.upsert({ - where: { - id: guild.id, - }, - update: { - creditsEnabled: enabled, - creditsRate: rate, - creditsTimeout: timeout, - creditsWorkRate: workRate, - creditsWorkTimeout: workTimeout, - creditsMinimumLength: minimumLength, - }, - create: { - id: guild.id, - creditsEnabled: enabled, - creditsRate: rate, - creditsTimeout: timeout, - creditsWorkRate: workRate, - creditsWorkTimeout: workTimeout, - creditsMinimumLength: minimumLength, - }, - }); - logger_1.default.silly(createGuild); - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:tools:] Credits") - .setDescription("Credits settings updated") - .setColor(successColor) - .addFields({ - name: "🤖 Enabled?", - value: `${createGuild.creditsEnabled}`, - inline: true, - }, { - name: "📈 Rate", - value: `${createGuild.creditsRate}`, - inline: true, - }, { - name: "📈 Work Rate", - value: `${createGuild.creditsWorkRate}`, - inline: true, - }, { - name: "🔨 Minimum Length", - value: `${createGuild.creditsMinimumLength}`, - inline: true, - }, { - name: "⏰ Timeout", - value: `${createGuild.creditsTimeout}`, - inline: true, - }, { - name: "⏰ Work Timeout", - value: `${createGuild.creditsWorkTimeout}`, - inline: true, - }) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - yield interaction.editReply({ - embeds: [interactionEmbed], - }); - return; - }), -}; diff --git a/dist/commands/config/modules/embeds/components/getValues/index.js b/dist/commands/config/modules/embeds/components/getValues/index.js deleted file mode 100644 index 192ae0f..0000000 --- a/dist/commands/config/modules/embeds/components/getValues/index.js +++ /dev/null @@ -1,67 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const database_1 = __importDefault(require("../../../../../../handlers/database")); -const getEmbedData_1 = __importDefault(require("../../../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../../../middlewares/logger")); -exports.default = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - const { options, guild } = interaction; - if (!guild) - throw new Error("Guild not found"); - const embedConfig = yield (0, getEmbedData_1.default)(guild); - if (!embedConfig) - throw new Error("Embed config not found"); - const newSuccessColor = options.getString("success-color"); - const newWaitColor = options.getString("wait-color"); - const newErrorColor = options.getString("error-color"); - const newFooterIcon = options.getString("footer-icon"); - const newFooterText = options.getString("footer-text"); - if (!newSuccessColor) - throw new Error("Success color not found"); - if (!newWaitColor) - throw new Error("Wait color not found"); - if (!newErrorColor) - throw new Error("Error color not found"); - if (!newFooterIcon) - throw new Error("Footer icon not found"); - if (!newFooterText) - throw new Error("Footer text not found"); - const createGuild = yield database_1.default.guild.upsert({ - where: { - id: guild.id, - }, - update: { - embedColorSuccess: newSuccessColor, - embedColorWait: newWaitColor, - embedColorError: newErrorColor, - embedFooterIcon: newFooterIcon, - embedFooterText: newFooterText, - }, - create: { - id: guild.id, - embedColorSuccess: newSuccessColor, - embedColorWait: newWaitColor, - embedColorError: newErrorColor, - embedFooterIcon: newFooterIcon, - embedFooterText: newFooterText, - }, - }); - logger_1.default.silly(createGuild); - const successColor = createGuild.embedColorSuccess; - const waitColor = createGuild.embedColorWait; - const errorColor = createGuild.embedColorError; - const footerText = createGuild.embedFooterText; - const footerIcon = createGuild.embedFooterIcon; - return { successColor, waitColor, errorColor, footerText, footerIcon }; -}); diff --git a/dist/commands/config/modules/embeds/index.js b/dist/commands/config/modules/embeds/index.js deleted file mode 100644 index cbc7636..0000000 --- a/dist/commands/config/modules/embeds/index.js +++ /dev/null @@ -1,91 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../helpers/checkPermission")); -const getValues_1 = __importDefault(require("./components/getValues")); -exports.default = { - builder: (command) => { - return command - .setName("embeds") - .setDescription(`Embeds`) - .addStringOption((option) => option - .setName("success-color") - .setDescription("No provided description") - .setRequired(true)) - .addStringOption((option) => option - .setName("wait-color") - .setDescription("No provided description") - .setRequired(true)) - .addStringOption((option) => option - .setName("error-color") - .setDescription("No provided description") - .setRequired(true)) - .addStringOption((option) => option - .setName("footer-icon") - .setDescription("No provided description") - .setRequired(true)) - .addStringOption((option) => option - .setName("footer-text") - .setDescription("No provided description") - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - const { guild } = interaction; - if (!guild) - throw new Error("Guild not found"); - const { successColor, waitColor, errorColor, footerText, footerIcon } = yield (0, getValues_1.default)(interaction); - const embed = new discord_js_1.EmbedBuilder() - .setTitle("[:tools:] Embeds") - .setFooter({ text: footerText, iconURL: footerIcon }) - .setTimestamp(new Date()); - embed - .setDescription("Following embed configuration will be used.") - .setColor(successColor) - .addFields([ - { - name: "🟢 Success Color", - value: `${successColor}`, - inline: true, - }, - { - name: "🟡 Wait Color", - value: `${waitColor}`, - inline: true, - }, - { - name: "🔴 Error Color", - value: `${errorColor}`, - inline: true, - }, - { - name: "🖼️ Footer Icon", - value: `${footerIcon}`, - inline: true, - }, - { - name: "📄 Footer Text", - value: `${footerText}`, - inline: true, - }, - ]); - yield interaction.editReply({ - embeds: [embed], - }); - return; - }), -}; diff --git a/dist/commands/config/modules/points/index.js b/dist/commands/config/modules/points/index.js deleted file mode 100644 index 7f090a2..0000000 --- a/dist/commands/config/modules/points/index.js +++ /dev/null @@ -1,112 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../helpers/checkPermission")); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -exports.default = { - builder: (command) => { - return command - .setName("points") - .setDescription("Points") - .addBooleanOption((option) => option - .setName("status") - .setDescription("Should credits be enabled?") - .setRequired(true)) - .addNumberOption((option) => option - .setName("rate") - .setDescription("Amount of credits per message.") - .setRequired(true)) - .addNumberOption((option) => option - .setName("minimum-length") - .setDescription("Minimum length of message to earn credits.") - .setRequired(true)) - .addNumberOption((option) => option - .setName("timeout") - .setDescription("Timeout between earning credits (milliseconds).") - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const { options, guild } = interaction; - const status = options === null || options === void 0 ? void 0 : options.getBoolean("status"); - const rate = options === null || options === void 0 ? void 0 : options.getNumber("rate"); - const timeout = options === null || options === void 0 ? void 0 : options.getNumber("timeout"); - const minimumLength = options === null || options === void 0 ? void 0 : options.getNumber("minimum-length"); - if (!guild) - throw new Error("Guild is required"); - if (status === null) - throw new Error("Status must be specified"); - if (!rate) - throw new Error("Rate must be specified"); - if (!timeout) - throw new Error("Timeout must be specified"); - if (!minimumLength) - throw new Error("Minimum length must be specified"); - const createGuild = yield database_1.default.guild.upsert({ - where: { - id: guild.id, - }, - update: { - pointsEnabled: status, - pointsRate: rate, - pointsTimeout: timeout, - pointsMinimumLength: minimumLength, - }, - create: { - id: guild.id, - pointsEnabled: status, - pointsRate: rate, - pointsTimeout: timeout, - pointsMinimumLength: minimumLength, - }, - }); - logger_1.default.silly(createGuild); - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:tools:] Points") - .setDescription("Points settings updated") - .setColor(successColor) - .addFields({ - name: "🤖 Status", - value: `${createGuild.pointsEnabled}`, - inline: true, - }, { - name: "📈 Rate", - value: `${createGuild.pointsRate}`, - inline: true, - }, { - name: "🔨 Minimum Length", - value: `${createGuild.pointsMinimumLength}`, - inline: true, - }, { - name: "⏰ Timeout", - value: `${createGuild.pointsTimeout}`, - inline: true, - }) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - yield (interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [interactionEmbed], - })); - return; - }), -}; diff --git a/dist/commands/config/modules/shop/index.js b/dist/commands/config/modules/shop/index.js deleted file mode 100644 index 0699bcc..0000000 --- a/dist/commands/config/modules/shop/index.js +++ /dev/null @@ -1,86 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../helpers/checkPermission")); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -exports.default = { - builder: (command) => { - return command - .setName("shop") - .setDescription("Shop") - .addBooleanOption((option) => option - .setName("roles-status") - .setDescription("Should roles be enabled?") - .setRequired(true)) - .addNumberOption((option) => option - .setName("roles-price-per-hour") - .setDescription("Price per hour for roles.") - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const { options, guild } = interaction; - const rolesStatus = options === null || options === void 0 ? void 0 : options.getBoolean("roles-status"); - const rolesPricePerHour = options === null || options === void 0 ? void 0 : options.getNumber("roles-price-per-hour"); - if (!guild) - throw new Error("Guild not found"); - if (rolesStatus === null) - throw new Error("Status must be provided"); - if (!rolesPricePerHour) - throw new Error("Roles price per hour must be provided"); - const createGuild = yield database_1.default.guild.upsert({ - where: { - id: guild.id, - }, - update: { - shopRolesEnabled: rolesStatus, - shopRolesPricePerHour: rolesPricePerHour, - }, - create: { - id: guild.id, - shopRolesEnabled: rolesStatus, - shopRolesPricePerHour: rolesPricePerHour, - }, - }); - logger_1.default.silly(createGuild); - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:tools:] Shop") - .setDescription("Shop settings updated") - .setColor(successColor) - .addFields({ - name: "🤖 Roles Status", - value: `${createGuild.shopRolesEnabled}`, - inline: true, - }, { - name: "🌊 Roles Price Per Hour", - value: `${createGuild.shopRolesPricePerHour}`, - inline: true, - }) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - yield (interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [interactionEmbed], - })); - return; - }), -}; diff --git a/dist/commands/config/modules/welcome/index.js b/dist/commands/config/modules/welcome/index.js deleted file mode 100644 index 0ca942b..0000000 --- a/dist/commands/config/modules/welcome/index.js +++ /dev/null @@ -1,130 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../helpers/checkPermission")); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -exports.default = { - builder: (command) => { - return command - .setName("welcome") - .setDescription("Welcome") - .addBooleanOption((option) => option - .setName("status") - .setDescription("Should welcome be enabled?") - .setRequired(true)) - .addChannelOption((option) => option - .setName("join-channel") - .setDescription("Channel for join messages.") - .addChannelTypes(discord_js_1.ChannelType.GuildText) - .setRequired(true)) - .addChannelOption((option) => option - .setName("leave-channel") - .setDescription("Channel for leave messages.") - .addChannelTypes(discord_js_1.ChannelType.GuildText) - .setRequired(true)) - .addStringOption((option) => option - .setName("leave-message") - .setDescription("Message for leave messages.") - .setRequired(true)) - .addStringOption((option) => option - .setName("join-message") - .setDescription("Message for join messages.") - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const { options, guild } = interaction; - const status = options === null || options === void 0 ? void 0 : options.getBoolean("status"); - const joinChannel = options === null || options === void 0 ? void 0 : options.getChannel("join-channel"); - const leaveChannel = options === null || options === void 0 ? void 0 : options.getChannel("leave-channel"); - const joinChannelMessage = options === null || options === void 0 ? void 0 : options.getString("join-message"); - const leaveChannelMessage = options === null || options === void 0 ? void 0 : options.getString("leave-message"); - if (!guild) - throw new Error("Guild not found"); - if (status === null) - throw new Error("Status not specified"); - if (!joinChannel) - throw new Error("Join channel not specified"); - if (!joinChannelMessage) - throw new Error("Join channel message not specified"); - if (!leaveChannel) - throw new Error("Leave channel not specified"); - if (!leaveChannelMessage) - throw new Error("Leave channel message not specified"); - const createGuild = yield database_1.default.guild.upsert({ - where: { - id: guild.id, - }, - update: { - welcomeEnabled: status, - welcomeJoinChannelId: joinChannel.id, - welcomeJoinChannelMessage: joinChannelMessage, - welcomeLeaveChannelId: leaveChannel.id, - welcomeLeaveChannelMessage: leaveChannelMessage, - }, - create: { - id: guild.id, - welcomeEnabled: status, - welcomeJoinChannelId: joinChannel.id, - welcomeJoinChannelMessage: joinChannelMessage, - welcomeLeaveChannelId: leaveChannel.id, - welcomeLeaveChannelMessage: leaveChannelMessage, - }, - }); - logger_1.default.silly(createGuild); - const interactionEmbedDisabled = new discord_js_1.EmbedBuilder() - .setTitle("[:tools:] Welcome") - .setDescription("This module is currently disabled, please enable it to continue.") - .setColor(successColor) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - if (!createGuild.welcomeEnabled) { - return interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [interactionEmbedDisabled], - }); - } - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:tools:] Welcome") - .setDescription(`The following configuration will be used. - - [👋] **Welcome** - - ㅤ**Channel**: <#${createGuild.welcomeJoinChannelId}> - ㅤ**Message**: ${createGuild.welcomeJoinChannelMessage} - - [🚪] **Leave** - - ㅤ**Channel**: <#${createGuild.welcomeLeaveChannelId}> - ㅤ**Message**: ${createGuild.welcomeLeaveChannelMessage}`) - .setColor(successColor) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - yield (interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [interactionEmbed], - })); - return true; - }), -}; diff --git a/dist/commands/counters/index.js b/dist/commands/counters/index.js deleted file mode 100644 index 8d545c9..0000000 --- a/dist/commands/counters/index.js +++ /dev/null @@ -1,33 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const discord_js_1 = require("discord.js"); -// Modules -const view_1 = require("./modules/view"); -// -exports.builder = new discord_js_1.SlashCommandBuilder() - .setName("counters") - .setDescription("View guild counters") - .setDMPermission(false) - // Modules - .addSubcommand(view_1.builder); -// Execute function -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - switch (interaction.options.getSubcommand()) { - case "view": - yield (0, view_1.execute)(interaction); - break; - default: - throw new Error("No module found for that command."); - } -}); -exports.execute = execute; diff --git a/dist/commands/counters/modules/view/index.js b/dist/commands/counters/modules/view/index.js deleted file mode 100644 index cd5139f..0000000 --- a/dist/commands/counters/modules/view/index.js +++ /dev/null @@ -1,66 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const baseEmbeds_1 = require("../../../../helpers/baseEmbeds"); -// 1. Create builder function. -const builder = (command) => { - return command - .setName("view") - .setDescription(`View a guild counter`) - .addChannelOption((option) => option - .setName("channel") - .setDescription(`The channel that contains the counter you want to view`) - .setRequired(true) - .addChannelTypes(discord_js_1.ChannelType.GuildText)); -}; -exports.builder = builder; -// 2. Create execute function. -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Defer reply as permanent. - yield (0, deferReply_1.default)(interaction, false); - // 2. Destructure interaction object - const { options, guild } = interaction; - if (!guild) - throw new Error(`Guild not found`); - if (!options) - throw new Error(`Options not found`); - // 3. Get options - const discordChannel = options.getChannel("channel"); - if (!discordChannel) - throw new Error(`Channel not found`); - // 4. Create base embeds. - const EmbedSuccess = yield (0, baseEmbeds_1.success)(guild, "[:1234:] View"); - // 5. Get counter from database. - const channelCounter = yield database_1.default.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: discordChannel.id, - }, - }, - }); - if (!channelCounter) - throw new Error("No counter found for channel"); - // 6. Send embed. - yield interaction.editReply({ - embeds: [ - EmbedSuccess.setDescription(`Viewing counter for channel ${discordChannel}: ${channelCounter.count}!`), - ], - }); -}); -exports.execute = execute; diff --git a/dist/commands/credits/index.js b/dist/commands/credits/index.js deleted file mode 100644 index 6316886..0000000 --- a/dist/commands/credits/index.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const discord_js_1 = require("discord.js"); -// Modules -const balance_1 = require("./modules/balance"); -const gift_1 = require("./modules/gift"); -const top_1 = require("./modules/top"); -const work_1 = require("./modules/work"); -// 1. Export a builder function. -exports.builder = new discord_js_1.SlashCommandBuilder() - .setName("credits") - .setDescription("Manage your credits.") - .setDMPermission(false) - // Modules - .addSubcommand(balance_1.builder) - .addSubcommand(gift_1.builder) - .addSubcommand(top_1.builder) - .addSubcommand(work_1.builder); -// 2. Export an execute function. -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - switch (interaction.options.getSubcommand()) { - case "balance": - yield (0, balance_1.execute)(interaction); - break; - case "gift": - yield (0, gift_1.execute)(interaction); - break; - case "top": - yield (0, top_1.execute)(interaction); - break; - case "work": - yield (0, work_1.execute)(interaction); - break; - default: - throw new Error("Subcommand not found"); - } -}); -exports.execute = execute; diff --git a/dist/commands/credits/modules/balance/index.js b/dist/commands/credits/modules/balance/index.js deleted file mode 100644 index 509caf8..0000000 --- a/dist/commands/credits/modules/balance/index.js +++ /dev/null @@ -1,90 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const baseEmbeds_1 = require("../../../../helpers/baseEmbeds"); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -// 1. Export a builder function. -const builder = (command) => { - return command - .setName("balance") - .setDescription(`Check balance`) - .addUserOption((option) => option.setName("target").setDescription(`Account you want to check`)); -}; -exports.builder = builder; -// 2. Export an execute function. -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Defer reply as ephemeral. - yield (0, deferReply_1.default)(interaction, true); - // 2. Destructure interaction object. - const { options, user, guild } = interaction; - if (!guild) - throw new Error("Server unavailable"); - if (!user) - throw new Error("User unavailable"); - if (!options) - throw new Error("Options unavailable"); - // 3. Get options from interaction. - const target = options.getUser("target"); - // 4. Create base embeds. - const EmbedSuccess = yield (0, baseEmbeds_1.success)(guild, ":credit_card:︱Balance"); - // 5. Upsert the user in the database. - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: (target || user).id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: (target || user).id, - }, - where: { - id: (target || user).id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(createGuildMember); - // 6. Send embed. - yield interaction.editReply({ - embeds: [ - EmbedSuccess.setDescription(target - ? `${target} has ${createGuildMember.creditsEarned} coins in his account.` - : `You have ${createGuildMember.creditsEarned} coins in your account.`), - ], - }); -}); -exports.execute = execute; diff --git a/dist/commands/credits/modules/gift/index.js b/dist/commands/credits/modules/gift/index.js deleted file mode 100644 index ddc48a7..0000000 --- a/dist/commands/credits/modules/gift/index.js +++ /dev/null @@ -1,153 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const baseEmbeds_1 = require("../../../../helpers/baseEmbeds"); -const transfer_1 = __importDefault(require("../../../../helpers/credits/transfer")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -// 1. Export a builder function. -const builder = (command) => { - return command - .setName("gift") - .setDescription(`Gift credits to an account`) - .addUserOption((option) => option - .setName("account") - .setDescription("The account you gift to") - .setRequired(true)) - .addIntegerOption((option) => option - .setName("credits") - .setDescription("How much you gift") - .setRequired(true) - .setMinValue(1) - .setMaxValue(100000000)) - .addStringOption((option) => option - .setName("message") - .setDescription("Your personalized message to the account")); -}; -exports.builder = builder; -// 2. Export an execute function. -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Defer reply as ephemeral. - yield (0, deferReply_1.default)(interaction, true); - // 2. Destructure interaction object. - const { options, user, guild } = interaction; - if (!guild) - throw new Error("Server unavailable"); - if (!user) - throw new Error("User unavailable"); - // 3. Get options from interaction. - const account = options.getUser("account"); - const credits = options.getInteger("credits"); - const message = options.getString("message"); - if (!account) - throw new Error("Account unavailable"); - if (typeof credits !== "number") - throw new Error("You need to enter a valid number of credits to gift"); - // 4. Create base embeds. - const receiverEmbed = yield (0, baseEmbeds_1.success)(guild, `:credit_card:︱You received a gift from ${user.username}`); - // 5. Start an transaction of the credits. - yield (0, transfer_1.default)(guild, user, account, credits); - const receiverGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: account.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: account.id, - }, - where: { - id: account.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(receiverGuildMember); - if (message) - receiverEmbed.setFields({ name: "Message", value: message }); - // 6. Tell the target that they have been gifted credits. - yield account.send({ - embeds: [ - receiverEmbed.setDescription(`You received a gift containing ${credits} coins from ${user}! You now have ${receiverGuildMember.creditsEarned} coins in balance!`), - ], - }); - const senderGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(senderGuildMember); - const senderEmbed = yield (0, baseEmbeds_1.success)(guild, ":credit_card:︱Send a gift"); - if (message) - senderEmbed.setFields({ name: "Message", value: message }); - // 7. Tell the sender that they have gifted the credits. - yield interaction.editReply({ - embeds: [ - senderEmbed.setDescription(`Your gift has been sent to ${account}. You now have ${senderGuildMember.creditsEarned} coins in balance!`), - ], - }); -}); -exports.execute = execute; diff --git a/dist/commands/credits/modules/top/index.js b/dist/commands/credits/modules/top/index.js deleted file mode 100644 index 73dc0c7..0000000 --- a/dist/commands/credits/modules/top/index.js +++ /dev/null @@ -1,60 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const baseEmbeds_1 = require("../../../../helpers/baseEmbeds"); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -// 1. Export a builder function. -const builder = (command) => { - return command.setName("top").setDescription(`View the top users`); -}; -exports.builder = builder; -// 2. Export an execute function. -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Defer reply as permanent. - yield (0, deferReply_1.default)(interaction, false); - // 2. Destructure interaction object. - const { guild, client } = interaction; - if (!guild) - throw new Error("Guild not found"); - if (!client) - throw new Error("Client not found"); - // 3. Create base embeds. - const EmbedSuccess = yield (0, baseEmbeds_1.success)(guild, "[:dollar:] Top"); - // 4. Get the top 10 users. - const topTen = yield database_1.default.guildMember.findMany({ - where: { - guildId: guild.id, - }, - orderBy: { - creditsEarned: "desc", - }, - take: 10, - }); - logger_1.default.silly(topTen); - // 5. Create the top 10 list. - const entry = (guildMember, index) => `${index + 1}. ${(0, discord_js_1.userMention)(guildMember.userId)} | :coin: ${guildMember.creditsEarned}`; - // 6. Send embed - return interaction.editReply({ - embeds: [ - EmbedSuccess.setDescription(`The top 10 users in this server are:\n\n${topTen - .map(entry) - .join("\n")}`), - ], - }); -}); -exports.execute = execute; diff --git a/dist/commands/credits/modules/work/index.js b/dist/commands/credits/modules/work/index.js deleted file mode 100644 index 065fad4..0000000 --- a/dist/commands/credits/modules/work/index.js +++ /dev/null @@ -1,70 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const chance_1 = __importDefault(require("chance")); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const baseEmbeds_1 = require("../../../../helpers/baseEmbeds"); -const give_1 = __importDefault(require("../../../../helpers/credits/give")); -const cooldown_1 = __importDefault(require("../../../../middlewares/cooldown")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -// 1. Export a builder function. -const builder = (command) => { - return command.setName("work").setDescription(`Work to earn credits`); -}; -exports.builder = builder; -// 2. Export an execute function. -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Defer reply as ephemeral. - yield (0, deferReply_1.default)(interaction, true); - // 2. Destructure interaction object. - const { guild, user, commandId } = interaction; - if (!guild) - throw new Error("Guild not found"); - if (!user) - throw new Error("User not found"); - // 3. Create base embeds. - const EmbedSuccess = yield (0, baseEmbeds_1.success)(guild, "[:dollar:] Work"); - // 4. Create new Chance instance. - const chance = new chance_1.default(); - // 5. Upsert the guild in the database. - const createGuild = yield database_1.default.guild.upsert({ - where: { - id: guild.id, - }, - update: {}, - create: { - id: guild.id, - }, - }); - logger_1.default.silly(createGuild); - if (!createGuild) - throw new Error("Guild not found"); - // 6. Create a cooldown for the user. - yield (0, cooldown_1.default)(guild, user, commandId, createGuild.creditsWorkTimeout); - // 6. Generate a random number between 0 and creditsWorkRate. - const creditsEarned = chance.integer({ - min: 0, - max: createGuild.creditsWorkRate, - }); - const upsertGuildMember = yield (0, give_1.default)(guild, user, creditsEarned); - // 8. Send embed. - yield interaction.editReply({ - embeds: [ - EmbedSuccess.setDescription(`You worked and earned **${creditsEarned}** credits! You now have **${upsertGuildMember.creditsEarned}** credits. :tada:`), - ], - }); -}); -exports.execute = execute; diff --git a/dist/commands/dns/index.js b/dist/commands/dns/index.js deleted file mode 100644 index cfb2509..0000000 --- a/dist/commands/dns/index.js +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const discord_js_1 = require("discord.js"); -// Modules -const lookup_1 = __importDefault(require("./modules/lookup")); -exports.builder = new discord_js_1.SlashCommandBuilder() - .setName("dns") - .setDescription("DNS commands.") - // Modules - .addSubcommand(lookup_1.default.builder); -// Execute the command -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - switch (interaction.options.getSubcommand()) { - case "lookup": - yield lookup_1.default.execute(interaction); - break; - default: - throw new Error(`Unknown subcommand: ${interaction.options.getSubcommand()}`); - } -}); -exports.execute = execute; diff --git a/dist/commands/dns/modules/lookup/index.js b/dist/commands/dns/modules/lookup/index.js deleted file mode 100644 index 3408939..0000000 --- a/dist/commands/dns/modules/lookup/index.js +++ /dev/null @@ -1,132 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const axios_1 = __importDefault(require("axios")); -const discord_js_1 = require("discord.js"); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -exports.default = { - builder: (command) => { - return command - .setName("lookup") - .setDescription("Lookup a domain or ip. (Request sent over HTTP, proceed with caution!)") - .addStringOption((option) => option - .setName("query") - .setDescription("The query you want to look up.") - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, false); - const { errorColor, successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const embedTitle = "[:hammer:] Utility (Lookup)"; - const { options } = interaction; - const query = options.getString("query"); - yield axios_1.default - .get(`http://ip-api.com/json/${query}`) - .then((response) => __awaiter(void 0, void 0, void 0, function* () { - var _a, _b; - if (response.data.status !== "success") { - yield interaction.editReply({ - embeds: [ - new discord_js_1.EmbedBuilder() - .setTitle(embedTitle) - .setFooter({ - text: footerText, - iconURL: footerIcon, - }) - .setTimestamp(new Date()) - .setColor(errorColor) - .setFooter({ text: footerText, iconURL: footerIcon }) - .setDescription(`${(_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.message}: ${(_b = response === null || response === void 0 ? void 0 : response.data) === null || _b === void 0 ? void 0 : _b.query}`), - ], - }); - return; - } - yield interaction.editReply({ - embeds: [ - new discord_js_1.EmbedBuilder() - .setTitle(embedTitle) - .setFooter({ - text: footerText, - iconURL: footerIcon, - }) - .setTimestamp(new Date()) - .setColor(successColor) - .setFields([ - { - name: ":classical_building: AS", - value: `${response.data.as || "Unknown"}`, - inline: true, - }, - { - name: ":classical_building: ISP", - value: `${response.data.isp || "Unknown"}`, - inline: true, - }, - { - name: ":classical_building: Organization", - value: `${response.data.org || "Unknown"}`, - inline: true, - }, - { - name: ":compass: Latitude", - value: `${response.data.lat || "Unknown"}`, - inline: true, - }, - { - name: ":compass: Longitude", - value: `${response.data.lon || "Unknown"}`, - inline: true, - }, - { - name: ":clock4: Timezone", - value: `${response.data.timezone || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: Country", - value: `${response.data.country || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: Region", - value: `${response.data.regionName || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: City", - value: `${response.data.city || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: Country Code", - value: `${response.data.countryCode || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: Region Code", - value: `${response.data.region || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: ZIP", - value: `${response.data.zip || "Unknown"}`, - inline: true, - }, - ]), - ], - }); - })); - }), -}; diff --git a/dist/commands/fun/index.js b/dist/commands/fun/index.js deleted file mode 100644 index f68d227..0000000 --- a/dist/commands/fun/index.js +++ /dev/null @@ -1,34 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const discord_js_1 = require("discord.js"); -const logger_1 = __importDefault(require("../../middlewares/logger")); -// Modules -const meme_1 = __importDefault(require("./modules/meme")); -exports.builder = new discord_js_1.SlashCommandBuilder() - .setName("fun") - .setDescription("Fun commands.") - .addSubcommand(meme_1.default.builder); -// Execute function -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - const { options } = interaction; - if (options.getSubcommand() === "meme") { - yield meme_1.default.execute(interaction); - } - else { - logger_1.default.silly(`Unknown subcommand ${options.getSubcommand()}`); - } -}); -exports.execute = execute; diff --git a/dist/commands/fun/modules/meme/index.js b/dist/commands/fun/modules/meme/index.js deleted file mode 100644 index d75c2f5..0000000 --- a/dist/commands/fun/modules/meme/index.js +++ /dev/null @@ -1,59 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const axios_1 = __importDefault(require("axios")); -const discord_js_1 = require("discord.js"); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -const cooldown_1 = __importDefault(require("../../../../middlewares/cooldown")); -exports.default = { - builder: (command) => { - return command.setName("meme").setDescription("Random memes from r/memes"); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, false); - const { guild, user, commandId } = interaction; - if (!guild) - throw new Error("Server unavailable"); - if (!user) - throw new Error("User unavailable"); - yield (0, cooldown_1.default)(guild, user, commandId, 15); - const embedConfig = yield (0, getEmbedData_1.default)(guild); - yield axios_1.default - .get("https://www.reddit.com/r/memes/random/.json") - .then((res) => __awaiter(void 0, void 0, void 0, function* () { - const response = res.data[0].data.children; - const content = response[0].data; - const buttons = new discord_js_1.ActionRowBuilder().addComponents(new discord_js_1.ButtonBuilder() - .setLabel("View post") - .setStyle(discord_js_1.ButtonStyle.Link) - .setEmoji("🔗") - .setURL(`https://reddit.com${content.permalink}`)); - const embed = new discord_js_1.EmbedBuilder() - .setTitle(`😆︱Meme`) - .setDescription(`**${content.title}**`) - .setTimestamp(new Date()) - .setImage(content.url) - .setFooter({ - text: `👍 ${content.ups}︱👎 ${content.downs}`, - }) - .setColor(embedConfig.successColor); - yield interaction.editReply({ embeds: [embed], components: [buttons] }); - return; - })) - .catch((error) => { - throw new Error(error.message); - }); - }), -}; diff --git a/dist/commands/manage/index.js b/dist/commands/manage/index.js deleted file mode 100644 index 69b94d7..0000000 --- a/dist/commands/manage/index.js +++ /dev/null @@ -1,46 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -//Dependencies -const discord_js_1 = require("discord.js"); -// Modules -const counters_1 = __importDefault(require("./modules/counters")); -const credits_1 = __importDefault(require("./modules/credits")); -// Function -exports.builder = new discord_js_1.SlashCommandBuilder() - .setName("manage") - .setDescription("Manage the bot.") - .setDMPermission(false) - // Modules - .addSubcommandGroup(counters_1.default.builder) - .addSubcommandGroup(credits_1.default.builder); -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - // Destructure - const { options } = interaction; - switch (options.getSubcommandGroup()) { - case "credits": { - yield credits_1.default.execute(interaction); - break; - } - case "counters": { - yield counters_1.default.execute(interaction); - break; - } - default: { - throw new Error("Could not find an module for the command."); - } - } -}); -exports.execute = execute; diff --git a/dist/commands/manage/modules/counters/index.js b/dist/commands/manage/modules/counters/index.js deleted file mode 100644 index 1788509..0000000 --- a/dist/commands/manage/modules/counters/index.js +++ /dev/null @@ -1,42 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Modules -const add_1 = __importDefault(require("./modules/add")); -const remove_1 = __importDefault(require("./modules/remove")); -exports.default = { - builder: (group) => { - return group - .setName("counters") - .setDescription("Manage guild counters.") - .addSubcommand(add_1.default.builder) - .addSubcommand(remove_1.default.builder); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - const { options } = interaction; - switch (options.getSubcommand()) { - case "add": { - yield add_1.default.execute(interaction); - break; - } - case "remove": { - yield remove_1.default.execute(interaction); - break; - } - default: { - throw new Error("Could not found a module for that command."); - } - } - }), -}; diff --git a/dist/commands/manage/modules/counters/modules/add/index.js b/dist/commands/manage/modules/counters/modules/add/index.js deleted file mode 100644 index 0d8b196..0000000 --- a/dist/commands/manage/modules/counters/modules/add/index.js +++ /dev/null @@ -1,105 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Dependencies -const discord_js_1 = require("discord.js"); -const deferReply_1 = __importDefault(require("../../../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../../../helpers/checkPermission")); -// Configurations -const database_1 = __importDefault(require("../../../../../../handlers/database")); -const getEmbedData_1 = __importDefault(require("../../../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../../../middlewares/logger")); -// Function -exports.default = { - builder: (command) => { - return command - .setName("add") - .setDescription("Add a counter to your guild.") - .addChannelOption((option) => option - .setName("channel") - .setDescription("The channel to send the counter to.") - .setRequired(true) - .addChannelTypes(discord_js_1.ChannelType.GuildText)) - .addStringOption((option) => option - .setName("word") - .setDescription("The word to use for the counter.") - .setRequired(true)) - .addNumberOption((option) => option - .setName("start") - .setDescription("The starting value of the counter.")); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const { options, guild } = interaction; - const discordChannel = options === null || options === void 0 ? void 0 : options.getChannel("channel"); - const triggerWord = options === null || options === void 0 ? void 0 : options.getString("word"); - const startValue = options === null || options === void 0 ? void 0 : options.getNumber("start"); - if (!guild) - throw new Error("We could not find a guild"); - if (!discordChannel) - throw new Error("We could not find a channel"); - if (!triggerWord) - throw new Error("We could not find a word"); - const channelCounter = yield database_1.default.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: discordChannel.id, - }, - }, - }); - if (channelCounter) - throw new Error("A counter already exists for this channel."); - const createGuildCounter = yield database_1.default.guildCounter.upsert({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: discordChannel.id, - }, - }, - update: {}, - create: { - channelId: discordChannel.id, - triggerWord, - count: startValue || 0, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - }); - logger_1.default.silly(createGuildCounter); - if (createGuildCounter) { - const embed = new discord_js_1.EmbedBuilder() - .setTitle("[:toolbox:] Counters - Add") - .setTimestamp(new Date()) - .setFooter({ text: footerText, iconURL: footerIcon }); - yield (interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [ - embed - .setDescription(":white_check_mark: Counter created successfully.") - .setColor(successColor), - ], - })); - } - }), -}; diff --git a/dist/commands/manage/modules/counters/modules/remove/index.js b/dist/commands/manage/modules/counters/modules/remove/index.js deleted file mode 100644 index 312cfa9..0000000 --- a/dist/commands/manage/modules/counters/modules/remove/index.js +++ /dev/null @@ -1,75 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Dependencies -// Models -const discord_js_1 = require("discord.js"); -const deferReply_1 = __importDefault(require("../../../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../../../helpers/checkPermission")); -// Configurations -const database_1 = __importDefault(require("../../../../../../handlers/database")); -const getEmbedData_1 = __importDefault(require("../../../../../../helpers/getEmbedData")); -// Function -exports.default = { - builder: (command) => { - return command - .setName("remove") - .setDescription(`Delete a counter from your guild.`) - .addChannelOption((option) => option - .setName("channel") - .setDescription("The channel to delete the counter from.") - .setRequired(true) - .addChannelTypes(discord_js_1.ChannelType.GuildText)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const { options, guild } = interaction; - const discordChannel = options === null || options === void 0 ? void 0 : options.getChannel("channel"); - if (!guild) - throw new Error("We could not find a guild"); - if (!discordChannel) - throw new Error("We could not find a channel"); - const embed = new discord_js_1.EmbedBuilder() - .setTitle("[:toolbox:] Counters - Remove") - .setTimestamp(new Date()) - .setFooter({ text: footerText, iconURL: footerIcon }); - const channelCounter = yield database_1.default.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: discordChannel.id, - }, - }, - }); - if (!channelCounter) - throw new Error("There is no counter sin this channel, please add one first."); - const deleteGuildCounter = yield database_1.default.guildCounter.deleteMany({ - where: { - guildId: guild.id, - channelId: discordChannel.id, - }, - }); - if (!deleteGuildCounter) - throw new Error("We could not find a counter for this guild"); - yield (interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [ - embed - .setDescription(":white_check_mark: Counter deleted successfully.") - .setColor(successColor), - ], - })); - }), -}; diff --git a/dist/commands/manage/modules/credits/index.js b/dist/commands/manage/modules/credits/index.js deleted file mode 100644 index 00cd15b..0000000 --- a/dist/commands/manage/modules/credits/index.js +++ /dev/null @@ -1,53 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Modules -const give_1 = __importDefault(require("./modules/give")); -const giveaway_1 = __importDefault(require("./modules/giveaway")); -const set_1 = __importDefault(require("./modules/set")); -const take_1 = __importDefault(require("./modules/take")); -const transfer_1 = __importDefault(require("./modules/transfer")); -exports.default = { - builder: (group) => { - return group - .setName("credits") - .setDescription("Manage the credits of a user.") - .addSubcommand(give_1.default.builder) - .addSubcommand(set_1.default.builder) - .addSubcommand(take_1.default.builder) - .addSubcommand(transfer_1.default.builder) - .addSubcommand(giveaway_1.default.builder); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - switch (interaction.options.getSubcommand()) { - case "give": - yield give_1.default.execute(interaction); - break; - case "set": - yield set_1.default.execute(interaction); - break; - case "take": - yield take_1.default.execute(interaction); - break; - case "transfer": - yield transfer_1.default.execute(interaction); - break; - case "giveaway": - yield giveaway_1.default.execute(interaction); - break; - default: - throw new Error("No module found for that specific command"); - } - }), -}; diff --git a/dist/commands/manage/modules/credits/modules/give/index.js b/dist/commands/manage/modules/credits/modules/give/index.js deleted file mode 100644 index f114c38..0000000 --- a/dist/commands/manage/modules/credits/modules/give/index.js +++ /dev/null @@ -1,69 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Dependencies -const discord_js_1 = require("discord.js"); -// Configurations -// Helpers../../../../../../../helpers/userData -const pluralize_1 = __importDefault(require("../../../../../../helpers/pluralize")); -// Models -// Handlers -const deferReply_1 = __importDefault(require("../../../../../../handlers/deferReply")); -const baseEmbeds_1 = require("../../../../../../helpers/baseEmbeds"); -const checkPermission_1 = __importDefault(require("../../../../../../helpers/checkPermission")); -const give_1 = __importDefault(require("../../../../../../helpers/credits/give")); -exports.default = { - builder: (command) => { - return command - .setName("give") - .setDescription("Give credits to a user.") - .addUserOption((option) => option - .setName("user") - .setDescription("The user to give credits to.") - .setRequired(true)) - .addIntegerOption((option) => option - .setName("amount") - .setDescription(`The amount of credits to give.`) - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Defer reply as ephemeral. - yield (0, deferReply_1.default)(interaction, true); - // 2. Check if the user has the MANAGE_GUILD permission. - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - // 3. Destructure interaction object. - const { guild, options } = interaction; - if (!guild) - throw new Error("We could not get the current guild from discord."); - if (!options) - throw new Error("We could not get the options from discord."); - // 4. Get the user and amount from the options. - const discordReceiver = options.getUser("user"); - const creditsAmount = options.getInteger("amount"); - if (typeof creditsAmount !== "number") - throw new Error("You need to provide a credit amount."); - if (!discordReceiver) - throw new Error("We could not get the receiving user from Discord"); - // 5. Create base embeds. - const embedSuccess = yield (0, baseEmbeds_1.success)(guild, "[:toolbox:] Give"); - // 6. Give the credits. - yield (0, give_1.default)(guild, discordReceiver, creditsAmount); - // 7. Send embed. - return yield interaction.editReply({ - embeds: [ - embedSuccess.setDescription(`Successfully gave ${(0, pluralize_1.default)(creditsAmount, "credit")}`), - ], - }); - }), -}; diff --git a/dist/commands/manage/modules/credits/modules/giveaway/index.js b/dist/commands/manage/modules/credits/modules/giveaway/index.js deleted file mode 100644 index 2b831c6..0000000 --- a/dist/commands/manage/modules/credits/modules/giveaway/index.js +++ /dev/null @@ -1,166 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Dependencies -const axios_1 = __importDefault(require("axios")); -const discord_js_1 = require("discord.js"); -const uuid_1 = require("uuid"); -const encryption_1 = __importDefault(require("../../../../../../helpers/encryption")); -// Configurations -const database_1 = __importDefault(require("../../../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../../../helpers/checkPermission")); -const getEmbedData_1 = __importDefault(require("../../../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../../../middlewares/logger")); -// Function -exports.default = { - builder: (command) => { - return command - .setName("giveaway") - .setDescription("Giveaway some credits for specified amount of users.") - .addIntegerOption((option) => option - .setName("uses") - .setDescription("How many users should be able to use this.") - .setRequired(true)) - .addIntegerOption((option) => option - .setName("credit") - .setDescription(`How much credits provided per use.`) - .setRequired(true)) - .addChannelOption((option) => option - .setName("channel") - .setDescription("The channel to send the message to.") - .setRequired(true) - .addChannelTypes(discord_js_1.ChannelType.GuildText)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - var _a; - yield (0, deferReply_1.default)(interaction, true); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); // Destructure - const { guild, user, options } = interaction; - const uses = options === null || options === void 0 ? void 0 : options.getInteger("uses"); - const creditAmount = options === null || options === void 0 ? void 0 : options.getInteger("credit"); - const channel = options === null || options === void 0 ? void 0 : options.getChannel("channel"); - if (!uses) - throw new Error("Amount of uses is required."); - if (!creditAmount) - throw new Error("Amount of credits is required."); - if (!channel) - throw new Error("Channel is required."); - if (!guild) - throw new Error("Guild is required."); - const embed = new discord_js_1.EmbedBuilder() - .setTitle("[:toolbox:] Giveaway") - .setFooter({ text: footerText, iconURL: footerIcon }); - const code = (0, uuid_1.v4)(); - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(createGuildMember); - if (!createGuildMember.guild.apiCpggUrlIv || - !createGuildMember.guild.apiCpggUrlContent) - throw new Error("No API url available"); - if (!createGuildMember.guild.apiCpggTokenIv || - !createGuildMember.guild.apiCpggTokenContent) - throw new Error("No API token available"); - const url = encryption_1.default.decrypt({ - iv: createGuildMember.guild.apiCpggUrlIv, - content: createGuildMember.guild.apiCpggUrlContent, - }); - const api = axios_1.default === null || axios_1.default === void 0 ? void 0 : axios_1.default.create({ - baseURL: `${url}/api/`, - headers: { - Authorization: `Bearer ${encryption_1.default.decrypt({ - iv: createGuildMember.guild.apiCpggTokenIv, - content: createGuildMember.guild.apiCpggTokenContent, - })}`, - }, - }); - const shopUrl = `${url}/store`; - yield api - .post("vouchers", { - uses, - code, - credits: creditAmount, - memo: `[GIVEAWAY] ${interaction === null || interaction === void 0 ? void 0 : interaction.createdTimestamp} - ${(_a = interaction === null || interaction === void 0 ? void 0 : interaction.user) === null || _a === void 0 ? void 0 : _a.id}`, - }) - .then(() => __awaiter(void 0, void 0, void 0, function* () { - yield interaction.editReply({ - embeds: [ - embed - .setColor(successColor) - .setDescription(`Successfully created code: ${code}`), - ], - }); - const buttons = new discord_js_1.ActionRowBuilder().addComponents(new discord_js_1.ButtonBuilder() - .setLabel("Redeem it here") - .setStyle(discord_js_1.ButtonStyle.Link) - .setEmoji("🏦") - .setURL(`${shopUrl}?voucher=${code}`)); - const discordChannel = guild === null || guild === void 0 ? void 0 : guild.channels.cache.get(channel.id); - if (!discordChannel) - return; - if (discordChannel.type !== discord_js_1.ChannelType.GuildText) - return; - discordChannel.send({ - embeds: [ - new discord_js_1.EmbedBuilder() - .setTitle("[:parachute:] Credits!") - .addFields([ - { - name: "💶 Credits", - value: `${creditAmount}`, - inline: true, - }, - ]) - .setDescription(`${interaction.user} dropped a voucher for a maximum **${uses}** members!`) - .setColor(successColor), - ], - components: [buttons], - }); - })); - }), -}; diff --git a/dist/commands/manage/modules/credits/modules/set/index.js b/dist/commands/manage/modules/credits/modules/set/index.js deleted file mode 100644 index d07adc2..0000000 --- a/dist/commands/manage/modules/credits/modules/set/index.js +++ /dev/null @@ -1,66 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Dependencies -// Helpers -// Models -const discord_js_1 = require("discord.js"); -const deferReply_1 = __importDefault(require("../../../../../../handlers/deferReply")); -const baseEmbeds_1 = require("../../../../../../helpers/baseEmbeds"); -const checkPermission_1 = __importDefault(require("../../../../../../helpers/checkPermission")); -const set_1 = __importDefault(require("../../../../../../helpers/credits/set")); -exports.default = { - builder: (command) => { - return command - .setName("set") - .setDescription("Set the amount of credits a user has.") - .addUserOption((option) => option - .setName("user") - .setDescription("The user to set the amount of credits for.") - .setRequired(true)) - .addIntegerOption((option) => option - .setName("amount") - .setDescription(`The amount of credits to set.`) - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Defer reply as ephemeral. - yield (0, deferReply_1.default)(interaction, true); - // 2. Check if the user has the permission to manage the guild. - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - // 3. Destructure interaction object. - const { options, guild } = interaction; - if (!guild) - throw new Error(`We could not find this guild.`); - if (!options) - throw new Error(`We could not find the options.`); - // 4. Get the user and amount from the options. - const discordUser = options.getUser("user"); - const creditAmount = options.getInteger("amount"); - if (typeof creditAmount !== "number") - throw new Error("Amount is not set."); - if (!discordUser) - throw new Error("User is not specified"); - // 5. Set the credits. - yield (0, set_1.default)(guild, discordUser, creditAmount); - // 6. Create base embeds. - const embedSuccess = yield (0, baseEmbeds_1.success)(guild, "[:toolbox:] Set"); - // 7. Send embed. - return yield interaction.editReply({ - embeds: [ - embedSuccess.setDescription(`Set **${discordUser}**'s credits to **${creditAmount}**.`), - ], - }); - }), -}; diff --git a/dist/commands/manage/modules/credits/modules/take/index.js b/dist/commands/manage/modules/credits/modules/take/index.js deleted file mode 100644 index 73a6356..0000000 --- a/dist/commands/manage/modules/credits/modules/take/index.js +++ /dev/null @@ -1,66 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Dependencies -// Models -const discord_js_1 = require("discord.js"); -const deferReply_1 = __importDefault(require("../../../../../../handlers/deferReply")); -const baseEmbeds_1 = require("../../../../../../helpers/baseEmbeds"); -const checkPermission_1 = __importDefault(require("../../../../../../helpers/checkPermission")); -const take_1 = __importDefault(require("../../../../../../helpers/credits/take")); -const pluralize_1 = __importDefault(require("../../../../../../helpers/pluralize")); -exports.default = { - builder: (command) => { - return command - .setName("take") - .setDescription("Take credits from a user.") - .addUserOption((option) => option - .setName("user") - .setDescription("The user to take credits from.") - .setRequired(true)) - .addIntegerOption((option) => option - .setName("amount") - .setDescription(`The amount of credits to take.`) - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Defer reply as ephemeral. - yield (0, deferReply_1.default)(interaction, true); - // 2. Check if the user has the MANAGE_GUILD permission. - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - // 3. Destructure interaction object. - const { guild, options } = interaction; - if (!guild) - throw new Error("Invalid guild."); - if (!options) - throw new Error("Invalid options."); - // 4. Get the user and amount from the options. - const discordReceiver = options.getUser("user"); - const optionAmount = options.getInteger("amount"); - if (typeof optionAmount !== "number") - throw new Error("Invalid amount."); - if (!discordReceiver) - throw new Error("Invalid user."); - // 5. Create base embeds. - const embedSuccess = yield (0, baseEmbeds_1.success)(guild, "[:toolbox:] Take"); - // 6. Take the credits. - yield (0, take_1.default)(guild, discordReceiver, optionAmount); - // 7. Send embed. - return yield interaction.editReply({ - embeds: [ - embedSuccess.setDescription(`Took ${(0, pluralize_1.default)(optionAmount, "credit")} from ${discordReceiver}.`), - ], - }); - }), -}; diff --git a/dist/commands/manage/modules/credits/modules/transfer/index.js b/dist/commands/manage/modules/credits/modules/transfer/index.js deleted file mode 100644 index fc27bfb..0000000 --- a/dist/commands/manage/modules/credits/modules/transfer/index.js +++ /dev/null @@ -1,73 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Dependencies -// Models -const discord_js_1 = require("discord.js"); -const transfer_1 = __importDefault(require("../../../../../../helpers/credits/transfer")); -// Configurations -const deferReply_1 = __importDefault(require("../../../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../../../helpers/checkPermission")); -const getEmbedData_1 = __importDefault(require("../../../../../../helpers/getEmbedData")); -// Function -exports.default = { - builder: (command) => { - return command - .setName("transfer") - .setDescription("Transfer credits from one user to another.") - .addUserOption((option) => option - .setName("from") - .setDescription("The user to transfer credits from.") - .setRequired(true)) - .addUserOption((option) => option - .setName("to") - .setDescription("The user to transfer credits to.") - .setRequired(true)) - .addIntegerOption((option) => option - .setName("amount") - .setDescription(`The amount of credits to transfer.`) - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageGuild); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); // Destructure member - const { guild, options } = interaction; - // Get options - const optionFromUser = options === null || options === void 0 ? void 0 : options.getUser("from"); - const optionToUser = options === null || options === void 0 ? void 0 : options.getUser("to"); - const optionAmount = options === null || options === void 0 ? void 0 : options.getInteger("amount"); - if (optionAmount === null) - throw new Error("Amount is not specified"); - if (optionAmount <= 0) - throw new Error("You need to set amount above zero to transfer."); - if (!guild) - throw new Error(`We could not find this guild.`); - if (!optionFromUser) - throw new Error("You must provide a user to transfer from."); - if (!optionToUser) - throw new Error("You must provide a user to transfer to."); - yield (0, transfer_1.default)(guild, optionFromUser, optionToUser, optionAmount); - return interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [ - new discord_js_1.EmbedBuilder() - .setTitle("[:toolbox:] Manage - Credits (Transfer)") - .setDescription(`Transferred ${optionAmount} credits.`) - .setTimestamp(new Date()) - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }), - ], - }); - }), -}; diff --git a/dist/commands/moderation/index.js b/dist/commands/moderation/index.js deleted file mode 100644 index ed29270..0000000 --- a/dist/commands/moderation/index.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const discord_js_1 = require("discord.js"); -// Modules -const prune_1 = __importDefault(require("./modules/prune")); -exports.builder = new discord_js_1.SlashCommandBuilder() - .setName("moderation") - .setDescription("Moderation.") - .setDMPermission(false) - .addSubcommand(prune_1.default.builder); -// Execute the command -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - switch (interaction.options.getSubcommand()) { - case "prune": { - yield prune_1.default.execute(interaction); - break; - } - default: { - throw new Error(`Unknown subcommand: ${interaction.options.getSubcommand()}`); - } - } -}); -exports.execute = execute; diff --git a/dist/commands/moderation/modules/prune/index.js b/dist/commands/moderation/modules/prune/index.js deleted file mode 100644 index bab2b18..0000000 --- a/dist/commands/moderation/modules/prune/index.js +++ /dev/null @@ -1,78 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Dependencies -const discord_js_1 = require("discord.js"); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const checkPermission_1 = __importDefault(require("../../../../helpers/checkPermission")); -// Configurations -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -// Function -exports.default = { - builder: (command) => { - return command - .setName("prune") - .setDescription("Prune messages!") - .addIntegerOption((option) => option - .setName("count") - .setDescription("How many messages you want to prune.") - .setRequired(true)) - .addBooleanOption((option) => option.setName("bots").setDescription("Include bots.")); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - var _a; - yield (0, deferReply_1.default)(interaction, false); - (0, checkPermission_1.default)(interaction, discord_js_1.PermissionsBitField.Flags.ManageMessages); - const { errorColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const count = interaction.options.getInteger("count"); - if (count === null) - return; - const bots = interaction.options.getBoolean("bots"); - if (count < 1 || count > 100) { - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:police_car:] Prune") - .setDescription(`You can only prune between 1 and 100 messages.`) - .setTimestamp() - .setColor(errorColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - yield interaction.editReply({ - embeds: [interactionEmbed], - }); - return; - } - if (((_a = interaction === null || interaction === void 0 ? void 0 : interaction.channel) === null || _a === void 0 ? void 0 : _a.type) !== discord_js_1.ChannelType.GuildText) - return; - yield interaction.channel.messages.fetch().then((messages) => __awaiter(void 0, void 0, void 0, function* () { - var _b; - const messagesToDelete = (bots - ? messages.filter((m) => { var _a; return ((_a = m === null || m === void 0 ? void 0 : m.interaction) === null || _a === void 0 ? void 0 : _a.id) !== interaction.id; }) - : messages.filter((m) => { var _a, _b; return ((_a = m === null || m === void 0 ? void 0 : m.interaction) === null || _a === void 0 ? void 0 : _a.id) !== interaction.id && ((_b = m === null || m === void 0 ? void 0 : m.author) === null || _b === void 0 ? void 0 : _b.bot) !== true; })).first(count); - if (((_b = interaction === null || interaction === void 0 ? void 0 : interaction.channel) === null || _b === void 0 ? void 0 : _b.type) !== discord_js_1.ChannelType.GuildText) - return; - yield interaction.channel - .bulkDelete(messagesToDelete, true) - .then(() => __awaiter(void 0, void 0, void 0, function* () { - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:police_car:] Prune") - .setDescription(`Successfully pruned \`${count}\` messages.`) - .setTimestamp() - .setColor(errorColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - yield interaction.editReply({ - embeds: [interactionEmbed], - }); - })); - })); - }), -}; diff --git a/dist/commands/reputation/index.js b/dist/commands/reputation/index.js deleted file mode 100644 index 25c0feb..0000000 --- a/dist/commands/reputation/index.js +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -// Dependencies -const discord_js_1 = require("discord.js"); -// Modules -const check_1 = __importDefault(require("./modules/check")); -const repute_1 = __importDefault(require("./modules/repute")); -// Function -exports.builder = new discord_js_1.SlashCommandBuilder() - .setName("reputation") - .setDescription("See and repute users to show other how trustworthy they are") - .setDMPermission(false) - // Modules - .addSubcommand(repute_1.default.builder) - .addSubcommand(check_1.default.builder); -// Execute function -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - if (interaction.options.getSubcommand() === "repute") { - yield repute_1.default.execute(interaction); - return; - } - if (interaction.options.getSubcommand() === "check") { - yield check_1.default.execute(interaction); - return; - } -}); -exports.execute = execute; diff --git a/dist/commands/reputation/modules/check/index.js b/dist/commands/reputation/modules/check/index.js deleted file mode 100644 index dfcf6db..0000000 --- a/dist/commands/reputation/modules/check/index.js +++ /dev/null @@ -1,96 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -exports.default = { - builder: (command) => { - return command - .setName("check") - .setDescription("Check reputation") - .addUserOption((option) => option - .setName("account") - .setDescription("The account you checking") - .setRequired(false)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - const { options, guild, user } = interaction; - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(guild); - const optionAccount = options === null || options === void 0 ? void 0 : options.getUser("account"); - if (!guild) - throw new Error("Server unavailable"); - if (!user) - throw new Error("User unavailable"); - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: (optionAccount || user).id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: (optionAccount || user).id, - }, - where: { - id: (optionAccount || user).id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(createGuildMember); - const reputationType = (reputation) => { - if (reputation < 0) - return `negative reputation of ${reputation}`; - if (reputation > 0) - return `positive reputation of ${reputation}`; - return "neutral reputation"; - }; - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle(optionAccount - ? `:loudspeaker:︱Showing ${optionAccount.username}'s reputation` - : ":loudspeaker:︱Showing your reputation") - .setDescription(optionAccount - ? `${optionAccount} have a ${reputationType(createGuildMember.user.reputationsEarned)}` - : `You have a ${reputationType(createGuildMember.user.reputationsEarned)}`) - .setTimestamp() - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - yield interaction.editReply({ - embeds: [interactionEmbed], - }); - }), -}; diff --git a/dist/commands/reputation/modules/repute/components/noSelfReputation.js b/dist/commands/reputation/modules/repute/components/noSelfReputation.js deleted file mode 100644 index 0e6b3ff..0000000 --- a/dist/commands/reputation/modules/repute/components/noSelfReputation.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = (to, from) => { - if ((from === null || from === void 0 ? void 0 : from.id) === (to === null || to === void 0 ? void 0 : to.id)) { - throw new Error("You can only repute other users"); - } -}; diff --git a/dist/commands/reputation/modules/repute/index.js b/dist/commands/reputation/modules/repute/index.js deleted file mode 100644 index b6d110b..0000000 --- a/dist/commands/reputation/modules/repute/index.js +++ /dev/null @@ -1,105 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -const noSelfReputation_1 = __importDefault(require("./components/noSelfReputation")); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const cooldown_1 = __importDefault(require("../../../../middlewares/cooldown")); -exports.default = { - builder: (command) => { - return command - .setName("repute") - .setDescription("Repute an account") - .addUserOption((option) => option - .setName("account") - .setDescription("The account you repute") - .setRequired(true)) - .addStringOption((option) => option - .setName("type") - .setDescription("Type of reputation") - .setRequired(true) - .addChoices({ name: "Positive", value: "positive" }, { - name: "Negative", - value: "negative", - })); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - const { options, user, guild, commandId } = interaction; - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(guild); - const optionAccount = options === null || options === void 0 ? void 0 : options.getUser("account"); - const optionType = options === null || options === void 0 ? void 0 : options.getString("type"); - if (!guild) - throw new Error("Server unavailable"); - if (!optionAccount) - throw new Error("User unavailable"); - // Pre-checks - (0, noSelfReputation_1.default)(optionAccount, user); - // Check if user is on cooldown otherwise create one - yield (0, cooldown_1.default)(guild, user, commandId, parseInt(process.env.REPUTATION_TIMEOUT)); - switch (optionType) { - case "positive": { - const createUser = yield database_1.default.user.upsert({ - where: { - id: optionAccount.id, - }, - update: { - reputationsEarned: { - increment: 1, - }, - }, - create: { - id: optionAccount.id, - reputationsEarned: 1, - }, - }); - logger_1.default.silly(createUser); - break; - } - case "negative": { - const createUser = yield database_1.default.user.upsert({ - where: { - id: optionAccount.id, - }, - update: { - reputationsEarned: { - decrement: 1, - }, - }, - create: { - id: optionAccount.id, - reputationsEarned: -1, - }, - }); - logger_1.default.silly(createUser); - break; - } - default: { - throw new Error("Invalid reputation type"); - } - } - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle(`:loudspeaker:︱Reputing ${optionAccount.username}`) - .setDescription(`You have given a ${optionType} repute to ${optionAccount}!`) - .setTimestamp() - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - yield interaction.editReply({ - embeds: [interactionEmbed], - }); - }), -}; diff --git a/dist/commands/shop/index.js b/dist/commands/shop/index.js deleted file mode 100644 index f21687f..0000000 --- a/dist/commands/shop/index.js +++ /dev/null @@ -1,51 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -// Dependencies -const discord_js_1 = require("discord.js"); -// Modules -const cpgg_1 = __importDefault(require("./modules/cpgg")); -const roles_1 = __importDefault(require("./modules/roles")); -// Function -exports.builder = new discord_js_1.SlashCommandBuilder() - .setName("shop") - .setDescription("Shop for credits and custom roles.") - .setDMPermission(false) - // Modules - .addSubcommand(cpgg_1.default.builder) - .addSubcommandGroup(roles_1.default.builder); -// Execute the command -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - const { options } = interaction; - switch (options.getSubcommand()) { - case "cpgg": { - yield cpgg_1.default.execute(interaction); - break; - } - default: { - throw new Error("Could not find module for that command."); - } - } - switch (options.getSubcommandGroup()) { - case "roles": { - yield roles_1.default.execute(interaction); - break; - } - default: { - throw new Error("Could not find module for that command."); - } - } -}); -exports.execute = execute; diff --git a/dist/commands/shop/modules/cpgg/index.js b/dist/commands/shop/modules/cpgg/index.js deleted file mode 100644 index 48a4643..0000000 --- a/dist/commands/shop/modules/cpgg/index.js +++ /dev/null @@ -1,175 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const axios_1 = __importDefault(require("axios")); -const discord_js_1 = require("discord.js"); -const uuid_1 = require("uuid"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const encryption_1 = __importDefault(require("../../../../helpers/encryption")); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -exports.default = { - builder: (command) => { - return command - .setName("cpgg") - .setDescription("Buy cpgg power.") - .addIntegerOption((option) => option - .setName("amount") - .setDescription("How much credits you want to withdraw.") - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - var _a, _b, _c, _d; - yield (0, deferReply_1.default)(interaction, true); - const { errorColor, successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const { options, guild, user, client } = interaction; - const optionAmount = options === null || options === void 0 ? void 0 : options.getInteger("amount"); - if (optionAmount === null) { - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`Amount is null.`); - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:dollar:] Gift") - .setDescription("We could not read your requested amount.") - .setTimestamp() - .setColor(errorColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - return interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [interactionEmbed], - }); - } - if (!guild) - throw new Error("Guild not found"); - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(createGuildMember); - const dmUser = (_b = (_a = client === null || client === void 0 ? void 0 : client.users) === null || _a === void 0 ? void 0 : _a.cache) === null || _b === void 0 ? void 0 : _b.get(user === null || user === void 0 ? void 0 : user.id); - if ((optionAmount || createGuildMember.creditsEarned) < 100) - throw new Error("You can't withdraw to CPGG below 100 credits."); - if ((optionAmount || createGuildMember.creditsEarned) > 1000000) - throw new Error("Amount or user credits is above 1.000.000."); - if (createGuildMember.creditsEarned < optionAmount) - throw new Error("You can't withdraw more than you have on your account."); - if (!createGuildMember.guild.apiCpggUrlIv || - !createGuildMember.guild.apiCpggUrlContent) - throw new Error("No API url available"); - if (!createGuildMember.guild.apiCpggTokenIv || - !createGuildMember.guild.apiCpggTokenContent) - throw new Error("No API token available"); - const code = (0, uuid_1.v4)(); - const url = encryption_1.default.decrypt({ - iv: createGuildMember.guild.apiCpggUrlIv, - content: createGuildMember.guild.apiCpggUrlContent, - }); - const api = axios_1.default === null || axios_1.default === void 0 ? void 0 : axios_1.default.create({ - baseURL: `${url}/api/`, - headers: { - Authorization: `Bearer ${encryption_1.default.decrypt({ - iv: createGuildMember.guild.apiCpggTokenIv, - content: createGuildMember.guild.apiCpggTokenContent, - })}`, - }, - }); - const shopUrl = `${url}/store`; - const buttons = new discord_js_1.ActionRowBuilder().addComponents(new discord_js_1.ButtonBuilder() - .setLabel("Redeem it here") - .setStyle(discord_js_1.ButtonStyle.Link) - .setEmoji("🏦") - .setURL(`${shopUrl}?voucher=${code}`)); - yield ((_d = api === null || api === void 0 ? void 0 : api.post("vouchers", { - uses: 1, - code, - credits: optionAmount || createGuildMember.creditsEarned, - memo: `${interaction === null || interaction === void 0 ? void 0 : interaction.createdTimestamp} - ${(_c = interaction === null || interaction === void 0 ? void 0 : interaction.user) === null || _c === void 0 ? void 0 : _c.id}`, - })) === null || _d === void 0 ? void 0 : _d.then(() => __awaiter(void 0, void 0, void 0, function* () { - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`Successfully created voucher.`); - createGuildMember.creditsEarned -= - optionAmount || createGuildMember.creditsEarned; - const updateGuildMember = yield database_1.default.guildMember.update({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - data: { - creditsEarned: { - decrement: optionAmount || createGuildMember.creditsEarned, - }, - }, - }); - logger_1.default.silly(updateGuildMember); - if (!interaction.guild) - throw new Error("Guild is undefined"); - const dmEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:shopping_cart:] CPGG") - .setDescription(`This voucher comes from **${interaction.guild.name}**.`) - .setTimestamp() - .addFields({ - name: "💶 Credits", - value: `${optionAmount || createGuildMember.creditsEarned}`, - inline: true, - }) - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - yield (dmUser === null || dmUser === void 0 ? void 0 : dmUser.send({ - embeds: [dmEmbed], - components: [buttons], - }).then((msg) => __awaiter(void 0, void 0, void 0, function* () { - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:shopping_cart:] CPGG") - .setDescription(`I have sent you the code in [DM](${msg.url})!`) - .setTimestamp() - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - yield (interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [interactionEmbed], - })); - }))); - }))); - return true; - }), -}; diff --git a/dist/commands/shop/modules/roles/index.js b/dist/commands/shop/modules/roles/index.js deleted file mode 100644 index 542a2f3..0000000 --- a/dist/commands/shop/modules/roles/index.js +++ /dev/null @@ -1,47 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Handlers -// Modules -const buy_1 = __importDefault(require("./modules/buy")); -const cancel_1 = __importDefault(require("./modules/cancel")); -const database_1 = __importDefault(require("../../../../handlers/database")); -exports.default = { - builder: (group) => { - return (group - .setName("roles") - .setDescription("Shop for custom roles.") - // Modules - .addSubcommand(buy_1.default.builder) - .addSubcommand(cancel_1.default.builder)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - if (!interaction.guild) - return; - const { options, guild } = interaction; - const getGuild = yield database_1.default.guild.findUnique({ - where: { id: guild.id }, - }); - if (!getGuild) - throw new Error("Guild not found"); - if (!getGuild.shopRolesEnabled) - throw new Error("This server has disabled shop roles."); - if ((options === null || options === void 0 ? void 0 : options.getSubcommand()) === "buy") { - yield buy_1.default.execute(interaction); - } - if ((options === null || options === void 0 ? void 0 : options.getSubcommand()) === "cancel") { - yield cancel_1.default.execute(interaction); - } - }), -}; diff --git a/dist/commands/shop/modules/roles/modules/buy/index.js b/dist/commands/shop/modules/roles/modules/buy/index.js deleted file mode 100644 index 8897822..0000000 --- a/dist/commands/shop/modules/roles/modules/buy/index.js +++ /dev/null @@ -1,162 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Dependencies -// Helpers -const discord_js_1 = require("discord.js"); -const deferReply_1 = __importDefault(require("../../../../../../handlers/deferReply")); -const getEmbedData_1 = __importDefault(require("../../../../../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../../../../../middlewares/logger")); -// Configurations -// import fetchUser from "../../../../../../helpers/userData"; -// Models -const database_1 = __importDefault(require("../../../../../../handlers/database")); -const pluralize_1 = __importDefault(require("../../../../../../helpers/pluralize")); -// Function -exports.default = { - builder: (command) => { - return command - .setName("buy") - .setDescription("Buy a custom role.") - .addStringOption((option) => option - .setName("name") - .setDescription("Name of the role you wish to buy.") - .setRequired(true)) - .addStringOption((option) => option - .setName("color") - .setDescription("Color of the role you wish to buy.") - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, true); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const { options, guild, user, member } = interaction; - const optionName = options === null || options === void 0 ? void 0 : options.getString("name"); - const optionColor = options === null || options === void 0 ? void 0 : options.getString("color"); - // If amount is null - if (optionName === null) - throw new Error("We could not read your requested name"); - yield (guild === null || guild === void 0 ? void 0 : guild.roles.create({ - name: optionName, - color: optionColor, - reason: `${user === null || user === void 0 ? void 0 : user.id} bought from shop`, - }).then((role) => __awaiter(void 0, void 0, void 0, function* () { - var _a; - const userId = "SNOWFLKAE"; - const guildId = "SNOWFLAKE"; - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId, - guildId, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: userId, - }, - where: { - id: userId, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guildId, - }, - where: { - id: guildId, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(createGuildMember); - // Get guild object - const pricePerHour = createGuildMember.guild.shopRolesPricePerHour; - const updateGuildMember = yield database_1.default.guildMember.update({ - where: { - userId_guildId: { - userId, - guildId, - }, - }, - data: { - creditsEarned: { decrement: pricePerHour }, - }, - }); - logger_1.default.silly(updateGuildMember); - const createShopRole = yield database_1.default.guildShopRoles.upsert({ - where: { - guildId_userId_roleId: { - guildId: guild.id, - userId: user.id, - roleId: role.id, - }, - }, - update: {}, - create: { - roleId: role.id, - lastPayed: new Date(), - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(createShopRole); - yield ((_a = member === null || member === void 0 ? void 0 : member.roles) === null || _a === void 0 ? void 0 : _a.add(role === null || role === void 0 ? void 0 : role.id)); - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`Role ${role === null || role === void 0 ? void 0 : role.name} was bought by ${user === null || user === void 0 ? void 0 : user.tag}`); - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:shopping_cart:] Buy") - .setDescription(`You bought **${optionName}** for **${(0, pluralize_1.default)(pricePerHour, "credit")}**.`) - .setTimestamp() - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - return interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [interactionEmbed], - }); - })).catch(() => { - throw new Error("Failed creating role."); - })); - }), -}; diff --git a/dist/commands/shop/modules/roles/modules/cancel/index.js b/dist/commands/shop/modules/roles/modules/cancel/index.js deleted file mode 100644 index 4bfb92f..0000000 --- a/dist/commands/shop/modules/roles/modules/cancel/index.js +++ /dev/null @@ -1,126 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Dependencies -// Helpers -const discord_js_1 = require("discord.js"); -// Configurations -// Models -const deferReply_1 = __importDefault(require("../../../../../../handlers/deferReply")); -const logger_1 = __importDefault(require("../../../../../../middlewares/logger")); -// Configurations -// Models -const database_1 = __importDefault(require("../../../../../../handlers/database")); -const getEmbedData_1 = __importDefault(require("../../../../../../helpers/getEmbedData")); -const pluralize_1 = __importDefault(require("../../../../../../helpers/pluralize")); -// Function -exports.default = { - builder: (command) => { - return command - .setName("cancel") - .setDescription("Cancel a purchase.") - .addRoleOption((option) => option - .setName("role") - .setDescription("Role you wish to cancel.") - .setRequired(true)); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - var _a; - yield (0, deferReply_1.default)(interaction, true); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const { options, guild, user, member } = interaction; - const optionRole = options.getRole("role"); - if (optionRole === null) - throw new Error("We could not read your requested role."); - if (!guild) - throw new Error("No guild specified"); - if (!user) - throw new Error("No user specified"); - const roleExist = yield database_1.default.guildShopRoles.findUnique({ - where: { - guildId_userId_roleId: { - guildId: guild.id, - userId: user.id, - roleId: optionRole.id, - }, - }, - }); - if (roleExist === null) - return; - yield ((_a = member === null || member === void 0 ? void 0 : member.roles) === null || _a === void 0 ? void 0 : _a.remove(optionRole === null || optionRole === void 0 ? void 0 : optionRole.id)); - yield (guild === null || guild === void 0 ? void 0 : guild.roles.delete(optionRole === null || optionRole === void 0 ? void 0 : optionRole.id, `${user === null || user === void 0 ? void 0 : user.id} canceled from shop`).then(() => __awaiter(void 0, void 0, void 0, function* () { - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(createGuildMember); - if (!createGuildMember) - throw new Error("Guild member not created"); - const deleteShopRole = yield database_1.default.guildShopRoles.delete({ - where: { - guildId_userId_roleId: { - guildId: guild === null || guild === void 0 ? void 0 : guild.id, - userId: user === null || user === void 0 ? void 0 : user.id, - roleId: optionRole === null || optionRole === void 0 ? void 0 : optionRole.id, - }, - }, - }); - logger_1.default.silly(deleteShopRole); - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setTitle("[:shopping_cart:] Cancel") - .setDescription(`You have canceled ${optionRole.name}.`) - .setTimestamp() - .setColor(successColor) - .addFields({ - name: "Your balance", - value: `${(0, pluralize_1.default)(createGuildMember.creditsEarned, "credit")}`, - }) - .setFooter({ text: footerText, iconURL: footerIcon }); - return interaction === null || interaction === void 0 ? void 0 : interaction.editReply({ - embeds: [interactionEmbed], - }); - }))); - }), -}; diff --git a/dist/commands/utils/index.js b/dist/commands/utils/index.js deleted file mode 100644 index aa1bf87..0000000 --- a/dist/commands/utils/index.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.builder = void 0; -const discord_js_1 = require("discord.js"); -// Modules -const about_1 = __importDefault(require("./modules/about")); -const avatar_1 = __importDefault(require("./modules/avatar")); -exports.builder = new discord_js_1.SlashCommandBuilder() - .setName("utils") - .setDescription("Common utility.") - // Modules - .addSubcommand(about_1.default.builder) - .addSubcommand(avatar_1.default.builder); -// Execute the command -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - switch (interaction.options.getSubcommand()) { - case "about": - yield about_1.default.execute(interaction); - break; - case "avatar": - yield avatar_1.default.execute(interaction); - break; - default: - throw new Error(`Unknown subcommand: ${interaction.options.getSubcommand()}`); - } -}); -exports.execute = execute; diff --git a/dist/commands/utils/modules/about/index.js b/dist/commands/utils/modules/about/index.js deleted file mode 100644 index 173d179..0000000 --- a/dist/commands/utils/modules/about/index.js +++ /dev/null @@ -1,101 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -/* eslint-disable no-loops/no-loops */ -// Dependencies -const date_fns_1 = require("date-fns"); -const discord_js_1 = require("discord.js"); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -// Configurations -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -// Function -exports.default = { - builder: (command) => { - return command - .setName("about") - .setDescription("Check information about this instance"); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, false); - if (!interaction.guild) - throw new Error("You need to be in a guild"); - const { client } = interaction; - // await cooldown( - // interaction.guild, - // interaction.user, - // interaction.commandId, - // 3600 - // ); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - // // Initialize a storage for the user ids - // const userIds = new Set(); - // // Iterate over all guilds (always cached) - // for await (const guild of client.guilds.cache.values()) { - // // Fetch all guild members and iterate over them - // for await (const member of (await guild.members.fetch()).values()) { - // // Fetch the user, if user already cached, returns value from cache - // // Will probably always return from cache - // const user = await client.users.fetch(member.id); - // // Check if user id is not already in set and user is not a bot - // if (!userIds.has(user.id) && !user.bot) { - // // Add unique user id to our set - // userIds.add(user.id); - // } - // } - // } - const buttons = new discord_js_1.ActionRowBuilder().addComponents(new discord_js_1.ButtonBuilder() - .setLabel("Support") - .setStyle(discord_js_1.ButtonStyle.Link) - .setEmoji("💬") - .setURL("https://discord.zyner.org"), new discord_js_1.ButtonBuilder() - .setLabel("Documentation") - .setStyle(discord_js_1.ButtonStyle.Link) - .setEmoji("📚") - .setURL("https://xyter.zyner.org")); - const interactionEmbed = new discord_js_1.EmbedBuilder() - .setColor(successColor) - .setTitle(":toolbox:︱About this instance") - .setDescription(`This bot instance is hosted by [${process.env.BOT_HOSTER_NAME}](${process.env.BOT_HOSTER_URL}) who might have modified the [source code](https://github.com/ZynerOrg/xyter).`) - .setFields({ - name: "Latency", - value: `${Math.round(client.ws.ping)} ms`, - inline: true, - }, { - name: "Servers (cached)", - value: `${client.guilds.cache.size}`, - inline: true, - }, { - name: "Users (cached)", - value: `${client.guilds.cache.reduce((a, g) => a + g.memberCount, 0)}`, - inline: true, - }, { - name: "Version", - value: `[${process.env.npm_package_version}](https://github.com/ZynerOrg/xyter/releases/tag/${process.env.npm_package_version})`, - inline: true, - }, { - name: "Since last restart", - value: `${(0, date_fns_1.formatDuration)((0, date_fns_1.intervalToDuration)({ - start: (0, date_fns_1.subMilliseconds)(new Date(), client.uptime), - end: new Date(), - }))}`, - inline: true, - }) - .setTimestamp() - .setFooter({ text: footerText, iconURL: footerIcon }); - yield interaction.editReply({ - embeds: [interactionEmbed], - components: [buttons], - }); - }), -}; diff --git a/dist/commands/utils/modules/avatar/index.js b/dist/commands/utils/modules/avatar/index.js deleted file mode 100644 index 6e3160e..0000000 --- a/dist/commands/utils/modules/avatar/index.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const deferReply_1 = __importDefault(require("../../../../handlers/deferReply")); -const getEmbedData_1 = __importDefault(require("../../../../helpers/getEmbedData")); -exports.default = { - builder: (command) => { - return command - .setName("avatar") - .setDescription("Check someones avatar!)") - .addUserOption((option) => option - .setName("user") - .setDescription("The user whose avatar you want to check")); - }, - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, deferReply_1.default)(interaction, false); - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - const userOption = interaction.options.getUser("user"); - const targetUser = userOption || interaction.user; - const embed = new discord_js_1.EmbedBuilder() - .setTitle(":toolbox:︱Avatar") - .setTimestamp(new Date()) - .setFooter({ text: footerText, iconURL: footerIcon }); - const avatarUrl = targetUser.displayAvatarURL(); - return interaction.editReply({ - embeds: [ - embed - .setDescription(userOption - ? `You can also [download it here](${avatarUrl})!` - : `Your avatar is available to [download here](${avatarUrl}).`) - .setThumbnail(avatarUrl) - .setColor(successColor), - ], - }); - }), -}; diff --git a/dist/events/guildCreate/index.js b/dist/events/guildCreate/index.js deleted file mode 100644 index bcf133a..0000000 --- a/dist/events/guildCreate/index.js +++ /dev/null @@ -1,60 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -const database_1 = __importDefault(require("../../handlers/database")); -const updatePresence_1 = __importDefault(require("../../handlers/updatePresence")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.options = { - type: "on", -}; -// Execute the function -const execute = (guild) => __awaiter(void 0, void 0, void 0, function* () { - const { client } = guild; - (0, updatePresence_1.default)(client); - // Create guildMember object - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: guild.ownerId, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: guild.ownerId, - }, - where: { - id: guild.ownerId, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - }); - logger_1.default.silly(createGuildMember); -}); -exports.execute = execute; diff --git a/dist/events/guildDelete/index.js b/dist/events/guildDelete/index.js deleted file mode 100644 index 7b9b88d..0000000 --- a/dist/events/guildDelete/index.js +++ /dev/null @@ -1,43 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -const database_1 = __importDefault(require("../../handlers/database")); -const updatePresence_1 = __importDefault(require("../../handlers/updatePresence")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.options = { - type: "on", -}; -// Execute the function -const execute = (guild) => __awaiter(void 0, void 0, void 0, function* () { - const { client } = guild; - (0, updatePresence_1.default)(client); - // Delete guildMember objects - const deleteGuildMembers = database_1.default.guildMember.deleteMany({ - where: { - guildId: guild.id, - }, - }); - // Delete guild object - const deleteGuild = database_1.default.guild.deleteMany({ - where: { - id: guild.id, - }, - }); - // The transaction runs synchronously so deleteUsers must run last. - yield database_1.default.$transaction([deleteGuildMembers, deleteGuild]); - logger_1.default.silly(deleteGuildMembers); - logger_1.default.silly(deleteGuild); -}); -exports.execute = execute; diff --git a/dist/events/guildMemberAdd/audits.js b/dist/events/guildMemberAdd/audits.js deleted file mode 100644 index 7595180..0000000 --- a/dist/events/guildMemberAdd/audits.js +++ /dev/null @@ -1,71 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../handlers/database")); -const getEmbedData_1 = __importDefault(require("../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.default = { - execute: (member) => __awaiter(void 0, void 0, void 0, function* () { - var _a; - const { client, guild } = member; - const getGuild = yield database_1.default.guild.findUnique({ - where: { id: member.guild.id }, - }); - if (!getGuild) - throw new Error("Guild not found"); - if (getGuild.auditsEnabled !== true) - return; - if (!getGuild.auditsChannelId) { - throw new Error("Channel not found"); - } - const embedConfig = yield (0, getEmbedData_1.default)(guild); - const channel = client.channels.cache.get(getGuild.auditsChannelId); - if (!channel) - throw new Error("Channel not found"); - if (channel.type !== discord_js_1.ChannelType.GuildText) { - throw new Error("Channel must be a text channel"); - } - const embed = new discord_js_1.EmbedBuilder() - .setTimestamp(new Date()) - .setAuthor({ - name: "Member Joined", - iconURL: (_a = client.user) === null || _a === void 0 ? void 0 : _a.displayAvatarURL(), - }) - .setFooter({ - text: embedConfig.footerText, - iconURL: embedConfig.footerIcon, - }); - yield channel - .send({ - embeds: [ - embed - .setColor(embedConfig.successColor) - .setDescription(`${member.user} - (${member.user.tag})`) - .addFields([ - { - name: "Account Age", - value: `${member.user.createdAt}`, - }, - ]), - ], - }) - .then(() => { - logger_1.default.debug(`Audit log sent for event guildMemberAdd`); - }) - .catch(() => { - throw new Error("Audit log failed to send"); - }); - }), -}; diff --git a/dist/events/guildMemberAdd/index.js b/dist/events/guildMemberAdd/index.js deleted file mode 100644 index e02a103..0000000 --- a/dist/events/guildMemberAdd/index.js +++ /dev/null @@ -1,65 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -const database_1 = __importDefault(require("../../handlers/database")); -const updatePresence_1 = __importDefault(require("../../handlers/updatePresence")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -const audits_1 = __importDefault(require("./audits")); -const joinMessage_1 = __importDefault(require("./joinMessage")); -exports.options = { - type: "on", -}; -// Execute the function -const execute = (member) => __awaiter(void 0, void 0, void 0, function* () { - const { client, user, guild } = member; - logger_1.default.silly(`New member: ${user.tag} (${user.id}) added to guild: ${guild.name} (${guild.id})`); - yield audits_1.default.execute(member); - yield joinMessage_1.default.execute(member); - (0, updatePresence_1.default)(client); - // Create guildMember object - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - }); - logger_1.default.silly(createGuildMember); -}); -exports.execute = execute; diff --git a/dist/events/guildMemberAdd/joinMessage.js b/dist/events/guildMemberAdd/joinMessage.js deleted file mode 100644 index 31b0751..0000000 --- a/dist/events/guildMemberAdd/joinMessage.js +++ /dev/null @@ -1,52 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../handlers/database")); -const getEmbedData_1 = __importDefault(require("../../helpers/getEmbedData")); -exports.default = { - execute: (member) => __awaiter(void 0, void 0, void 0, function* () { - const { footerText, footerIcon, successColor } = yield (0, getEmbedData_1.default)(member.guild); - const getGuild = yield database_1.default.guild.findUnique({ - where: { id: member.guild.id }, - }); - if (!getGuild) - throw new Error("Guild not found"); - const { client } = member; - if (getGuild.welcomeEnabled !== true) - return; - if (!getGuild.welcomeJoinChannelId) - return; - const channel = client.channels.cache.get(`${getGuild.welcomeJoinChannelId}`); - if (!channel) - throw new Error("Channel not found"); - if (channel.type !== discord_js_1.ChannelType.GuildText) - throw new Error("Channel is not a text channel"); - channel.send({ - embeds: [ - new discord_js_1.EmbedBuilder() - .setColor(successColor) - .setTitle(`${member.user.username} has joined the server!`) - .setThumbnail(member.user.displayAvatarURL()) - .setDescription(getGuild.welcomeJoinChannelMessage || - "Configure a join message in the `/settings guild welcome`.") - .setTimestamp() - .setFooter({ - text: footerText, - iconURL: footerIcon, - }), - ], - }); - }), -}; diff --git a/dist/events/guildMemberRemove/audits.js b/dist/events/guildMemberRemove/audits.js deleted file mode 100644 index 23683df..0000000 --- a/dist/events/guildMemberRemove/audits.js +++ /dev/null @@ -1,69 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../handlers/database")); -const getEmbedData_1 = __importDefault(require("../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.default = { - execute: (member) => __awaiter(void 0, void 0, void 0, function* () { - var _a; - const { client, guild } = member; - const getGuild = yield database_1.default.guild.findUnique({ - where: { id: member.guild.id }, - }); - if (!getGuild) - throw new Error("Guild not found"); - if (getGuild.auditsEnabled !== true) - return; - if (!getGuild.auditsChannelId) { - throw new Error("Channel not found"); - } - const embedConfig = yield (0, getEmbedData_1.default)(guild); - const channel = client.channels.cache.get(getGuild.auditsChannelId); - if ((channel === null || channel === void 0 ? void 0 : channel.type) !== discord_js_1.ChannelType.GuildText) { - throw new Error("Channel must be a text channel"); - } - const embed = new discord_js_1.EmbedBuilder() - .setTimestamp(new Date()) - .setAuthor({ - name: "Member Left", - iconURL: (_a = client.user) === null || _a === void 0 ? void 0 : _a.displayAvatarURL(), - }) - .setFooter({ - text: embedConfig.footerText, - iconURL: embedConfig.footerIcon, - }); - channel - .send({ - embeds: [ - embed - .setColor(embedConfig.errorColor) - .setDescription(`${member.user} - (${member.user.tag})`) - .addFields([ - { - name: "Account Age", - value: `${member.user.createdAt}`, - }, - ]), - ], - }) - .then(() => { - logger_1.default.debug(`Audit log sent for event guildMemberRemove.`); - }) - .catch(() => { - throw new Error("Audit log failed to send"); - }); - }), -}; diff --git a/dist/events/guildMemberRemove/index.js b/dist/events/guildMemberRemove/index.js deleted file mode 100644 index a0243d9..0000000 --- a/dist/events/guildMemberRemove/index.js +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -const database_1 = __importDefault(require("../../handlers/database")); -const updatePresence_1 = __importDefault(require("../../handlers/updatePresence")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -const audits_1 = __importDefault(require("./audits")); -const leaveMessage_1 = __importDefault(require("./leaveMessage")); -exports.options = { - type: "on", -}; -// Execute the function -const execute = (member) => __awaiter(void 0, void 0, void 0, function* () { - const { client, user, guild } = member; - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`Removed member: ${user.tag} (${user.id}) from guild: ${guild.name} (${guild.id})`); - yield audits_1.default.execute(member); - yield leaveMessage_1.default.execute(member); - (0, updatePresence_1.default)(client); - // Delete guildMember object - const deleteGuildMember = yield database_1.default.guildMember.deleteMany({ - where: { - userId: user.id, - guildId: guild.id, - }, - }); - logger_1.default.silly(deleteGuildMember); -}); -exports.execute = execute; diff --git a/dist/events/guildMemberRemove/leaveMessage.js b/dist/events/guildMemberRemove/leaveMessage.js deleted file mode 100644 index 3e3f0e8..0000000 --- a/dist/events/guildMemberRemove/leaveMessage.js +++ /dev/null @@ -1,52 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../handlers/database")); -const getEmbedData_1 = __importDefault(require("../../helpers/getEmbedData")); -exports.default = { - execute: (member) => __awaiter(void 0, void 0, void 0, function* () { - const { footerText, footerIcon, errorColor } = yield (0, getEmbedData_1.default)(member.guild); - const getGuild = yield database_1.default.guild.findUnique({ - where: { id: member.guild.id }, - }); - if (!getGuild) - throw new Error("Guild not found"); - const { client } = member; - if (getGuild.welcomeEnabled !== true) - return; - if (!getGuild.welcomeLeaveChannelId) - return; - const channel = client.channels.cache.get(`${getGuild.welcomeLeaveChannelId}`); - if (!channel) - throw new Error("Channel not found"); - if (channel.type !== discord_js_1.ChannelType.GuildText) - throw new Error("Channel is not a text channel"); - channel.send({ - embeds: [ - new discord_js_1.EmbedBuilder() - .setColor(errorColor) - .setTitle(`${member.user.username} has left the server!`) - .setThumbnail(member.user.displayAvatarURL()) - .setDescription(getGuild.welcomeLeaveChannelMessage || - "Configure a leave message in the `/settings guild welcome`.") - .setTimestamp() - .setFooter({ - text: footerText, - iconURL: footerIcon, - }), - ], - }); - }), -}; diff --git a/dist/events/interactionCreate/audits.js b/dist/events/interactionCreate/audits.js deleted file mode 100644 index aa660a8..0000000 --- a/dist/events/interactionCreate/audits.js +++ /dev/null @@ -1,68 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../handlers/database")); -const getEmbedData_1 = __importDefault(require("../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.default = { - execute: (interaction) => __awaiter(void 0, void 0, void 0, function* () { - if (interaction === null) - return; - if (interaction.guild === null) - return; - const getGuild = yield database_1.default.guild.findUnique({ - where: { id: interaction.guild.id }, - }); - if (!getGuild) - throw new Error("Guild not found"); - const { footerText, footerIcon, successColor } = yield (0, getEmbedData_1.default)(interaction.guild); - const { client } = interaction; - if (getGuild.auditsEnabled !== true) - return; - if (!getGuild.auditsChannelId) - return; - const channel = client.channels.cache.get(`${getGuild.auditsChannelId}`); - if (!channel) - return; - if (channel.type !== discord_js_1.ChannelType.GuildText) - return; - channel - .send({ - embeds: [ - new discord_js_1.EmbedBuilder() - .setColor(successColor) - .setDescription(` - **Interaction created by** ${interaction.user.username} **in** ${interaction.channel} - ㅤ**Interaction ID**: ${interaction.id} - ㅤ**Type**: ${interaction.type} - ㅤ**User ID**: ${interaction.user.id} - `) - .setThumbnail(interaction.user.displayAvatarURL()) - .setTimestamp() - .setFooter({ - text: footerText, - iconURL: footerIcon, - }), - ], - }) - .then(() => { - var _a, _b; - logger_1.default.debug(`Audit log sent for event interactionCreate in guild ${(_a = interaction === null || interaction === void 0 ? void 0 : interaction.guild) === null || _a === void 0 ? void 0 : _a.name} (${(_b = interaction === null || interaction === void 0 ? void 0 : interaction.guild) === null || _b === void 0 ? void 0 : _b.id})`); - }) - .catch(() => { - logger_1.default.silly("Failed to send audit log for event interactionCreate"); - }); - }), -}; diff --git a/dist/events/interactionCreate/handlers/button/index.js b/dist/events/interactionCreate/handlers/button/index.js deleted file mode 100644 index 7b069c5..0000000 --- a/dist/events/interactionCreate/handlers/button/index.js +++ /dev/null @@ -1,44 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - var _a; - if (!interaction.isButton()) - return; - const { customId } = interaction; - const currentButton = yield (_a = `../../../buttons/${customId}`, Promise.resolve().then(() => __importStar(require(_a)))); - if (!currentButton) - throw new Error(`Unknown button ${customId}`); - yield currentButton.execute(interaction); -}); diff --git a/dist/events/interactionCreate/handlers/command/index.js b/dist/events/interactionCreate/handlers/command/index.js deleted file mode 100644 index f24dae0..0000000 --- a/dist/events/interactionCreate/handlers/command/index.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - if (!interaction.isCommand()) - return; - const { client, commandName } = interaction; - const currentCommand = client.commands.get(commandName); - if (!currentCommand) - throw new Error(`Unknown command ${commandName}`); - yield currentCommand.execute(interaction); -}); diff --git a/dist/events/interactionCreate/handlers/index.js b/dist/events/interactionCreate/handlers/index.js deleted file mode 100644 index 13706f4..0000000 --- a/dist/events/interactionCreate/handlers/index.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.handleCommandInteraction = exports.execute = void 0; -const discord_js_1 = require("discord.js"); -const getEmbedData_1 = __importDefault(require("../../../helpers/getEmbedData")); -const button_1 = __importDefault(require("./button")); -const command_1 = __importDefault(require("./command")); -// Send interactions to all available handlers -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, button_1.default)(interaction); - yield (0, command_1.default)(interaction); -}); -exports.execute = execute; -// Handle interactions from commands -const handleCommandInteraction = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - const { errorColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(interaction.guild); - yield (0, command_1.default)(interaction).catch((err) => { - const buttons = new discord_js_1.ActionRowBuilder().addComponents(new discord_js_1.ButtonBuilder() - .setLabel("Report Problem") - .setStyle(discord_js_1.ButtonStyle.Link) - .setEmoji("📝") - .setURL("https://discord.zyner.org")); - return interaction.editReply({ - embeds: [ - new discord_js_1.EmbedBuilder() - .setTitle(`:no_entry_sign:︱Your request failed`) - .setDescription(`${err.message}`) - .setColor(errorColor) - .setTimestamp(new Date()) - .setFooter({ text: footerText, iconURL: footerIcon }), - ], - components: [buttons], - }); - }); -}); -exports.handleCommandInteraction = handleCommandInteraction; diff --git a/dist/events/interactionCreate/index.js b/dist/events/interactionCreate/index.js deleted file mode 100644 index d7906ee..0000000 --- a/dist/events/interactionCreate/index.js +++ /dev/null @@ -1,38 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -// 3rd party dependencies -const discord_js_1 = require("discord.js"); -const logger_1 = __importDefault(require("../../middlewares/logger")); -// Dependencies -const audits_1 = __importDefault(require("./audits")); -const handlers_1 = require("./handlers"); -exports.options = { - type: "on", -}; -// Execute the event -const execute = (interaction) => __awaiter(void 0, void 0, void 0, function* () { - const { guild, id } = interaction; - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`New interaction: ${id} in guild: ${guild === null || guild === void 0 ? void 0 : guild.name} (${guild === null || guild === void 0 ? void 0 : guild.id})`); - switch (interaction.type) { - case discord_js_1.InteractionType.ApplicationCommand: - yield (0, handlers_1.handleCommandInteraction)(interaction); - break; - default: - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.error(`Unknown interaction type: ${interaction.type}`); - } - yield audits_1.default.execute(interaction); -}); -exports.execute = execute; diff --git a/dist/events/messageCreate/index.js b/dist/events/messageCreate/index.js deleted file mode 100644 index 97574b3..0000000 --- a/dist/events/messageCreate/index.js +++ /dev/null @@ -1,26 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -const modules_1 = __importDefault(require("./modules")); -exports.options = { - type: "on", -}; -// Execute the function -const execute = (message) => __awaiter(void 0, void 0, void 0, function* () { - yield modules_1.default.credits.execute(message); - yield modules_1.default.points.execute(message); - yield modules_1.default.counters.execute(message); -}); -exports.execute = execute; diff --git a/dist/events/messageCreate/modules/counters/index.js b/dist/events/messageCreate/modules/counters/index.js deleted file mode 100644 index a7d11dd..0000000 --- a/dist/events/messageCreate/modules/counters/index.js +++ /dev/null @@ -1,69 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -exports.default = { - execute: (message) => __awaiter(void 0, void 0, void 0, function* () { - const { guild, author, content, channel } = message; - if (!guild) - return; - if (author.bot) - return; - if ((channel === null || channel === void 0 ? void 0 : channel.type) !== discord_js_1.ChannelType.GuildText) - return; - const messages = yield message.channel.messages.fetch({ limit: 2 }); - const lastMessage = messages.last(); - const channelCounter = yield database_1.default.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: channel.id, - }, - }, - }); - if (!channelCounter) { - logger_1.default.debug("No counters found in channel."); - return; - } - if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.author.id) === author.id && - channel.id === channelCounter.channelId) { - logger_1.default.silly(`${author.username} sent the last message therefor not allowing again.`); - yield message.delete(); - return false; - } - if (content !== channelCounter.triggerWord) { - logger_1.default.silly(`Counter word ${channelCounter.triggerWord} does not match message ${content}`); - yield message.delete(); - return false; - } - const updateGuildCounter = yield database_1.default.guildCounter.update({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: channel.id, - }, - }, - data: { - count: { - increment: 1, - }, - }, - }); - logger_1.default.silly(updateGuildCounter); - if (!updateGuildCounter) - logger_1.default.error(`Failed to update counter - ${updateGuildCounter}`); - }), -}; diff --git a/dist/events/messageCreate/modules/credits/index.js b/dist/events/messageCreate/modules/credits/index.js deleted file mode 100644 index d99136c..0000000 --- a/dist/events/messageCreate/modules/credits/index.js +++ /dev/null @@ -1,70 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const give_1 = __importDefault(require("../../../../helpers/credits/give")); -const cooldown_1 = __importDefault(require("../../../../middlewares/cooldown")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -exports.default = { - execute: (message) => __awaiter(void 0, void 0, void 0, function* () { - const { guild, author, content, channel } = message; - if (!guild) - return; - if (author.bot) - return; - if (channel.type !== discord_js_1.ChannelType.GuildText) - return; - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: author.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: author.id, - }, - where: { - id: author.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(createGuildMember); - if (content.length < createGuildMember.guild.creditsMinimumLength) - return; - yield (0, cooldown_1.default)(guild, author, "event-messageCreate-credits", createGuildMember.guild.creditsTimeout, true); - yield (0, give_1.default)(guild, author, createGuildMember.guild.creditsRate); - }), -}; diff --git a/dist/events/messageCreate/modules/index.js b/dist/events/messageCreate/modules/index.js deleted file mode 100644 index 1ebf005..0000000 --- a/dist/events/messageCreate/modules/index.js +++ /dev/null @@ -1,13 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const counters_1 = __importDefault(require("./counters")); -const credits_1 = __importDefault(require("./credits")); -const points_1 = __importDefault(require("./points")); -exports.default = { - counters: counters_1.default, - credits: credits_1.default, - points: points_1.default, -}; diff --git a/dist/events/messageCreate/modules/points/index.js b/dist/events/messageCreate/modules/points/index.js deleted file mode 100644 index 5604ebf..0000000 --- a/dist/events/messageCreate/modules/points/index.js +++ /dev/null @@ -1,84 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../../../handlers/database")); -const cooldown_1 = __importDefault(require("../../../../middlewares/cooldown")); -const logger_1 = __importDefault(require("../../../../middlewares/logger")); -exports.default = { - execute: (message) => __awaiter(void 0, void 0, void 0, function* () { - const { guild, author, content, channel } = message; - if (!guild) - return; - if (author.bot) - return; - if (channel.type !== discord_js_1.ChannelType.GuildText) - return; - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: author.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: author.id, - }, - where: { - id: author.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(createGuildMember); - if (content.length < createGuildMember.guild.pointsMinimumLength) - return; - yield (0, cooldown_1.default)(guild, author, "event-messageCreate-points", createGuildMember.guild.pointsTimeout, true); - const updateGuildMember = yield database_1.default.guildMember.update({ - where: { - userId_guildId: { - userId: author.id, - guildId: guild.id, - }, - }, - data: { - pointsEarned: { - increment: createGuildMember.guild.pointsRate, - }, - }, - }); - logger_1.default.silly(updateGuildMember); - if (!updateGuildMember) - throw new Error("Failed to update guildMember object"); - }), -}; diff --git a/dist/events/messageDelete/audits.js b/dist/events/messageDelete/audits.js deleted file mode 100644 index 14c1450..0000000 --- a/dist/events/messageDelete/audits.js +++ /dev/null @@ -1,72 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../handlers/database")); -const getEmbedData_1 = __importDefault(require("../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.default = { - execute: (message) => __awaiter(void 0, void 0, void 0, function* () { - if (message === null) - return; - if (message.guild === null) - return; - const { footerText, footerIcon, successColor } = yield (0, getEmbedData_1.default)(message.guild); - const getGuild = yield database_1.default.guild.findUnique({ - where: { id: message.guild.id }, - }); - if (!getGuild) - throw new Error("Guild not found"); - const { client } = message; - if (!getGuild) - throw new Error("Guild not found"); - if (getGuild.auditsEnabled !== true) - return; - if (!getGuild.auditsChannelId) - return; - const channel = client.channels.cache.get(`${getGuild.auditsChannelId}`); - if (!channel) - return; - if (channel.type !== discord_js_1.ChannelType.GuildText) - return; - channel - .send({ - embeds: [ - new discord_js_1.EmbedBuilder() - .setColor(successColor) - .setAuthor({ - name: message.author.username, - iconURL: message.author.displayAvatarURL(), - }) - .setDescription(` - **Message sent by** ${message.author} **deleted in** ${message.channel} - ${message.content} - `) - .setTimestamp() - .setFooter({ - text: footerText, - iconURL: footerIcon, - }), - ], - }) - .then(() => { - var _a, _b; - logger_1.default.info(`Audit log sent for event messageDelete in guild ${(_a = message === null || message === void 0 ? void 0 : message.guild) === null || _a === void 0 ? void 0 : _a.name} (${(_b = message === null || message === void 0 ? void 0 : message.guild) === null || _b === void 0 ? void 0 : _b.id})`); - }) - .catch(() => { - var _a, _b; - throw new Error(`Audit log failed to send for event messageDelete in guild ${(_a = message === null || message === void 0 ? void 0 : message.guild) === null || _a === void 0 ? void 0 : _a.name} (${(_b = message === null || message === void 0 ? void 0 : message.guild) === null || _b === void 0 ? void 0 : _b.id})`); - }); - }), -}; diff --git a/dist/events/messageDelete/index.js b/dist/events/messageDelete/index.js deleted file mode 100644 index e742293..0000000 --- a/dist/events/messageDelete/index.js +++ /dev/null @@ -1,26 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -const audits_1 = __importDefault(require("./audits")); -const counter_1 = __importDefault(require("./modules/counter")); -exports.options = { - type: "on", -}; -// Execute the function -const execute = (message) => __awaiter(void 0, void 0, void 0, function* () { - yield audits_1.default.execute(message); - yield (0, counter_1.default)(message); -}); -exports.execute = execute; diff --git a/dist/events/messageDelete/modules/counter.js b/dist/events/messageDelete/modules/counter.js deleted file mode 100644 index dfa138e..0000000 --- a/dist/events/messageDelete/modules/counter.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Models -const database_1 = __importDefault(require("../../../handlers/database")); -const logger_1 = __importDefault(require("../../../middlewares/logger")); -exports.default = (message) => __awaiter(void 0, void 0, void 0, function* () { - const { guild, channel, author, content } = message; - if (!guild) - throw new Error("Guild not found"); - if (!channel) - throw new Error("Channel not found"); - const channelCounter = yield database_1.default.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: channel.id, - }, - }, - }); - if (!channelCounter) - throw new Error("No counter found in channel."); - const messages = yield message.channel.messages.fetch({ limit: 1 }); - const lastMessage = messages.last(); - if (!lastMessage) - return; - if (content !== channelCounter.triggerWord) - return; - if (lastMessage.author.id === message.author.id) - return; - channel === null || channel === void 0 ? void 0 : channel.send(`${author} said **${channelCounter.triggerWord}**.`); - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`${author} said ${channelCounter.triggerWord} in ${channel}`); - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`User: ${author === null || author === void 0 ? void 0 : author.tag} (${author === null || author === void 0 ? void 0 : author.id}) in guild: ${guild === null || guild === void 0 ? void 0 : guild.name} (${guild === null || guild === void 0 ? void 0 : guild.id}) said the counter word: ${channelCounter.triggerWord}`); -}); diff --git a/dist/events/messageUpdate/audits.js b/dist/events/messageUpdate/audits.js deleted file mode 100644 index 35c350d..0000000 --- a/dist/events/messageUpdate/audits.js +++ /dev/null @@ -1,74 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -/* eslint-disable no-loops/no-loops */ -const discord_js_1 = require("discord.js"); -const database_1 = __importDefault(require("../../handlers/database")); -const getEmbedData_1 = __importDefault(require("../../helpers/getEmbedData")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.default = { - execute: (oldMessage, newMessage) => __awaiter(void 0, void 0, void 0, function* () { - if (oldMessage === null) - return; - if (newMessage === null) - return; - if (oldMessage.guild === null) - return; - if (newMessage.guild === null) - return; - const { footerText, footerIcon, successColor } = yield (0, getEmbedData_1.default)(newMessage.guild); - const getGuild = yield database_1.default.guild.findUnique({ - where: { id: oldMessage.guild.id }, - }); - if (!getGuild) - throw new Error("Guild not found"); - const { client } = oldMessage; - if (getGuild.auditsEnabled !== true) - return; - if (!getGuild.auditsChannelId) - return; - const channel = client.channels.cache.get(`${getGuild.auditsChannelId}`); - if (!channel) - return; - if (channel.type !== discord_js_1.ChannelType.GuildText) - return; - channel - .send({ - embeds: [ - new discord_js_1.EmbedBuilder() - .setColor(successColor) - .setAuthor({ - name: newMessage.author.username, - iconURL: newMessage.author.displayAvatarURL(), - }) - .setDescription(` - **Message edited in** ${newMessage.channel} [jump to message](https://discord.com/channels/${newMessage.guild.id}/${newMessage.channel.id}/${newMessage.id}) - `) - .setTimestamp() - .setFooter({ - text: footerText, - iconURL: footerIcon, - }), - ], - }) - .then(() => { - var _a, _b; - logger_1.default.info(`Audit log sent for event messageUpdate in guild ${(_a = newMessage === null || newMessage === void 0 ? void 0 : newMessage.guild) === null || _a === void 0 ? void 0 : _a.name} (${(_b = newMessage === null || newMessage === void 0 ? void 0 : newMessage.guild) === null || _b === void 0 ? void 0 : _b.id})`); - }) - .catch(() => { - var _a, _b; - throw new Error(`Audit log failed to send for event messageUpdate in guild ${(_a = newMessage === null || newMessage === void 0 ? void 0 : newMessage.guild) === null || _a === void 0 ? void 0 : _a.name} (${(_b = newMessage === null || newMessage === void 0 ? void 0 : newMessage.guild) === null || _b === void 0 ? void 0 : _b.id})`); - }); - }), -}; diff --git a/dist/events/messageUpdate/index.js b/dist/events/messageUpdate/index.js deleted file mode 100644 index f7079f4..0000000 --- a/dist/events/messageUpdate/index.js +++ /dev/null @@ -1,33 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -const logger_1 = __importDefault(require("../../middlewares/logger")); -// Modules -const counter_1 = __importDefault(require("./modules/counter")); -const audits_1 = __importDefault(require("./audits")); -exports.options = { - type: "on", -}; -// Execute the function -const execute = (oldMessage, newMessage) => __awaiter(void 0, void 0, void 0, function* () { - const { author, guild } = newMessage; - yield audits_1.default.execute(oldMessage, newMessage); - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`Message update event fired by ${author.tag} (${author.id}) in guild: ${guild === null || guild === void 0 ? void 0 : guild.name} (${guild === null || guild === void 0 ? void 0 : guild.id})`); - if (author === null || author === void 0 ? void 0 : author.bot) - return logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`Message update event fired by bot`); - yield (0, counter_1.default)(newMessage); - return true; -}); -exports.execute = execute; diff --git a/dist/events/messageUpdate/modules/counter.js b/dist/events/messageUpdate/modules/counter.js deleted file mode 100644 index bf5c2db..0000000 --- a/dist/events/messageUpdate/modules/counter.js +++ /dev/null @@ -1,46 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Models -const database_1 = __importDefault(require("../../../handlers/database")); -const logger_1 = __importDefault(require("../../../middlewares/logger")); -exports.default = (message) => __awaiter(void 0, void 0, void 0, function* () { - const { guild, channel, author, content } = message; - if (!guild) - throw new Error("Guild not found"); - if (!channel) - throw new Error("Channel not found"); - const channelCounter = yield database_1.default.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: channel.id, - }, - }, - }); - if (!channelCounter) - return logger_1.default.debug("No counters found in channel."); - if (content === channelCounter.triggerWord) - return logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`User: ${author === null || author === void 0 ? void 0 : author.tag} (${author === null || author === void 0 ? void 0 : author.id}) in guild: ${guild === null || guild === void 0 ? void 0 : guild.name} (${guild === null || guild === void 0 ? void 0 : guild.id}) said the counter word: ${channelCounter.triggerWord}`); - yield message - .delete() - .then(() => __awaiter(void 0, void 0, void 0, function* () { - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`${author} said ${channelCounter.triggerWord} in ${channel}`); - yield (channel === null || channel === void 0 ? void 0 : channel.send(`${author} said **${channelCounter.triggerWord}**.`)); - })) - .catch((error) => { - return logger_1.default.error(error); - }); - return true; -}); diff --git a/dist/events/rateLimit/index.js b/dist/events/rateLimit/index.js deleted file mode 100644 index fa59d44..0000000 --- a/dist/events/rateLimit/index.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.options = { - type: "on", -}; -// Function to execute the event -const execute = (client) => { - var _a; - logger_1.default.warn(`Discord's API client (${(_a = client === null || client === void 0 ? void 0 : client.user) === null || _a === void 0 ? void 0 : _a.tag}) is rate-limited!`); -}; -exports.execute = execute; diff --git a/dist/events/ready/index.js b/dist/events/ready/index.js deleted file mode 100644 index 41e1a22..0000000 --- a/dist/events/ready/index.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -// Helpers -const deployCommands_1 = __importDefault(require("../../handlers/deployCommands")); -const updatePresence_1 = __importDefault(require("../../handlers/updatePresence")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.options = { - type: "once", -}; -// Execute the event -const execute = (client) => __awaiter(void 0, void 0, void 0, function* () { - logger_1.default.info("Discord's API client is ready!"); - (0, updatePresence_1.default)(client); - yield (0, deployCommands_1.default)(client); -}); -exports.execute = execute; diff --git a/dist/handlers/command/index.js b/dist/handlers/command/index.js deleted file mode 100644 index 1d9b5b9..0000000 --- a/dist/handlers/command/index.js +++ /dev/null @@ -1,92 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __asyncValues = (this && this.__asyncValues) || function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.register = void 0; -const checkDirectory_1 = __importDefault(require("../../helpers/checkDirectory")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -// Register the commands. -const register = (client) => __awaiter(void 0, void 0, void 0, function* () { - var _a, e_1, _b, _c; - logger_1.default.info("🔧 Started command management"); - const commandNames = yield (0, checkDirectory_1.default)("commands"); - if (!commandNames) - return logger_1.default.warn("No available commands found"); - const totalCommands = commandNames.length; - let loadedCommands = 0; - logger_1.default.info(`🔧 Loading ${totalCommands} commands`); - // Import an command. - const importCommand = (name) => __awaiter(void 0, void 0, void 0, function* () { - var _e; - const command = yield (_e = `../../commands/${name}`, Promise.resolve().then(() => __importStar(require(_e)))); - client.commands.set(command.builder.name, command); - return loadedCommands++; - }); - try { - for (var _d = true, commandNames_1 = __asyncValues(commandNames), commandNames_1_1; commandNames_1_1 = yield commandNames_1.next(), _a = commandNames_1_1.done, !_a;) { - _c = commandNames_1_1.value; - _d = false; - try { - const commandName = _c; - yield importCommand(commandName).then(() => { - return logger_1.default.verbose(`🔧 Loaded command "${commandName}"`); - }); - if (loadedCommands === totalCommands) { - return logger_1.default.info("🔧 All commands loaded"); - } - } - finally { - _d = true; - } - } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { - try { - if (!_d && !_a && (_b = commandNames_1.return)) yield _b.call(commandNames_1); - } - finally { if (e_1) throw e_1.error; } - } - return true; -}); -exports.register = register; diff --git a/dist/handlers/database/index.js b/dist/handlers/database/index.js deleted file mode 100644 index 2f6ad5e..0000000 --- a/dist/handlers/database/index.js +++ /dev/null @@ -1,25 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const client_1 = require("@prisma/client"); -const logger_1 = __importDefault(require("../../middlewares/logger")); -const prisma = new client_1.PrismaClient(); -prisma.$use((params, next) => __awaiter(void 0, void 0, void 0, function* () { - const before = Date.now(); - const result = yield next(params); - const after = Date.now(); - logger_1.default.debug(`Query ${params.model}.${params.action} took ${after - before}ms`); - return result; -})); -exports.default = prisma; diff --git a/dist/handlers/deferReply/index.js b/dist/handlers/deferReply/index.js deleted file mode 100644 index d098ce7..0000000 --- a/dist/handlers/deferReply/index.js +++ /dev/null @@ -1,37 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const getEmbedData_1 = __importDefault(require("../../helpers/getEmbedData")); -exports.default = (interaction, ephemeral) => __awaiter(void 0, void 0, void 0, function* () { - if (!interaction.isRepliable()) - throw new Error(`Cannot reply to an interaction that is not repliable`); - yield interaction.deferReply({ - ephemeral, - }); - const embedConfig = yield (0, getEmbedData_1.default)(interaction.guild); - yield interaction.editReply({ - embeds: [ - new discord_js_1.EmbedBuilder() - .setFooter({ - text: embedConfig.footerText, - iconURL: embedConfig.footerIcon, - }) - .setTimestamp(new Date()) - .setTitle("⏳︱Your request are being processed") - .setColor(embedConfig.waitColor) - .setDescription("This might take a while, please wait..."), - ], - }); -}); diff --git a/dist/handlers/deployCommands/index.js b/dist/handlers/deployCommands/index.js deleted file mode 100644 index bfc7406..0000000 --- a/dist/handlers/deployCommands/index.js +++ /dev/null @@ -1,44 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.default = (client) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Destructure the client. - const { application } = client; - if (!application) - throw new Error("No application found"); - // 2. Log that we are starting the command management. - logger_1.default.info("🔧 Started command deployment"); - // 3. Get the commands. - const commands = []; - client.commands.forEach((command) => { - commands.push(command.builder.toJSON()); - logger_1.default.verbose(`🔧 Loaded command "${command.builder.name}"`); - }); - // 4. Set the commands. - yield application.commands.set(commands).then(() => { - logger_1.default.info("🔧 Deployed commands globally"); - }); - // 5. Tell the user that development mode is enabled. - if (process.env.NODE_ENV === "development") { - logger_1.default.info("🔧 Development mode enabled"); - yield application.commands - .set(commands, process.env.DISCORD_GUILD_ID) - .then(() => { - logger_1.default.info(`🔧 Deployed commands to guild`); - }); - } - // 6. Log that we are done with the command management. - logger_1.default.info("🔧 Finished command deployment"); -}); diff --git a/dist/handlers/event/index.js b/dist/handlers/event/index.js deleted file mode 100644 index 38cadf3..0000000 --- a/dist/handlers/event/index.js +++ /dev/null @@ -1,105 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __asyncValues = (this && this.__asyncValues) || function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.register = void 0; -const checkDirectory_1 = __importDefault(require("../../helpers/checkDirectory")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -// Registers all available events. -const register = (client) => __awaiter(void 0, void 0, void 0, function* () { - var _a, e_1, _b, _c; - logger_1.default.info("📡 Started event management"); - const eventNames = yield (0, checkDirectory_1.default)("events"); - if (!eventNames) - return logger_1.default.warn("No available events found"); - const totalEvents = eventNames.length; - let loadedEvents = 0; - logger_1.default.info(`📡 Loading ${totalEvents} events`); - // Import an event. - const importEvent = (name) => __awaiter(void 0, void 0, void 0, function* () { - var _e; - const event = yield (_e = `../../events/${name}`, Promise.resolve().then(() => __importStar(require(_e)))); - // Create a new event execute function. - const eventExecutor = (...args) => __awaiter(void 0, void 0, void 0, function* () { - yield event.execute(...args); - }); - switch (event.options.type) { - case "once": - client.once(name, eventExecutor); - break; - case "on": - client.on(name, eventExecutor); - break; - default: - throw new Error(`📡 Invalid event type for event: ${name}`); - } - return loadedEvents++; - }); - try { - for (var _d = true, eventNames_1 = __asyncValues(eventNames), eventNames_1_1; eventNames_1_1 = yield eventNames_1.next(), _a = eventNames_1_1.done, !_a;) { - _c = eventNames_1_1.value; - _d = false; - try { - const eventName = _c; - yield importEvent(eventName).then(() => { - return logger_1.default.verbose(`📡 Loaded event "${eventName}"`); - }); - if (loadedEvents === totalEvents) { - return logger_1.default.info("📡 All events loaded"); - } - } - finally { - _d = true; - } - } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { - try { - if (!_d && !_a && (_b = eventNames_1.return)) yield _b.call(eventNames_1); - } - finally { if (e_1) throw e_1.error; } - } - return true; -}); -exports.register = register; diff --git a/dist/handlers/schedule/index.js b/dist/handlers/schedule/index.js deleted file mode 100644 index d547396..0000000 --- a/dist/handlers/schedule/index.js +++ /dev/null @@ -1,57 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.start = void 0; -const node_schedule_1 = __importDefault(require("node-schedule")); -const checkDirectory_1 = __importDefault(require("../../helpers/checkDirectory")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -// Start all jobs that are in the schedules directory -const start = (client) => __awaiter(void 0, void 0, void 0, function* () { - logger_1.default.info("⏰ Started job management"); - const jobNames = yield (0, checkDirectory_1.default)("schedules"); - if (!jobNames) - return logger_1.default.warn("⏰ No available jobs found"); - return yield Promise.all(jobNames.map((jobName) => __awaiter(void 0, void 0, void 0, function* () { - var _a; - const job = yield (_a = `../../schedules/${jobName}`, Promise.resolve().then(() => __importStar(require(_a)))); - return node_schedule_1.default.scheduleJob(job.options.schedule, () => __awaiter(void 0, void 0, void 0, function* () { - logger_1.default.verbose(`⏰ Performed the job "${jobName}"`); - yield job.execute(client); - })); - }))); -}); -exports.start = start; diff --git a/dist/handlers/updatePresence/index.js b/dist/handlers/updatePresence/index.js deleted file mode 100644 index c026be1..0000000 --- a/dist/handlers/updatePresence/index.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// Dependencies -const discord_js_1 = require("discord.js"); -const logger_1 = __importDefault(require("../../middlewares/logger")); -// Function -exports.default = (client) => { - // 1. Destructure the client. - const { guilds, user } = client; - if (!user) - throw new Error("No user found"); - // 2. Get the total number of guilds and members. - const memberCount = guilds.cache.reduce((a, g) => a + g.memberCount, 0); - const guildCount = guilds.cache.size; - // 3. Set the presence. - user.setPresence({ - activities: [ - { - name: `${guildCount} guilds | ${memberCount} members`, - type: discord_js_1.ActivityType.Watching, - }, - ], - }); - // 4. Log the presence. - return logger_1.default.info(`👀 Presence set to "${guildCount} guilds | ${memberCount} members"`); -}; diff --git a/dist/helpers/baseEmbeds/index.js b/dist/helpers/baseEmbeds/index.js deleted file mode 100644 index 9c2be31..0000000 --- a/dist/helpers/baseEmbeds/index.js +++ /dev/null @@ -1,47 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.error = exports.wait = exports.success = void 0; -const discord_js_1 = require("discord.js"); -const getEmbedData_1 = __importDefault(require("../getEmbedData")); -// Construct a base embed for success messages -const success = (guild, title) => __awaiter(void 0, void 0, void 0, function* () { - const { successColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(guild); - return new discord_js_1.EmbedBuilder() - .setTimestamp(new Date()) - .setTitle(title) - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); -}); -exports.success = success; -// Construct a base embed for wait messages -const wait = (guild, title) => __awaiter(void 0, void 0, void 0, function* () { - const { waitColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(guild); - return new discord_js_1.EmbedBuilder() - .setTimestamp(new Date()) - .setTitle(title) - .setColor(waitColor) - .setFooter({ text: footerText, iconURL: footerIcon }); -}); -exports.wait = wait; -// Construct a base embed for error messages -const error = (guild, title) => __awaiter(void 0, void 0, void 0, function* () { - const { errorColor, footerText, footerIcon } = yield (0, getEmbedData_1.default)(guild); - return new discord_js_1.EmbedBuilder() - .setTimestamp(new Date()) - .setTitle(title) - .setColor(errorColor) - .setFooter({ text: footerText, iconURL: footerIcon }); -}); -exports.error = error; diff --git a/dist/helpers/capitalizeFirstLetter/index.js b/dist/helpers/capitalizeFirstLetter/index.js deleted file mode 100644 index 84071db..0000000 --- a/dist/helpers/capitalizeFirstLetter/index.js +++ /dev/null @@ -1,5 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = (text) => { - return text.charAt(0).toUpperCase() + text.slice(1); -}; diff --git a/dist/helpers/checkDirectory/index.js b/dist/helpers/checkDirectory/index.js deleted file mode 100644 index e250f61..0000000 --- a/dist/helpers/checkDirectory/index.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const fs_1 = __importDefault(require("fs")); -const fsPromises = fs_1.default.promises; -exports.default = (path) => __awaiter(void 0, void 0, void 0, function* () { - const result = yield fsPromises.readdir(`${__dirname}/../../${path}`); - return result; -}); diff --git a/dist/helpers/checkPermission/index.js b/dist/helpers/checkPermission/index.js deleted file mode 100644 index c234e11..0000000 --- a/dist/helpers/checkPermission/index.js +++ /dev/null @@ -1,8 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = (interaction, permission) => { - if (!interaction.memberPermissions) - throw new Error("Could not check user for permissions"); - if (!interaction.memberPermissions.has(permission)) - throw new Error("Permission denied"); -}; diff --git a/dist/helpers/credits/give.js b/dist/helpers/credits/give.js deleted file mode 100644 index 95948ba..0000000 --- a/dist/helpers/credits/give.js +++ /dev/null @@ -1,64 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const database_1 = __importDefault(require("../../handlers/database")); -const transactionRules_1 = __importDefault(require("./transactionRules")); -exports.default = (guild, user, amount) => __awaiter(void 0, void 0, void 0, function* () { - return yield database_1.default.$transaction((tx) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Check if the transaction is valid. - (0, transactionRules_1.default)(guild, user, amount); - // 2. Make the transaction. - const recipient = yield tx.guildMember.upsert({ - update: { - creditsEarned: { - increment: amount, - }, - }, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - creditsEarned: amount, - }, - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - }); - // 3. Verify that the recipient actually is created. - if (!recipient) - throw new Error("No recipient available"); - // 4. Return the recipient. - return recipient; - })); -}); diff --git a/dist/helpers/credits/set.js b/dist/helpers/credits/set.js deleted file mode 100644 index 4ba0e91..0000000 --- a/dist/helpers/credits/set.js +++ /dev/null @@ -1,62 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const database_1 = __importDefault(require("../../handlers/database")); -const transactionRules_1 = __importDefault(require("./transactionRules")); -exports.default = (guild, user, amount) => __awaiter(void 0, void 0, void 0, function* () { - return yield database_1.default.$transaction((tx) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Check if the transaction is valid. - (0, transactionRules_1.default)(guild, user, amount); - // 2. Make the transaction. - const recipient = yield tx.guildMember.upsert({ - update: { - creditsEarned: amount, - }, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - creditsEarned: amount, - }, - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - }); - // 3. Verify that the recipient actually is created. - if (!recipient) - throw new Error("No recipient available"); - // 4. Return the recipient. - return recipient; - })); -}); diff --git a/dist/helpers/credits/take.js b/dist/helpers/credits/take.js deleted file mode 100644 index 1224c70..0000000 --- a/dist/helpers/credits/take.js +++ /dev/null @@ -1,64 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const database_1 = __importDefault(require("../../handlers/database")); -const transactionRules_1 = __importDefault(require("./transactionRules")); -exports.default = (guild, user, amount) => __awaiter(void 0, void 0, void 0, function* () { - return yield database_1.default.$transaction((tx) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Check if the transaction is valid. - (0, transactionRules_1.default)(guild, user, amount); - // 2. Make the transaction. - const recipient = yield tx.guildMember.upsert({ - update: { - creditsEarned: { - decrement: amount, - }, - }, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - creditsEarned: -amount, - }, - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - }); - // 3. Verify that the recipient credits are not below zero. - if (recipient.creditsEarned < -100) - throw new Error("User do not have enough credits"); - // 4. Return the recipient. - return recipient; - })); -}); diff --git a/dist/helpers/credits/transactionRules.js b/dist/helpers/credits/transactionRules.js deleted file mode 100644 index 861983f..0000000 --- a/dist/helpers/credits/transactionRules.js +++ /dev/null @@ -1,16 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = (guild, user, amount) => { - // 1. Verify that the amount is not above 100.000.000 credits. - if (amount > 100000000) { - throw new Error("You can't give more than 1.000.000 credits."); - } - // 2. Verify that the amount is not below 1 credits. - if (amount <= 0) { - throw new Error("You can't give below one credit."); - } - // 3. Verify that the user is not an bot. - if (user.bot) { - throw new Error("You can't give to an bot."); - } -}; diff --git a/dist/helpers/credits/transfer.js b/dist/helpers/credits/transfer.js deleted file mode 100644 index f93b869..0000000 --- a/dist/helpers/credits/transfer.js +++ /dev/null @@ -1,105 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const database_1 = __importDefault(require("../../handlers/database")); -const transactionRules_1 = __importDefault(require("./transactionRules")); -exports.default = (guild, from, to, amount) => __awaiter(void 0, void 0, void 0, function* () { - return yield database_1.default.$transaction((tx) => __awaiter(void 0, void 0, void 0, function* () { - // 1. Decrement amount from the sender. - const sender = yield tx.guildMember.upsert({ - update: { - creditsEarned: { - decrement: amount, - }, - }, - create: { - user: { - connectOrCreate: { - create: { - id: from.id, - }, - where: { - id: from.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - creditsEarned: -amount, - }, - where: { - userId_guildId: { - userId: from.id, - guildId: guild.id, - }, - }, - }); - // 4. Verify that the sender's balance didn't go below zero. - if (sender.creditsEarned < 0) { - throw new Error(`${from} doesn't have enough to send ${amount}`); - } - // 5. Check if the transactions is valid. - (0, transactionRules_1.default)(guild, from, amount); - (0, transactionRules_1.default)(guild, to, amount); - // 6. Verify that sender and recipient are not the same user. - if (from.id === to.id) - throw new Error("You can't transfer to yourself."); - // 7. Increment the recipient's balance by amount. - const recipient = yield tx.guildMember.upsert({ - update: { - creditsEarned: { - increment: amount, - }, - }, - create: { - user: { - connectOrCreate: { - create: { - id: to.id, - }, - where: { - id: to.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - creditsEarned: amount, - }, - where: { - userId_guildId: { - userId: to.id, - guildId: guild.id, - }, - }, - }); - return recipient; - })); -}); diff --git a/dist/helpers/encryption/index.js b/dist/helpers/encryption/index.js deleted file mode 100644 index 986d9c1..0000000 --- a/dist/helpers/encryption/index.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const crypto_1 = __importDefault(require("crypto")); -const iv = crypto_1.default.randomBytes(16); -// Encrypts a string -const encrypt = (text) => { - const cipher = crypto_1.default.createCipheriv(process.env.ENCRYPTION_ALGORITHM, process.env.ENCRYPTION_SECRET, iv); - const encrypted = Buffer.concat([cipher.update(text), cipher.final()]); - return { - iv: iv.toString("hex"), - content: encrypted.toString("hex"), - }; -}; -// Decrypts a string -const decrypt = (hash) => { - const decipher = crypto_1.default.createDecipheriv(process.env.ENCRYPTION_ALGORITHM, process.env.ENCRYPTION_SECRET, Buffer.from(hash.iv, "hex")); - const decrypted = Buffer.concat([ - decipher.update(Buffer.from(hash.content, "hex")), - decipher.final(), - ]); - return decrypted.toString(); -}; -exports.default = { - encrypt, - decrypt, -}; diff --git a/dist/helpers/getEmbedData/index.js b/dist/helpers/getEmbedData/index.js deleted file mode 100644 index 1d9cf64..0000000 --- a/dist/helpers/getEmbedData/index.js +++ /dev/null @@ -1,75 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const database_1 = __importDefault(require("../../handlers/database")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.default = (guild) => __awaiter(void 0, void 0, void 0, function* () { - const { EMBED_COLOR_SUCCESS, EMBED_COLOR_WAIT, EMBED_COLOR_ERROR, EMBED_FOOTER_TEXT, EMBED_FOOTER_ICON, } = process.env; - const defaultEmbedConfig = { - successColor: EMBED_COLOR_SUCCESS, - waitColor: EMBED_COLOR_WAIT, - errorColor: EMBED_COLOR_ERROR, - footerText: EMBED_FOOTER_TEXT, - footerIcon: EMBED_FOOTER_ICON, - }; - if (!guild) { - return defaultEmbedConfig; - } - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: guild === null || guild === void 0 ? void 0 : guild.ownerId, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: guild.ownerId, - }, - where: { - id: guild.ownerId, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(createGuildMember); - if (!createGuildMember) { - return defaultEmbedConfig; - } - return { - successColor: createGuildMember.guild.embedColorSuccess, - waitColor: createGuildMember.guild.embedColorWait, - errorColor: createGuildMember.guild.embedColorError, - footerText: createGuildMember.guild.embedFooterText, - footerIcon: createGuildMember.guild.embedFooterIcon, - }; -}); diff --git a/dist/helpers/pluralize/index.js b/dist/helpers/pluralize/index.js deleted file mode 100644 index edeac7e..0000000 --- a/dist/helpers/pluralize/index.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.default = (count, noun, suffix) => { - const result = `${count} ${noun}${count !== 1 ? suffix || "s" : ""}`; - logger_1.default === null || logger_1.default === void 0 ? void 0 : logger_1.default.silly(`Pluralized ${count} to ${result}`); - return result; -}; diff --git a/dist/helpers/upsertGuildMember/index.js b/dist/helpers/upsertGuildMember/index.js deleted file mode 100644 index 8be93f0..0000000 --- a/dist/helpers/upsertGuildMember/index.js +++ /dev/null @@ -1,49 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const database_1 = __importDefault(require("../../handlers/database")); -exports.default = (guildMember) => __awaiter(void 0, void 0, void 0, function* () { - const { guild, user } = guildMember; - return yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - }); -}); diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index 9580842..0000000 --- a/dist/index.js +++ /dev/null @@ -1,38 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); // discord.js -require("dotenv/config"); -const command_1 = require("./handlers/command"); -const event_1 = require("./handlers/event"); -const schedule_1 = require("./handlers/schedule"); -// Main process that starts all other sub processes -const main = () => __awaiter(void 0, void 0, void 0, function* () { - // Initiate client object - const client = new discord_js_1.Client({ - intents: [ - discord_js_1.GatewayIntentBits.Guilds, - discord_js_1.GatewayIntentBits.GuildMembers, - discord_js_1.GatewayIntentBits.GuildMessages, - discord_js_1.GatewayIntentBits.MessageContent, - ], - }); - // Create command collection - client.commands = new discord_js_1.Collection(); - // Start critical handlers - yield (0, schedule_1.start)(client); - yield (0, event_1.register)(client); - yield (0, command_1.register)(client); - // Authorize with Discord's API - yield client.login(process.env.DISCORD_TOKEN); -}); -// Start main process -main(); diff --git a/dist/interfaces/Command.js b/dist/interfaces/Command.js deleted file mode 100644 index c8ad2e5..0000000 --- a/dist/interfaces/Command.js +++ /dev/null @@ -1,2 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/interfaces/EncryptionData.js b/dist/interfaces/EncryptionData.js deleted file mode 100644 index c8ad2e5..0000000 --- a/dist/interfaces/EncryptionData.js +++ /dev/null @@ -1,2 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/interfaces/Event.js b/dist/interfaces/Event.js deleted file mode 100644 index c8ad2e5..0000000 --- a/dist/interfaces/Event.js +++ /dev/null @@ -1,2 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/interfaces/EventOptions.js b/dist/interfaces/EventOptions.js deleted file mode 100644 index c8ad2e5..0000000 --- a/dist/interfaces/EventOptions.js +++ /dev/null @@ -1,2 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/interfaces/Job.js b/dist/interfaces/Job.js deleted file mode 100644 index c8ad2e5..0000000 --- a/dist/interfaces/Job.js +++ /dev/null @@ -1,2 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/middlewares/cooldown/index.js b/dist/middlewares/cooldown/index.js deleted file mode 100644 index ce53556..0000000 --- a/dist/middlewares/cooldown/index.js +++ /dev/null @@ -1,89 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const date_fns_1 = require("date-fns"); -const database_1 = __importDefault(require("../../handlers/database")); -const logger_1 = __importDefault(require("../logger")); -exports.default = (guild, user, id, cooldown, silent) => __awaiter(void 0, void 0, void 0, function* () { - // Check if user has a timeout - const isOnCooldown = yield database_1.default.cooldown.findUnique({ - where: { - guildId_userId_timeoutId: { - guildId: guild.id, - userId: user.id, - timeoutId: id, - }, - }, - }); - logger_1.default.silly(isOnCooldown); - if (isOnCooldown) { - const { userId, timeoutId, createdAt } = isOnCooldown; - const dueDate = (0, date_fns_1.add)(createdAt, { seconds: cooldown }); - const duration = (0, date_fns_1.formatDuration)((0, date_fns_1.intervalToDuration)({ - start: new Date(), - end: dueDate, - })); - if ((0, date_fns_1.isPast)(dueDate)) { - return yield database_1.default.cooldown.delete({ - where: { - guildId_userId_timeoutId: { - guildId: guild.id, - userId: user.id, - timeoutId: id, - }, - }, - }); - } - if (silent) { - return logger_1.default.verbose(`User ${userId} is on cooldown for ${timeoutId}, it ends in ${duration}.`); - } - throw new Error(`You need to wait for ${duration} before you can do that again`); - } - const createCooldown = yield database_1.default.cooldown.upsert({ - where: { - guildId_userId_timeoutId: { - userId: user.id, - guildId: guild.id, - timeoutId: id, - }, - }, - update: {}, - create: { - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - timeoutId: id, - cooldown, - }, - }); - logger_1.default.silly(createCooldown); - return createCooldown; -}); diff --git a/dist/middlewares/logger/index.js b/dist/middlewares/logger/index.js deleted file mode 100644 index b7686a9..0000000 --- a/dist/middlewares/logger/index.js +++ /dev/null @@ -1,25 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const winston_1 = __importDefault(require("winston")); -require("winston-daily-rotate-file"); -const { combine, timestamp, printf, errors, colorize, align, json } = winston_1.default.format; -exports.default = winston_1.default.createLogger({ - level: process.env.LOG_LEVEL || "info", - transports: [ - new winston_1.default.transports.DailyRotateFile({ - filename: "logs/combined-%DATE%.log", - datePattern: "YYYY-MM-DD", - maxFiles: "14d", - format: combine(timestamp(), json()), - }), - new winston_1.default.transports.Console({ - format: combine(errors({ stack: true, trace: true }), // <-- use errors format - colorize({ all: true }), timestamp({ - format: "YYYY-MM-DD HH:MM:ss", - }), align(), printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`)), - }), - ], -}); diff --git a/dist/schedules/cooldowns/index.js b/dist/schedules/cooldowns/index.js deleted file mode 100644 index 437afbe..0000000 --- a/dist/schedules/cooldowns/index.js +++ /dev/null @@ -1,73 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __asyncValues = (this && this.__asyncValues) || function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -/* eslint-disable no-loops/no-loops */ -const date_fns_1 = require("date-fns"); -const database_1 = __importDefault(require("../../handlers/database")); -const logger_1 = __importDefault(require("../../middlewares/logger")); -exports.options = { - schedule: "*/30 * * * *", // https://crontab.guru/ -}; -// Execute the job -const execute = () => __awaiter(void 0, void 0, void 0, function* () { - var _a, e_1, _b, _c; - const cooldownsObj = yield database_1.default.cooldown.findMany(); - try { - for (var _d = true, cooldownsObj_1 = __asyncValues(cooldownsObj), cooldownsObj_1_1; cooldownsObj_1_1 = yield cooldownsObj_1.next(), _a = cooldownsObj_1_1.done, !_a;) { - _c = cooldownsObj_1_1.value; - _d = false; - try { - const cooldownObj = _c; - const { guildId, userId, timeoutId, cooldown, createdAt } = cooldownObj; - const dueDate = (0, date_fns_1.add)(createdAt, { seconds: cooldown }); - if (!(0, date_fns_1.isPast)(dueDate)) - return; - const duration = (0, date_fns_1.formatDuration)((0, date_fns_1.intervalToDuration)({ - start: new Date(), - end: dueDate, - })); - const deleteCooldown = yield database_1.default.cooldown.delete({ - where: { - guildId_userId_timeoutId: { - guildId, - userId, - timeoutId, - }, - }, - }); - logger_1.default.silly(deleteCooldown); - logger_1.default.verbose(`User ${userId} is on cooldown for ${timeoutId}, it ends in ${duration}.`); - } - finally { - _d = true; - } - } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { - try { - if (!_d && !_a && (_b = cooldownsObj_1.return)) yield _b.call(cooldownsObj_1); - } - finally { if (e_1) throw e_1.error; } - } -}); -exports.execute = execute; diff --git a/dist/schedules/shop/index.js b/dist/schedules/shop/index.js deleted file mode 100644 index fb18058..0000000 --- a/dist/schedules/shop/index.js +++ /dev/null @@ -1,21 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = exports.options = void 0; -const roles_1 = require("./modules/roles"); -exports.options = { - schedule: "*/5 * * * *", // https://crontab.guru/ -}; -// Execute the function -const execute = (client) => __awaiter(void 0, void 0, void 0, function* () { - yield (0, roles_1.execute)(client); -}); -exports.execute = execute; diff --git a/dist/schedules/shop/modules/roles/components/dueForPayment.js b/dist/schedules/shop/modules/roles/components/dueForPayment.js deleted file mode 100644 index b26f837..0000000 --- a/dist/schedules/shop/modules/roles/components/dueForPayment.js +++ /dev/null @@ -1,13 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = void 0; -const logger_1 = __importDefault(require("../../../../../middlewares/logger")); -// Execute the dueForPayment function -const execute = (_client, role) => { - const { roleId } = role; - logger_1.default.silly(`Shop role ${roleId} is not due for payment.`); -}; -exports.execute = execute; diff --git a/dist/schedules/shop/modules/roles/components/overDueForPayment.js b/dist/schedules/shop/modules/roles/components/overDueForPayment.js deleted file mode 100644 index a63a29e..0000000 --- a/dist/schedules/shop/modules/roles/components/overDueForPayment.js +++ /dev/null @@ -1,124 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = void 0; -const logger_1 = __importDefault(require("../../../../../middlewares/logger")); -const database_1 = __importDefault(require("../../../../../handlers/database")); -// Execute the component -const execute = (client, role) => __awaiter(void 0, void 0, void 0, function* () { - const { guildId, userId, roleId } = role; - if (!userId) - throw new Error("User ID not found for shop role."); - const rGuild = client.guilds.cache.get(guildId); - if (!rGuild) - throw new Error("Guild not found."); - const rMember = yield rGuild.members.fetch(userId); - if (!rMember) - throw new Error("Member not found."); - const rRole = rMember.roles.cache.get(roleId); - if (!rRole) - throw new Error("Role not found."); - logger_1.default.debug(`Shop role ${roleId} is due for payment.`); - const getGuildMember = yield database_1.default.guildMember.findUnique({ - where: { - userId_guildId: { - userId, - guildId, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(getGuildMember); - if (!getGuildMember) - throw new Error("Could not find guild member."); - const pricePerHour = getGuildMember.guild.shopRolesPricePerHour; - if (getGuildMember.creditsEarned < pricePerHour) { - yield rMember.roles - .remove(roleId) - .then(() => __awaiter(void 0, void 0, void 0, function* () { - const deleteShopRole = yield database_1.default.guildShopRoles.delete({ - where: { - guildId_userId_roleId: { - guildId, - userId, - roleId, - }, - }, - }); - logger_1.default.silly(deleteShopRole); - logger_1.default.silly(`Shop role document ${roleId} has been deleted from user ${userId}.`); - })) - .catch(() => { - throw new Error(`Failed removing role from user.`); - }); - throw new Error("User does not have enough credits."); - } - const createGuildMember = yield database_1.default.guildMember.upsert({ - where: { - userId_guildId: { - userId, - guildId, - }, - }, - update: { creditsEarned: { decrement: pricePerHour } }, - create: { - creditsEarned: -pricePerHour, - user: { - connectOrCreate: { - create: { - id: userId, - }, - where: { - id: userId, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guildId, - }, - where: { - id: guildId, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger_1.default.silly(createGuildMember); - logger_1.default.silly(`User ${userId} has been updated.`); - const updateGuildShopRole = yield database_1.default.guildShopRoles.update({ - where: { - guildId_userId_roleId: { - guildId, - userId, - roleId, - }, - }, - data: { - lastPayed: new Date(), - }, - }); - logger_1.default.silly(updateGuildShopRole); - logger_1.default.silly(`Shop role ${roleId} has been updated.`); - logger_1.default.debug(`Shop role ${roleId} has been paid.`); -}); -exports.execute = execute; diff --git a/dist/schedules/shop/modules/roles/index.js b/dist/schedules/shop/modules/roles/index.js deleted file mode 100644 index 060df75..0000000 --- a/dist/schedules/shop/modules/roles/index.js +++ /dev/null @@ -1,60 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __asyncValues = (this && this.__asyncValues) || function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.execute = void 0; -const database_1 = __importDefault(require("../../../../handlers/database")); -const dueForPayment_1 = require("./components/dueForPayment"); -const overDueForPayment_1 = require("./components/overDueForPayment"); -// Execute the roles function -const execute = (client) => __awaiter(void 0, void 0, void 0, function* () { - var _a, e_1, _b, _c; - const roles = yield database_1.default.guildShopRoles.findMany(); - try { - for (var _d = true, roles_1 = __asyncValues(roles), roles_1_1; roles_1_1 = yield roles_1.next(), _a = roles_1_1.done, !_a;) { - _c = roles_1_1.value; - _d = false; - try { - const role = _c; - const { lastPayed } = role; - const nextPayment = new Date(lastPayed.setHours(lastPayed.getHours() + 1)); - const now = new Date(); - if (nextPayment > now) { - (0, dueForPayment_1.execute)(client, role); - return; - } - if (nextPayment < now) { - yield (0, overDueForPayment_1.execute)(client, role); - } - } - finally { - _d = true; - } - } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { - try { - if (!_d && !_a && (_b = roles_1.return)) yield _b.call(roles_1); - } - finally { if (e_1) throw e_1.error; } - } -}); -exports.execute = execute; diff --git a/docker-compose.yml b/docker-compose.yml index 3abf3c8..cfc2ab8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,28 +1,36 @@ version: "3.7" - services: - app: - container_name: app - image: zyner/xyter:main + xyter: + container_name: xyter + # image: zyner/xyter + build: + context: . restart: unless-stopped env_file: - .env volumes: - ./logs:/logs + depends_on: + - mariadb + + phpmyadmin: + container_name: phpmyadmin + image: phpmyadmin:5 + restart: unless-stopped + ports: + - 8080:80 + environment: + - PMA_HOST=mariadb + depends_on: + - mariadb mariadb: container_name: mariadb image: lscr.io/linuxserver/mariadb:latest restart: unless-stopped - environment: - - PUID=1000 - - PGID=1000 - - TZ=Region/City - - MYSQL_ROOT_PASSWORD=root - - MYSQL_DATABASE=database - - MYSQL_USER=username - - MYSQL_PASSWORD=password - volumes: - - ./db:/config ports: - 3306:3306 + volumes: + - ./db:/config + env_file: + - .env diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100755 index 0000000..2bb8b2b --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +check_db_connection() { + mysqladmin ping -h "${DB_HOST}" -u "${DB_USER}" -p"${DB_PASSWORD}" 2>/dev/null +} + +wait_for_db() { + echo "Checking database connection..." + until check_db_connection; do + echo "Waiting for the database..." + sleep 1 + done + echo "Database is ready!" +} + +# Parse the DATABASE_URL into individual variables +DB_URL="${DATABASE_URL#*://}" +DB_USER="${DB_URL%%:*}" +DB_URL="${DB_URL#*:}" +DB_PASSWORD="${DB_URL%%@*}" +DB_HOST="${DB_URL#*@}" +DB_HOST="${DB_HOST%%/*}" +DB_NAME="${DB_URL#*/}" + +wait_for_db +"$@" diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..55e11a8 --- /dev/null +++ b/flake.lock @@ -0,0 +1,43 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1674236650, + "narHash": "sha256-B4GKL1YdJnII6DQNNJ4wDW1ySJVx2suB1h/v4Ql8J0Q=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "cfb43ad7b941d9c3606fb35d91228da7ebddbfc5", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..ab6f638 --- /dev/null +++ b/flake.nix @@ -0,0 +1,34 @@ +{ + description = "A Nix-flake-based Node.js development environment for Xyter"; + + inputs = { + flake-utils.url = "github:numtide/flake-utils"; + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + }; + + outputs = { self, flake-utils, nixpkgs }: + flake-utils.lib.eachDefaultSystem (system: + let + overlays = [ (self: super: rec { nodejs = super.nodejs-19_x; }) ]; + pkgs = import nixpkgs { inherit overlays system; }; + in { + devShells.default = pkgs.mkShell { + buildInputs = with pkgs; [ + node2nix + docker + nodejs + + # Node Packages + nodePackages.typescript + nodePackages.prisma + ]; + shellHook = with pkgs; '' + export PRISMA_MIGRATION_ENGINE_BINARY="${prisma-engines}/bin/migration-engine" + export PRISMA_QUERY_ENGINE_BINARY="${prisma-engines}/bin/query-engine" + export PRISMA_QUERY_ENGINE_LIBRARY="${prisma-engines}/lib/libquery_engine.node" + export PRISMA_INTROSPECTION_ENGINE_BINARY="${prisma-engines}/bin/introspection-engine" + export PRISMA_FMT_BINARY="${prisma-engines}/bin/prisma-fmt" + ''; + }; + }); +} diff --git a/package-lock.json b/package-lock.json index e4f2160..b171ce5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { "name": "xyter", - "version": "1.3.5", + "version": "1.4.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "xyter", + "version": "1.4.4", "license": "GPL-3.0-only", "dependencies": { "@prisma/client": "^4.7.1", "@types/i18next-fs-backend": "^1.1.2", - "axios": "^1.2.1", + "axios": "^1.4.0", "chance": "^1.1.9", "date-fns": "^2.29.3", "discord.js": "^14.7.1", @@ -18,33 +19,36 @@ "node-schedule": "^2.1.0", "typescript": "^4.9.4", "uuid": "^9.0.0", + "voca": "^1.4.0", "winston": "^3.8.2", "winston-daily-rotate-file": "^4.7.1" }, "devDependencies": { "@semantic-release/git": "^10.0.1", + "@semantic-release/release-notes-generator": "^10.0.3", + "@types/axios": "^0.14.0", "@types/chance": "1.1.3", "@types/node-schedule": "2.1.0", "@types/uuid": "9.0.0", + "@types/voca": "^1.4.2", "@typescript-eslint/eslint-plugin": "^5.46.1", "@typescript-eslint/parser": "^5.46.1", "eslint": "^8.29.0", "eslint-config-prettier": "8.5.0", - "eslint-plugin-import": "2.26.0", + "eslint-plugin-import": "2.27.4", "eslint-plugin-no-loops": "0.3.0", "eslint-plugin-prettier": "4.2.1", - "lint-staged": "13.0.4", + "lint-staged": "13.1.0", "nodemon": "2.0.20", - "prettier": "2.8.0", - "prisma": "^4.7.1", - "semantic-release": "^19.0.5" - }, - "version": "1.3.5" + "prettier": "2.8.2", + "prisma": "^4.9.0", + "semantic-release": "^20.0.0" + } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, "dependencies": { "@babel/highlight": "^7.18.6" @@ -148,9 +152,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz", - "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==", + "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" }, @@ -177,65 +181,120 @@ } }, "node_modules/@discordjs/builders": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.4.0.tgz", - "integrity": "sha512-nEeTCheTTDw5kO93faM1j8ZJPonAX86qpq/QVoznnSa8WWcCgJpjlu6GylfINTDW6o7zZY0my2SYdxx2mfNwGA==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.6.3.tgz", + "integrity": "sha512-CTCh8NqED3iecTNuiz49mwSsrc2iQb4d0MjMdmS/8pb69Y4IlzJ/DIy/p5GFlgOrFbNO2WzMHkWKQSiJ3VNXaw==", "dependencies": { - "@discordjs/util": "^0.1.0", - "@sapphire/shapeshift": "^3.7.1", - "discord-api-types": "^0.37.20", + "@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.2", - "tslib": "^2.4.1" + "ts-mixer": "^6.0.3", + "tslib": "^2.5.0" }, "engines": { "node": ">=16.9.0" } }, "node_modules/@discordjs/collection": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.3.0.tgz", - "integrity": "sha512-ylt2NyZ77bJbRij4h9u/wVy7qYw/aDqQLWnadjvDqW/WoWCxrsX6M3CIw9GVP5xcGCDxsrKj5e0r5evuFYwrKg==", + "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.4.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.4.0.tgz", - "integrity": "sha512-k3Ip7ffFSAfp7Mu4H/3BEXFvFz+JsbXRrRtpeBMnSp1LefhtlZWJE6xdXzNlblktKNQltnRwY+z0NZrGQdxAMw==", + "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.3.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.20", - "file-type": "^18.0.0", - "tslib": "^2.4.1", - "undici": "^5.13.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/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", + "espree": "^9.5.2", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -249,10 +308,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/js": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", + "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", - "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -318,28 +386,28 @@ } }, "node_modules/@octokit/auth-token": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz", - "integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", + "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", "dev": true, "dependencies": { - "@octokit/types": "^8.0.0" + "@octokit/types": "^9.0.0" }, "engines": { "node": ">= 14" } }, "node_modules/@octokit/core": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz", - "integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", + "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", "dev": true, "dependencies": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", "@octokit/request": "^6.0.0", "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" }, @@ -348,12 +416,12 @@ } }, "node_modules/@octokit/endpoint": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz", - "integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", + "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", "dev": true, "dependencies": { - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" }, @@ -362,13 +430,13 @@ } }, "node_modules/@octokit/graphql": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz", - "integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", "dev": true, "dependencies": { "@octokit/request": "^6.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -376,18 +444,19 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==", + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", + "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz", - "integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", "dev": true, "dependencies": { - "@octokit/types": "^8.0.0" + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" }, "engines": { "node": ">= 14" @@ -406,12 +475,12 @@ } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz", - "integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.1.2.tgz", + "integrity": "sha512-R0oJ7j6f/AdqPLtB9qRXLO+wjI9pctUn8Ka8UGfGaFCcCv3Otx14CshQ89K4E88pmyYZS8p0rNTiprML/81jig==", "dev": true, "dependencies": { - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.2.3", "deprecation": "^2.3.1" }, "engines": { @@ -422,14 +491,14 @@ } }, "node_modules/@octokit/request": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", - "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", + "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", "dev": true, "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.7", "universal-user-agent": "^6.0.0" @@ -439,12 +508,12 @@ } }, "node_modules/@octokit/request-error": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz", - "integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", + "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", "dev": true, "dependencies": { - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "deprecation": "^2.0.0", "once": "^1.4.0" }, @@ -453,36 +522,83 @@ } }, "node_modules/@octokit/rest": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz", - "integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==", + "version": "19.0.11", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", + "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", "dev": true, "dependencies": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^5.0.0", + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^6.7.0" + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" }, "engines": { "node": ">= 14" } }, + "node_modules/@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", + "dev": true + }, "node_modules/@octokit/types": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", - "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", + "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^14.0.0" + "@octokit/openapi-types": "^17.2.0" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.0.tgz", + "integrity": "sha512-roLI1ul/GwzwcfcVpZYPdrgW2W/drLriObl1h+yLF5syc8/5ULWw2ALbCHUWF+4YltIqA3xFSbG4IwyJz37e9g==", + "dev": true, + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" } }, "node_modules/@prisma/client": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.7.1.tgz", - "integrity": "sha512-/GbnOwIPtjiveZNUzGXOdp7RxTEkHL4DZP3vBaFNadfr6Sf0RshU5EULFzVaSi9i9PIK9PYd+1Rn7z2B2npb9w==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.14.1.tgz", + "integrity": "sha512-TZIswkeX1ccsHG/eN2kICzg/csXll0osK3EHu1QKd8VJ3XLcXozbNELKkCNfsCUvKJAwPdDtFCzF+O+raIVldw==", "hasInstallScript": true, "dependencies": { - "@prisma/engines-version": "4.7.1-1.272861e07ab64f234d3ffc4094e32bd61775599c" + "@prisma/engines-version": "4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c" }, "engines": { "node": ">=14.17" @@ -497,16 +613,16 @@ } }, "node_modules/@prisma/engines": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.7.1.tgz", - "integrity": "sha512-zWabHosTdLpXXlMefHmnouhXMoTB1+SCbUU3t4FCmdrtIOZcarPKU3Alto7gm/pZ9vHlGOXHCfVZ1G7OIrSbog==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.14.1.tgz", + "integrity": "sha512-APqFddPVHYmWNKqc+5J5SqrLFfOghKOLZxobmguDUacxOwdEutLsbXPVhNnpFDmuQWQFbXmrTTPoRrrF6B1MWA==", "devOptional": true, "hasInstallScript": true }, "node_modules/@prisma/engines-version": { - "version": "4.7.1-1.272861e07ab64f234d3ffc4094e32bd61775599c", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.7.1-1.272861e07ab64f234d3ffc4094e32bd61775599c.tgz", - "integrity": "sha512-Bd4LZ+WAnUHOq31e9X/ihi5zPlr4SzTRwUZZYxvWOxlerIZ7HJlVa9zXpuKTKLpI9O1l8Ec4OYCKsivWCs5a3Q==" + "version": "4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c.tgz", + "integrity": "sha512-3jum8/YSudeSN0zGW5qkpz+wAN2V/NYCQ+BPjvHYDfWatLWlQkqy99toX0GysDeaUoBIJg1vaz2yKqiA3CFcQw==" }, "node_modules/@sapphire/async-queue": { "version": "1.5.0", @@ -518,9 +634,9 @@ } }, "node_modules/@sapphire/shapeshift": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.8.0.tgz", - "integrity": "sha512-Ec8CqUy7CX87jM1AAUfVycNrKnKmfdOzJhq0gqlRRMQFPcarKV5z8P8TVFgN09E6bbKQW+Lh4Zsi+dzDadeyzw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.0.tgz", + "integrity": "sha512-iJpHmjAdwX9aSL6MvFpVyo+tkokDtInmSjoJHbz/k4VJfnim3DjvG0hgGEKWtWZgCu45RaLgcoNgR1fCPdIz3w==", "dependencies": { "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21" @@ -531,9 +647,9 @@ } }, "node_modules/@sapphire/snowflake": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.3.0.tgz", - "integrity": "sha512-Hec5N6zEkZuZFLybVKyLFLlcSgYmR6C1/+9NkIhxPwOf6tgX52ndJCSz8ADejmbrNE0VuNCNkpzhRZzenEC9vA==", + "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" @@ -591,95 +707,6 @@ "semantic-release": ">=18.0.0" } }, - "node_modules/@semantic-release/git/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/@semantic-release/git/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/@semantic-release/git/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/git/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@semantic-release/git/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@semantic-release/git/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/git/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/@semantic-release/github": { "version": "8.0.7", "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-8.0.7.tgz", @@ -711,22 +738,22 @@ } }, "node_modules/@semantic-release/npm": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-9.0.1.tgz", - "integrity": "sha512-I5nVZklxBzfMFwemhRNbSrkiN/dsH3c7K9+KSk6jUnq0rdLFUuJt7EBsysq4Ir3moajQgFkfEryEHPqiKJj20g==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-9.0.2.tgz", + "integrity": "sha512-zgsynF6McdzxPnFet+a4iO9HpAlARXOM5adz7VGVCvj0ne8wtL2ZOQoDV2wZPDmdEotDIbVeJjafhelZjs9j6g==", "dev": true, "dependencies": { "@semantic-release/error": "^3.0.0", "aggregate-error": "^3.0.0", "execa": "^5.0.0", - "fs-extra": "^10.0.0", + "fs-extra": "^11.0.0", "lodash": "^4.17.15", "nerf-dart": "^1.0.0", "normalize-url": "^6.0.0", "npm": "^8.3.0", "rc": "^1.2.8", "read-pkg": "^5.0.0", - "registry-auth-token": "^4.0.0", + "registry-auth-token": "^5.0.0", "semver": "^7.1.2", "tempy": "^1.0.0" }, @@ -737,109 +764,6 @@ "semantic-release": ">=19.0.0" } }, - "node_modules/@semantic-release/npm/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/@semantic-release/npm/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@semantic-release/npm/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/@semantic-release/npm/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@semantic-release/npm/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@semantic-release/npm/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/@semantic-release/release-notes-generator": { "version": "10.0.3", "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-10.0.3.tgz", @@ -878,6 +802,16 @@ "node": ">= 10" } }, + "node_modules/@types/axios": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz", + "integrity": "sha512-KqQnQbdYE54D7oa/UmYVMZKq7CO4l8DEENzOKc4aBRwxCXSlJXGz83flFx5L7AWrOQnmuN3kVsRdt+GZPPjiVQ==", + "deprecated": "This is a stub types definition for axios (https://github.com/mzabriskie/axios). axios provides its own type definitions, so you don't need @types/axios installed!", + "dev": true, + "dependencies": { + "axios": "*" + } + }, "node_modules/@types/chance": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@types/chance/-/chance-1.1.3.tgz", @@ -911,9 +845,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.11.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.14.tgz", - "integrity": "sha512-0KXV57tENYmmJMl+FekeW9V3O/rlcqGQQJ/hNh9r8pKIj304pskWuEd8fCyNT86g/TpO0gcOTiLzsHLEURFMIQ==" + "version": "20.2.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.3.tgz", + "integrity": "sha512-pg9d0yC4rVNWQzX8U7xb4olIOFuuVL9za3bzMT2pu2SU0SNEi66i2qrvhE2qt0HvkhuCaWJu7pLNOt/Pj8BIrw==" }, "node_modules/@types/node-schedule": { "version": "2.1.0", @@ -930,12 +864,6 @@ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, "node_modules/@types/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", @@ -943,38 +871,50 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, + "node_modules/@types/triple-beam": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", + "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==" + }, "node_modules/@types/uuid": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz", "integrity": "sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==", "dev": true }, + "node_modules/@types/voca": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@types/voca/-/voca-1.4.2.tgz", + "integrity": "sha512-Vmw8euGSdVlcDV69LoixtuervYUim5u6Vgp41PNxrHVGIo4vxSKMhW0I9MmBKbk3gtveNFzdHIVzyW1DpECzYw==", + "dev": true + }, "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", + "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", "dependencies": { "@types/node": "*" } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.46.1.tgz", - "integrity": "sha512-YpzNv3aayRBwjs4J3oz65eVLXc9xx0PDbIRisHj+dYhvBn02MjYOD96P8YGiWEIFBrojaUjxvkaUpakD82phsA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", + "integrity": "sha512-BL+jYxUFIbuYwy+4fF86k5vdT9lT0CNJ6HtwrIvGh0PhH8s0yy5rjaKH2fDCrz5ITHy07WCzVGNvAmjJh4IJFA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.46.1", - "@typescript-eslint/type-utils": "5.46.1", - "@typescript-eslint/utils": "5.46.1", + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/type-utils": "5.59.7", + "@typescript-eslint/utils": "5.59.7", "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" }, @@ -996,14 +936,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz", - "integrity": "sha512-RelQ5cGypPh4ySAtfIMBzBGyrNerQcmfA1oJvPj5f+H4jI59rl9xxpn4bonC0tQvUKOEN7eGBFWxFLK3Xepneg==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", + "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.46.1", - "@typescript-eslint/types": "5.46.1", - "@typescript-eslint/typescript-estree": "5.46.1", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "debug": "^4.3.4" }, "engines": { @@ -1023,13 +963,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.46.1.tgz", - "integrity": "sha512-iOChVivo4jpwUdrJZyXSMrEIM/PvsbbDOX1y3UCKjSgWn+W89skxWaYXACQfxmIGhPVpRWK/VWPYc+bad6smIA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", + "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.46.1", - "@typescript-eslint/visitor-keys": "5.46.1" + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1040,13 +980,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.46.1.tgz", - "integrity": "sha512-V/zMyfI+jDmL1ADxfDxjZ0EMbtiVqj8LUGPAGyBkXXStWmCUErMpW873zEHsyguWCuq2iN4BrlWUkmuVj84yng==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.7.tgz", + "integrity": "sha512-ozuz/GILuYG7osdY5O5yg0QxXUAEoI4Go3Do5xeu+ERH9PorHBPSdvD3Tjp2NN2bNLh1NJQSsQu2TPu/Ly+HaQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.46.1", - "@typescript-eslint/utils": "5.46.1", + "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/utils": "5.59.7", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1067,9 +1007,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.46.1.tgz", - "integrity": "sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", + "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1080,13 +1020,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.46.1.tgz", - "integrity": "sha512-j9W4t67QiNp90kh5Nbr1w92wzt+toiIsaVPnEblB2Ih2U9fqBTyqV9T3pYWZBRt6QoMh/zVWP59EpuCjc4VRBg==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", + "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.46.1", - "@typescript-eslint/visitor-keys": "5.46.1", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1107,18 +1047,18 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.46.1.tgz", - "integrity": "sha512-RBdBAGv3oEpFojaCYT4Ghn4775pdjvwfDOfQ2P6qzNVgQOVrnSPe5/Pb88kv7xzYQjoio0eKHKB9GJ16ieSxvA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", + "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", "dev": true, "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.46.1", - "@typescript-eslint/types": "5.46.1", - "@typescript-eslint/typescript-estree": "5.46.1", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", "semver": "^7.3.7" }, "engines": { @@ -1133,12 +1073,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.46.1.tgz", - "integrity": "sha512-jczZ9noovXwy59KjRTk1OftT78pwygdcmCuBf8yMoWt/8O8l+6x2LSEze0E4TeepXK4MezW3zGSyoDRZK7Y9cg==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", + "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/types": "5.59.7", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1149,6 +1089,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "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/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -1156,9 +1105,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "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" @@ -1299,6 +1248,19 @@ "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", "dev": true }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -1351,6 +1313,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -1379,10 +1359,22 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/axios": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz", - "integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -1453,6 +1445,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -1526,9 +1519,9 @@ } }, "node_modules/chance": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.9.tgz", - "integrity": "sha512-TfxnA/DcZXRTA4OekA2zL9GH8qscbbl6X0ZqU4tXhGveVY/mXWvEQLt5GwZcYXTEyEFflVtj+pG8nc8EwSm1RQ==" + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.11.tgz", + "integrity": "sha512-kqTg3WWywappJPqtgrdvbA380VoXO2eu9VCV895JgbyHsaErXdyHK9LOZ911OvAk6L0obK7kDk9CGs8+oBawVA==" }, "node_modules/chokidar": { "version": "3.5.3", @@ -1651,14 +1644,17 @@ } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/cliui/node_modules/emoji-regex": { @@ -1739,9 +1735,9 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, "node_modules/colorspace": { @@ -1765,9 +1761,9 @@ } }, "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": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true, "engines": { "node": "^12.20.0 || >=14" @@ -1789,6 +1785,16 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "node_modules/conventional-changelog-angular": { "version": "5.0.13", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", @@ -1874,40 +1880,32 @@ "dev": true }, "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", "dev": true, "dependencies": { - "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "path-type": "^4.0.0" }, "engines": { - "node": ">=10" - } - }, - "node_modules/cosmiconfig/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" } }, "node_modules/cron-parser": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz", - "integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.8.1.tgz", + "integrity": "sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ==", "dependencies": { - "is-nan": "^1.3.2", - "luxon": "^1.26.0" + "luxon": "^3.2.1" }, "engines": { - "node": ">=0.8" + "node": ">=12.0.0" } }, "node_modules/cross-spawn": { @@ -1934,9 +1932,12 @@ } }, "node_modules/date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, "engines": { "node": ">=0.11" }, @@ -2021,9 +2022,10 @@ "dev": true }, "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, "dependencies": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" @@ -2084,27 +2086,29 @@ } }, "node_modules/discord-api-types": { - "version": "0.37.22", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.22.tgz", - "integrity": "sha512-1FSm5hIUaxt3e+3H6lhY5Hg32DTJCPp3Q5gf3CM2CPSr95ZnqkSNEV0s7EdiBrlv5QoPrpcPIDYC3hWqZT2mIg==" + "version": "0.37.42", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.42.tgz", + "integrity": "sha512-1Huaj9cQ1W7/uryS8MZs/tZemnoKB94thM1cE40lep3rpU3q7WHqkdjN/veX0prTkYlPhcyLd/DeF/pBO8X8oQ==" }, "node_modules/discord.js": { - "version": "14.7.1", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.1.tgz", - "integrity": "sha512-1FECvqJJjjeYcjSm0IGMnPxLqja/pmG1B0W2l3lUY2Gi4KXiyTeQmU1IxWcbXHn2k+ytP587mMWqva2IA87EbA==", + "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.4.0", - "@discordjs/collection": "^1.3.0", - "@discordjs/rest": "^1.4.0", - "@discordjs/util": "^0.1.0", - "@sapphire/snowflake": "^3.2.2", - "@types/ws": "^8.5.3", - "discord-api-types": "^0.37.20", + "@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.1", - "undici": "^5.13.0", - "ws": "^8.11.0" + "tslib": "^2.5.0", + "undici": "^5.22.0", + "ws": "^8.13.0" }, "engines": { "node": ">=16.9.0" @@ -2151,36 +2155,6 @@ "readable-stream": "^2.0.2" } }, - "node_modules/duplexer2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/duplexer2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/duplexer2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2199,106 +2173,126 @@ "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, "node_modules/env-ci": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-5.5.0.tgz", - "integrity": "sha512-o0JdWIbOLP+WJKIUt36hz1ImQQFuN92nhsfTkHHap+J8CiI8WgGpH/a9jEGHh4/TU5BUUGjlnKXNoDb57+ne+A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-8.0.0.tgz", + "integrity": "sha512-W+3BqGZozFua9MPeXpmTm5eYEBtGgL76jGu/pwMVp/L8PdECSCEWaIp7d4Mw7kuUrbUldK0oV0bNd6ZZjLiMiA==", "dev": true, "dependencies": { - "execa": "^5.0.0", - "fromentries": "^1.3.2", - "java-properties": "^1.0.0" + "execa": "^6.1.0", + "java-properties": "^1.0.2" }, "engines": { - "node": ">=10.17" + "node": "^16.10 || >=18" } }, "node_modules/env-ci/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, "node_modules/env-ci/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", "dev": true, "engines": { - "node": ">=10.17.0" + "node": ">=12.20.0" } }, "node_modules/env-ci/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/env-ci/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/env-ci/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", "dev": true, "dependencies": { - "path-key": "^3.0.0" + "path-key": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/env-ci/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/env-ci/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/error-ex": { @@ -2311,36 +2305,45 @@ } }, "node_modules/es-abstract": { - "version": "1.20.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.5.tgz", - "integrity": "sha512-7h8MM2EQhsCA7pU/Nv78qOXFpD8Rhqd12gYiSJVkrH9+e8VuA8JlPJK/hQjjlLv6pJvx/z1iRFKzYb0XT/RuAQ==", + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", "dev": true, "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.0", "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", "gopd": "^1.0.1", "has": "^1.0.3", "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "object-inspect": "^1.12.3", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.4.3", "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", "string.prototype.trimend": "^1.0.6", "string.prototype.trimstart": "^1.0.6", - "unbox-primitive": "^1.0.2" + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" }, "engines": { "node": ">= 0.4" @@ -2349,6 +2352,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -2397,13 +2414,16 @@ } }, "node_modules/eslint": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz", - "integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.11.6", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.41.0", + "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", @@ -2412,24 +2432,22 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.15.0", - "grapheme-splitter": "^1.0.4", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -2437,7 +2455,6 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -2465,13 +2482,14 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", "dev": true, "dependencies": { "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -2484,9 +2502,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -2510,23 +2528,25 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", - "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", + "version": "2.27.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.4.tgz", + "integrity": "sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==", "dev": true, "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.0", + "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", "has": "^1.0.3", - "is-core-module": "^2.8.1", + "is-core-module": "^2.11.0", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", "tsconfig-paths": "^3.14.1" }, "engines": { @@ -2537,12 +2557,12 @@ } }, "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "node_modules/eslint-plugin-import/node_modules/doctrine": { @@ -2557,11 +2577,14 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } }, "node_modules/eslint-plugin-no-loops": { "version": "0.3.0", @@ -2606,46 +2629,22 @@ "node": ">=8.0.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -2653,6 +2652,9 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/estraverse": { @@ -2665,14 +2667,14 @@ } }, "node_modules/espree": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", - "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2695,9 +2697,9 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -2755,23 +2757,23 @@ } }, "node_modules/execa": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", - "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^3.0.1", - "is-stream": "^3.0.0", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" @@ -2783,9 +2785,9 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true }, "node_modules/fast-glob": { @@ -2829,9 +2831,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", - "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -2843,27 +2845,31 @@ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", "dev": true, "dependencies": { - "escape-string-regexp": "^1.0.5" + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" }, "engines": { - "node": ">=8" + "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/file-entry-cache": { @@ -2887,9 +2893,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.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.4.0.tgz", + "integrity": "sha512-o6MQrZKTAK6WpvmQk3jqTVUmqxYBxW5bloUfrdH1ZnRFDvvAPNr+l+rgOxM3nkqWT+3khaj3FRMDydWe0xhu+w==", "dependencies": { "readable-web-to-node-stream": "^3.0.2", "strtok3": "^7.0.0", @@ -2931,15 +2937,15 @@ } }, "node_modules/find-versions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", - "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", + "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==", "dev": true, "dependencies": { - "semver-regex": "^3.1.2" + "semver-regex": "^4.0.5" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2988,6 +2994,15 @@ } } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -3011,60 +3026,10 @@ "readable-stream": "^2.0.0" } }, - "node_modules/from2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/from2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/from2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/fs-extra": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", - "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -3098,7 +3063,8 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -3137,12 +3103,14 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" }, "funding": { @@ -3191,27 +3159,6 @@ "traverse": "~0.6.6" } }, - "node_modules/git-log-parser/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/git-log-parser/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/git-log-parser/node_modules/split2": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", @@ -3221,15 +3168,6 @@ "through2": "~2.0.0" } }, - "node_modules/git-log-parser/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/git-log-parser/node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -3273,9 +3211,9 @@ } }, "node_modules/globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -3287,6 +3225,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -3320,9 +3273,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/grapheme-splitter": { @@ -3331,6 +3284,12 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/handlebars": { "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", @@ -3365,6 +3324,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -3394,6 +3354,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, "dependencies": { "get-intrinsic": "^1.1.1" }, @@ -3401,10 +3362,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -3428,12 +3402,15 @@ } }, "node_modules/hook-std": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-2.0.0.tgz", - "integrity": "sha512-zZ6T5WcuBMIUVh49iPQS9t977t7C0l7OtHrpeMb5uk48JdflRX0NSFvCekfYNmGQETnLq9W/isMyHl69kxGi8g==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz", + "integrity": "sha512-jHRQzjSDzMtFy34AGj1DN+vq54WVuhSvKgrHf0OMiFQTwDD4L/qqofVEWjLOBMTn5+lCD3fPg32W9yOfnEJTTw==", "dev": true, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/hosted-git-info": { @@ -3476,12 +3453,12 @@ } }, "node_modules/human-signals": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", - "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, "engines": { - "node": ">=12.20.0" + "node": ">=10.17.0" } }, "node_modules/i18next": { @@ -3526,9 +3503,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", - "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, "engines": { "node": ">= 4" @@ -3608,12 +3585,12 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.0", + "get-intrinsic": "^1.2.0", "has": "^1.0.3", "side-channel": "^1.0.4" }, @@ -3637,6 +3614,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -3696,9 +3687,9 @@ } }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -3755,21 +3746,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -3880,12 +3856,11 @@ } }, "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3933,6 +3908,37 @@ "node": ">=0.10.0" } }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -3982,16 +3988,6 @@ "node": ">= 0.6.0" } }, - "node_modules/js-sdsl": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", - "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4041,9 +4037,9 @@ "dev": true }, "node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "dependencies": { "minimist": "^1.2.0" @@ -4132,9 +4128,9 @@ "dev": true }, "node_modules/lint-staged": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.0.4.tgz", - "integrity": "sha512-HxlHCXoYRsq9QCby5wFozmZW00hMs/9e3l+/dz6Qr8Kle4UH0kJTdABAbqhzG+3pcG6QjL9kz7NgGBfph+a5dw==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.1.0.tgz", + "integrity": "sha512-pn/sR8IrcF/T0vpWLilih8jmVouMlxqXxKuAojmbiGX5n/gDnz+abdPptlj0vYnbfE0SQNl3CY/HwtM0+yfOVQ==", "dev": true, "dependencies": { "cli-truncate": "^3.1.0", @@ -4161,10 +4157,120 @@ "url": "https://opencollective.com/lint-staged" } }, + "node_modules/lint-staged/node_modules/execa": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "dev": true, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/listr2": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.6.tgz", - "integrity": "sha512-u60KxKBy1BR2uLJNTWNptzWQ1ob/gjMzIJPZffAENzpZqbMZ/5PrXXOomDcevIS/+IB7s1mmCEtSlT2qHWMqag==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", + "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", "dev": true, "dependencies": { "cli-truncate": "^2.1.0", @@ -4172,7 +4278,7 @@ "log-update": "^4.0.0", "p-map": "^4.0.0", "rfdc": "^1.3.0", - "rxjs": "^7.5.7", + "rxjs": "^7.8.0", "through": "^2.3.8", "wrap-ansi": "^7.0.0" }, @@ -4295,6 +4401,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true + }, "node_modules/lodash.capitalize": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", @@ -4421,11 +4533,12 @@ } }, "node_modules/logform": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.4.2.tgz", - "integrity": "sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", + "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", "dependencies": { "@colors/colors": "1.5.0", + "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", @@ -4450,11 +4563,11 @@ } }, "node_modules/luxon": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", - "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz", + "integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==", "engines": { - "node": "*" + "node": ">=12" } }, "node_modules/map-obj": { @@ -4470,9 +4583,9 @@ } }, "node_modules/marked": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.4.tgz", - "integrity": "sha512-Wcc9ikX7Q5E4BYDPvh1C6QNSxrjC9tBgz+A/vAhp59KXUgachw++uMvMKiSW8oA85nopmPZcEvBoex/YLMsiyA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -4482,35 +4595,35 @@ } }, "node_modules/marked-terminal": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.1.1.tgz", - "integrity": "sha512-+cKTOx9P4l7HwINYhzbrBSyzgxO2HaHKGZGuB1orZsMIgXYaJyfidT81VXRdpelW/PcHEWxywscePVgI/oUF6g==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.2.0.tgz", + "integrity": "sha512-Piv6yNwAQXGFjZSaiNljyNFw7jKDdGrw70FSbtxEyldLsyeuV5ZHm/1wW++kWbrOF1VPnUgYOhB2oLL0ZpnekA==", "dev": true, "dependencies": { - "ansi-escapes": "^5.0.0", + "ansi-escapes": "^6.2.0", "cardinal": "^2.1.1", - "chalk": "^5.0.0", - "cli-table3": "^0.6.1", + "chalk": "^5.2.0", + "cli-table3": "^0.6.3", "node-emoji": "^1.11.0", - "supports-hyperlinks": "^2.2.0" + "supports-hyperlinks": "^2.3.0" }, "engines": { "node": ">=14.13.1 || >=16.0.0" }, "peerDependencies": { - "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0" + "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" } }, "node_modules/marked-terminal/node_modules/ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", "dev": true, "dependencies": { - "type-fest": "^1.0.2" + "type-fest": "^3.0.0" }, "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4529,12 +4642,12 @@ } }, "node_modules/marked-terminal/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.11.0.tgz", + "integrity": "sha512-JaPw5U9ixP0XcpUbQoVSbxSDcK/K4nww20C3kjm9yE6cDRRhptU28AH60VWf9ltXmCrIfIbtt9J+2OUk2Uqiaw==", "dev": true, "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4637,15 +4750,12 @@ } }, "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/min-indent": { @@ -4670,9 +4780,9 @@ } }, "node_modules/minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4748,9 +4858,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "dev": true, "dependencies": { "whatwg-url": "^5.0.0" @@ -4768,11 +4878,11 @@ } }, "node_modules/node-schedule": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.0.tgz", - "integrity": "sha512-nl4JTiZ7ZQDc97MmpTq9BQjYhq7gOtoh7SiPH069gBFBj0PzD8HI7zyFs6rzqL8Y5tTiEEYLxgtbx034YPrbyQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.1.tgz", + "integrity": "sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==", "dependencies": { - "cron-parser": "^3.5.0", + "cron-parser": "^4.2.0", "long-timeout": "0.1.1", "sorted-array-functions": "^1.3.0" }, @@ -4899,9 +5009,9 @@ } }, "node_modules/npm": { - "version": "8.19.3", - "resolved": "https://registry.npmjs.org/npm/-/npm-8.19.3.tgz", - "integrity": "sha512-0QjmyPtDxSyMWWD8I91QGbrgx9KzbV6C9FK1liEb/K0zppiZkr5KxXc990G+LzPwBHDfRjUBlO9T1qZ08vl9mA==", + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/npm/-/npm-8.19.4.tgz", + "integrity": "sha512-3HANl8i9DKnUA89P4KEgVNN28EjSeDCmvEqbzOAuxCFDzdBZzjUl99zgnGpOUumvW5lvJo2HKcjrsc+tfyv1Hw==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -5062,30 +5172,15 @@ } }, "node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "dependencies": { - "path-key": "^4.0.0" + "path-key": "^3.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/npm/node_modules/@colors/colors": { @@ -5953,7 +6048,7 @@ } }, "node_modules/npm/node_modules/http-cache-semantics": { - "version": "4.1.0", + "version": "4.1.1", "dev": true, "inBundle": true, "license": "BSD-2-Clause" @@ -7500,9 +7595,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7512,6 +7607,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -7569,15 +7665,15 @@ } }, "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "dependencies": { - "mimic-fn": "^4.0.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=12" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7601,12 +7697,12 @@ } }, "node_modules/p-each-series": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", - "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-3.0.0.tgz", + "integrity": "sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7916,9 +8012,9 @@ } }, "node_modules/prettier": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.0.tgz", - "integrity": "sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.2.tgz", + "integrity": "sha512-BtRV9BcncDyI2tsuS19zzhzoxD8Dh8LiCx7j7tHzrkz8GFXAexeWFdi22mjE1d16dftH2qNaytVxqiRTGlMfpw==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -7943,13 +8039,13 @@ } }, "node_modules/prisma": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.7.1.tgz", - "integrity": "sha512-CCQP+m+1qZOGIZlvnL6T3ZwaU0LAleIHYFPN9tFSzjs/KL6vH9rlYbGOkTuG9Q1s6Ki5D0LJlYlW18Z9EBUpGg==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.14.1.tgz", + "integrity": "sha512-z6hxzTMYqT9SIKlzD08dhzsLUpxjFKKsLpp5/kBDnSqiOjtUyyl/dC5tzxLcOa3jkEHQ8+RpB/fE3w8bgNP51g==", "devOptional": true, "hasInstallScript": true, "dependencies": { - "@prisma/engines": "4.7.1" + "@prisma/engines": "4.14.1" }, "bin": { "prisma": "build/index.js", @@ -7965,6 +8061,12 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -7977,9 +8079,9 @@ "dev": true }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, "engines": { "node": ">=6" @@ -8187,16 +8289,18 @@ } }, "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": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "node_modules/readable-web-to-node-stream": { @@ -8214,6 +8318,19 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -8254,14 +8371,14 @@ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -8270,28 +8387,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/registry-auth-token": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", - "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", "dev": true, "dependencies": { - "rc": "1.2.8" + "@pnpm/npm-conf": "^2.1.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=14" } }, "node_modules/require-directory": { @@ -8304,12 +8409,12 @@ } }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -8342,30 +8447,6 @@ "node": ">=8" } }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -8430,32 +8511,18 @@ } }, "node_modules/rxjs": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.6.0.tgz", - "integrity": "sha512-DDa7d8TFNUalGC9VqXvQ1euWNN7sc63TrUCuM9J998+ViviahMIjKSOU7rfcgFOF+FCD71BhDRv4hrFz+ImDLQ==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, "dependencies": { "tslib": "^2.1.0" } }, "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/safe-regex-test": { "version": "1.0.0", @@ -8472,17 +8539,17 @@ } }, "node_modules/safe-stable-stringify": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.1.tgz", - "integrity": "sha512-dVHE6bMtS/bnL2mwualjc6IxEv1F+OCUpA46pKUj6F8uDbUM0jCCulPqRNPSnWwGNKx5etqMjZYdXtrm5KJZGA==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", "engines": { "node": ">=10" } }, "node_modules/semantic-release": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.5.tgz", - "integrity": "sha512-NMPKdfpXTnPn49FDogMBi36SiBfXkSOJqCkk0E4iWOY1tusvvgBwqUmxTX1kmlT6kIYed9YwNKD1sfPpqa5yaA==", + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-20.1.3.tgz", + "integrity": "sha512-sMIK9IaOdLP9hxzTxdTVHxINsazlDgv2gjZ1yeyRZXpIT3xAnuQUDEez8k+AC+lFUtGnfzA2Ct3V5lDyiMestw==", "dev": true, "dependencies": { "@semantic-release/commit-analyzer": "^9.0.2", @@ -8490,112 +8557,323 @@ "@semantic-release/github": "^8.0.0", "@semantic-release/npm": "^9.0.0", "@semantic-release/release-notes-generator": "^10.0.0", - "aggregate-error": "^3.0.0", - "cosmiconfig": "^7.0.0", + "aggregate-error": "^4.0.1", + "cosmiconfig": "^8.0.0", "debug": "^4.0.0", - "env-ci": "^5.0.0", - "execa": "^5.0.0", - "figures": "^3.0.0", - "find-versions": "^4.0.0", + "env-ci": "^8.0.0", + "execa": "^7.0.0", + "figures": "^5.0.0", + "find-versions": "^5.1.0", "get-stream": "^6.0.0", "git-log-parser": "^1.2.0", - "hook-std": "^2.0.0", - "hosted-git-info": "^4.0.0", - "lodash": "^4.17.21", - "marked": "^4.0.10", - "marked-terminal": "^5.0.0", + "hook-std": "^3.0.0", + "hosted-git-info": "^6.0.0", + "lodash-es": "^4.17.21", + "marked": "^4.1.0", + "marked-terminal": "^5.1.1", "micromatch": "^4.0.2", - "p-each-series": "^2.1.0", - "p-reduce": "^2.0.0", - "read-pkg-up": "^7.0.0", + "p-each-series": "^3.0.0", + "p-reduce": "^3.0.0", + "read-pkg-up": "^9.1.0", "resolve-from": "^5.0.0", "semver": "^7.3.2", - "semver-diff": "^3.1.1", + "semver-diff": "^4.0.0", "signale": "^1.2.1", - "yargs": "^16.2.0" + "yargs": "^17.5.1" }, "bin": { "semantic-release": "bin/semantic-release.js" }, "engines": { - "node": ">=16 || ^14.17" + "node": ">=18" } }, - "node_modules/semantic-release/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/semantic-release/node_modules/aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/semantic-release/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/semantic-release/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semantic-release/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/semantic-release/node_modules/clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/execa": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", + "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/semantic-release/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/semantic-release/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/semantic-release/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/semantic-release/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/semantic-release/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", "dev": true, "dependencies": { - "path-key": "^3.0.0" + "path-key": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/semantic-release/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/p-reduce": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", + "integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/semantic-release/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/read-pkg": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz", + "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.1", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^2.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/read-pkg-up": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz", + "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==", + "dev": true, + "dependencies": { + "find-up": "^6.3.0", + "read-pkg": "^7.1.0", + "type-fest": "^2.5.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8611,18 +8889,45 @@ } }, "node_modules/semantic-release/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -8635,33 +8940,27 @@ } }, "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", "dev": true, "dependencies": { - "semver": "^6.3.0" + "semver": "^7.3.5" }, "engines": { - "node": ">=8" - } - }, - "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/semver-regex": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", - "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", + "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8897,9 +9196,9 @@ "dev": true }, "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -8923,9 +9222,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, "node_modules/split": { @@ -8949,6 +9248,20 @@ "readable-stream": "^3.0.0" } }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -8967,36 +9280,6 @@ "readable-stream": "^2.0.2" } }, - "node_modules/stream-combiner2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/stream-combiner2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/stream-combiner2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -9006,17 +9289,17 @@ } }, "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dependencies": { - "safe-buffer": "~5.2.0" + "safe-buffer": "~5.1.0" } }, "node_modules/string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, "engines": { "node": ">=0.6.19" @@ -9066,6 +9349,23 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string.prototype.trimend": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", @@ -9116,15 +9416,12 @@ } }, "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/strip-indent": { @@ -9232,18 +9529,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tempy/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/tempy/node_modules/type-fest": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", @@ -9291,6 +9576,20 @@ "readable-stream": "3" } }, + "node_modules/through2/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -9361,26 +9660,26 @@ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "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==" + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", + "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" }, "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", + "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -9427,10 +9726,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9474,14 +9787,14 @@ "dev": true }, "node_modules/undici": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.14.0.tgz", - "integrity": "sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", + "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", "dependencies": { "busboy": "^1.6.0" }, "engines": { - "node": ">=12.18" + "node": ">=14.0" } }, "node_modules/unique-string": { @@ -9549,6 +9862,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/voca": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/voca/-/voca-1.4.1.tgz", + "integrity": "sha512-NJC/BzESaHT1p4B5k4JykxedeltmNbau4cummStd4RjFojgq/kLew5TzYge9N2geeWyI2w8T30wUET5v+F7ZHA==" + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -9596,6 +9914,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/winston": { "version": "3.8.2", "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz", @@ -9647,15 +9985,30 @@ "node": ">= 6.4.0" } }, - "node_modules/winston/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "engines": { - "node": ">=8" + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 6" + } + }, + "node_modules/winston/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/word-wrap": { @@ -9726,15 +10079,15 @@ "dev": true }, "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": { @@ -9770,30 +10123,31 @@ "dev": true }, "node_modules/yaml": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz", - "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.0.tgz", + "integrity": "sha512-8/1wgzdKc7bc9E6my5wZjmdavHLvO/QOmLG1FBugblEvY4IXrLjlViIOmL24HthU042lWTDRO90Fz1Yp66UnMw==", "dev": true, "engines": { - "node": ">= 14" + "node": ">= 14", + "npm": ">= 7" } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { @@ -9834,6 +10188,15 @@ "node": ">=8" } }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -9849,9 +10212,9 @@ }, "dependencies": { "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, "requires": { "@babel/highlight": "^7.18.6" @@ -9933,9 +10296,9 @@ } }, "@babel/runtime": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz", - "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", + "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", "requires": { "regenerator-runtime": "^0.13.11" } @@ -9956,53 +10319,93 @@ } }, "@discordjs/builders": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.4.0.tgz", - "integrity": "sha512-nEeTCheTTDw5kO93faM1j8ZJPonAX86qpq/QVoznnSa8WWcCgJpjlu6GylfINTDW6o7zZY0my2SYdxx2mfNwGA==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.6.3.tgz", + "integrity": "sha512-CTCh8NqED3iecTNuiz49mwSsrc2iQb4d0MjMdmS/8pb69Y4IlzJ/DIy/p5GFlgOrFbNO2WzMHkWKQSiJ3VNXaw==", "requires": { - "@discordjs/util": "^0.1.0", - "@sapphire/shapeshift": "^3.7.1", - "discord-api-types": "^0.37.20", + "@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.2", - "tslib": "^2.4.1" + "ts-mixer": "^6.0.3", + "tslib": "^2.5.0" } }, "@discordjs/collection": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.3.0.tgz", - "integrity": "sha512-ylt2NyZ77bJbRij4h9u/wVy7qYw/aDqQLWnadjvDqW/WoWCxrsX6M3CIw9GVP5xcGCDxsrKj5e0r5evuFYwrKg==" + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.1.tgz", + "integrity": "sha512-aWEc9DCf3TMDe9iaJoOnO2+JVAjeRNuRxPZQA6GVvBf+Z3gqUuWYBy2NWh4+5CLYq5uoc3MOvUQ5H5m8CJBqOA==" + }, + "@discordjs/formatters": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.1.tgz", + "integrity": "sha512-M7X4IGiSeh4znwcRGcs+49B5tBkNDn4k5bmhxJDAUhRxRHTiFAOTVUNQ6yAKySu5jZTnCbSvTYHW3w0rAzV1MA==", + "requires": { + "discord-api-types": "^0.37.41" + } }, "@discordjs/rest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.4.0.tgz", - "integrity": "sha512-k3Ip7ffFSAfp7Mu4H/3BEXFvFz+JsbXRrRtpeBMnSp1LefhtlZWJE6xdXzNlblktKNQltnRwY+z0NZrGQdxAMw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.7.1.tgz", + "integrity": "sha512-Ofa9UqT0U45G/eX86cURQnX7gzOJLG2oC28VhIk/G6IliYgQF7jFByBJEykPSHE4MxPhqCleYvmsrtfKh1nYmQ==", "requires": { - "@discordjs/collection": "^1.3.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.20", - "file-type": "^18.0.0", - "tslib": "^2.4.1", - "undici": "^5.13.0" + "@sapphire/snowflake": "^3.4.2", + "discord-api-types": "^0.37.41", + "file-type": "^18.3.0", + "tslib": "^2.5.0", + "undici": "^5.22.0" } }, "@discordjs/util": { - "version": "0.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==" + }, + "@discordjs/ws": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-0.8.3.tgz", + "integrity": "sha512-hcYtppanjHecbdNyCKQNH2I4RP9UrphDgmRgLYrATEQF1oo4sYSve7ZmGsBEXSzH72MO2tBPdWSThunbxUVk0g==", + "requires": { + "@discordjs/collection": "^1.5.1", + "@discordjs/rest": "^1.7.1", + "@discordjs/util": "^0.3.1", + "@sapphire/async-queue": "^1.5.0", + "@types/ws": "^8.5.4", + "@vladfrangu/async_event_emitter": "^2.2.1", + "discord-api-types": "^0.37.41", + "tslib": "^2.5.0", + "ws": "^8.13.0" + } + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true }, "@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", + "espree": "^9.5.2", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -10010,10 +10413,16 @@ "strip-json-comments": "^3.1.1" } }, + "@eslint/js": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", + "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", + "dev": true + }, "@humanwhocodes/config-array": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", - "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -10060,64 +10469,65 @@ } }, "@octokit/auth-token": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz", - "integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", + "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", "dev": true, "requires": { - "@octokit/types": "^8.0.0" + "@octokit/types": "^9.0.0" } }, "@octokit/core": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz", - "integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", + "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", "dev": true, "requires": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", "@octokit/request": "^6.0.0", "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" } }, "@octokit/endpoint": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz", - "integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", + "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", "dev": true, "requires": { - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" } }, "@octokit/graphql": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz", - "integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", "dev": true, "requires": { "@octokit/request": "^6.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "universal-user-agent": "^6.0.0" } }, "@octokit/openapi-types": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==", + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", + "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==", "dev": true }, "@octokit/plugin-paginate-rest": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz", - "integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", "dev": true, "requires": { - "@octokit/types": "^8.0.0" + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" } }, "@octokit/plugin-request-log": { @@ -10128,79 +10538,119 @@ "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz", - "integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.1.2.tgz", + "integrity": "sha512-R0oJ7j6f/AdqPLtB9qRXLO+wjI9pctUn8Ka8UGfGaFCcCv3Otx14CshQ89K4E88pmyYZS8p0rNTiprML/81jig==", "dev": true, "requires": { - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.2.3", "deprecation": "^2.3.1" } }, "@octokit/request": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", - "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", + "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", "dev": true, "requires": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.7", "universal-user-agent": "^6.0.0" } }, "@octokit/request-error": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz", - "integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", + "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", "dev": true, "requires": { - "@octokit/types": "^8.0.0", + "@octokit/types": "^9.0.0", "deprecation": "^2.0.0", "once": "^1.4.0" } }, "@octokit/rest": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz", - "integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==", + "version": "19.0.11", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", + "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", "dev": true, "requires": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^5.0.0", + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^6.7.0" + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" } }, + "@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==", + "dev": true + }, "@octokit/types": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", - "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", + "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", "dev": true, "requires": { - "@octokit/openapi-types": "^14.0.0" + "@octokit/openapi-types": "^17.2.0" + } + }, + "@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true + }, + "@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "requires": { + "graceful-fs": "4.2.10" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + } + } + }, + "@pnpm/npm-conf": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.0.tgz", + "integrity": "sha512-roLI1ul/GwzwcfcVpZYPdrgW2W/drLriObl1h+yLF5syc8/5ULWw2ALbCHUWF+4YltIqA3xFSbG4IwyJz37e9g==", + "dev": true, + "requires": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" } }, "@prisma/client": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.7.1.tgz", - "integrity": "sha512-/GbnOwIPtjiveZNUzGXOdp7RxTEkHL4DZP3vBaFNadfr6Sf0RshU5EULFzVaSi9i9PIK9PYd+1Rn7z2B2npb9w==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.14.1.tgz", + "integrity": "sha512-TZIswkeX1ccsHG/eN2kICzg/csXll0osK3EHu1QKd8VJ3XLcXozbNELKkCNfsCUvKJAwPdDtFCzF+O+raIVldw==", "requires": { - "@prisma/engines-version": "4.7.1-1.272861e07ab64f234d3ffc4094e32bd61775599c" + "@prisma/engines-version": "4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c" } }, "@prisma/engines": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.7.1.tgz", - "integrity": "sha512-zWabHosTdLpXXlMefHmnouhXMoTB1+SCbUU3t4FCmdrtIOZcarPKU3Alto7gm/pZ9vHlGOXHCfVZ1G7OIrSbog==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.14.1.tgz", + "integrity": "sha512-APqFddPVHYmWNKqc+5J5SqrLFfOghKOLZxobmguDUacxOwdEutLsbXPVhNnpFDmuQWQFbXmrTTPoRrrF6B1MWA==", "devOptional": true }, "@prisma/engines-version": { - "version": "4.7.1-1.272861e07ab64f234d3ffc4094e32bd61775599c", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.7.1-1.272861e07ab64f234d3ffc4094e32bd61775599c.tgz", - "integrity": "sha512-Bd4LZ+WAnUHOq31e9X/ihi5zPlr4SzTRwUZZYxvWOxlerIZ7HJlVa9zXpuKTKLpI9O1l8Ec4OYCKsivWCs5a3Q==" + "version": "4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c.tgz", + "integrity": "sha512-3jum8/YSudeSN0zGW5qkpz+wAN2V/NYCQ+BPjvHYDfWatLWlQkqy99toX0GysDeaUoBIJg1vaz2yKqiA3CFcQw==" }, "@sapphire/async-queue": { "version": "1.5.0", @@ -10208,18 +10658,18 @@ "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==" }, "@sapphire/shapeshift": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.8.0.tgz", - "integrity": "sha512-Ec8CqUy7CX87jM1AAUfVycNrKnKmfdOzJhq0gqlRRMQFPcarKV5z8P8TVFgN09E6bbKQW+Lh4Zsi+dzDadeyzw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.0.tgz", + "integrity": "sha512-iJpHmjAdwX9aSL6MvFpVyo+tkokDtInmSjoJHbz/k4VJfnim3DjvG0hgGEKWtWZgCu45RaLgcoNgR1fCPdIz3w==", "requires": { "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21" } }, "@sapphire/snowflake": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.3.0.tgz", - "integrity": "sha512-Hec5N6zEkZuZFLybVKyLFLlcSgYmR6C1/+9NkIhxPwOf6tgX52ndJCSz8ADejmbrNE0VuNCNkpzhRZzenEC9vA==" + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz", + "integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==" }, "@semantic-release/commit-analyzer": { "version": "9.0.2", @@ -10256,67 +10706,6 @@ "lodash": "^4.17.4", "micromatch": "^4.0.0", "p-reduce": "^2.0.0" - }, - "dependencies": { - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - } } }, "@semantic-release/github": { @@ -10344,96 +10733,24 @@ } }, "@semantic-release/npm": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-9.0.1.tgz", - "integrity": "sha512-I5nVZklxBzfMFwemhRNbSrkiN/dsH3c7K9+KSk6jUnq0rdLFUuJt7EBsysq4Ir3moajQgFkfEryEHPqiKJj20g==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-9.0.2.tgz", + "integrity": "sha512-zgsynF6McdzxPnFet+a4iO9HpAlARXOM5adz7VGVCvj0ne8wtL2ZOQoDV2wZPDmdEotDIbVeJjafhelZjs9j6g==", "dev": true, "requires": { "@semantic-release/error": "^3.0.0", "aggregate-error": "^3.0.0", "execa": "^5.0.0", - "fs-extra": "^10.0.0", + "fs-extra": "^11.0.0", "lodash": "^4.17.15", "nerf-dart": "^1.0.0", "normalize-url": "^6.0.0", "npm": "^8.3.0", "rc": "^1.2.8", "read-pkg": "^5.0.0", - "registry-auth-token": "^4.0.0", + "registry-auth-token": "^5.0.0", "semver": "^7.1.2", "tempy": "^1.0.0" - }, - "dependencies": { - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - } } }, "@semantic-release/release-notes-generator": { @@ -10465,6 +10782,15 @@ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true }, + "@types/axios": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz", + "integrity": "sha512-KqQnQbdYE54D7oa/UmYVMZKq7CO4l8DEENzOKc4aBRwxCXSlJXGz83flFx5L7AWrOQnmuN3kVsRdt+GZPPjiVQ==", + "dev": true, + "requires": { + "axios": "*" + } + }, "@types/chance": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@types/chance/-/chance-1.1.3.tgz", @@ -10498,9 +10824,9 @@ "dev": true }, "@types/node": { - "version": "18.11.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.14.tgz", - "integrity": "sha512-0KXV57tENYmmJMl+FekeW9V3O/rlcqGQQJ/hNh9r8pKIj304pskWuEd8fCyNT86g/TpO0gcOTiLzsHLEURFMIQ==" + "version": "20.2.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.3.tgz", + "integrity": "sha512-pg9d0yC4rVNWQzX8U7xb4olIOFuuVL9za3bzMT2pu2SU0SNEi66i2qrvhE2qt0HvkhuCaWJu7pLNOt/Pj8BIrw==" }, "@types/node-schedule": { "version": "2.1.0", @@ -10517,12 +10843,6 @@ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, "@types/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", @@ -10530,90 +10850,102 @@ "dev": true }, "@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, + "@types/triple-beam": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", + "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==" + }, "@types/uuid": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz", "integrity": "sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==", "dev": true }, + "@types/voca": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@types/voca/-/voca-1.4.2.tgz", + "integrity": "sha512-Vmw8euGSdVlcDV69LoixtuervYUim5u6Vgp41PNxrHVGIo4vxSKMhW0I9MmBKbk3gtveNFzdHIVzyW1DpECzYw==", + "dev": true + }, "@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", + "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", "requires": { "@types/node": "*" } }, "@typescript-eslint/eslint-plugin": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.46.1.tgz", - "integrity": "sha512-YpzNv3aayRBwjs4J3oz65eVLXc9xx0PDbIRisHj+dYhvBn02MjYOD96P8YGiWEIFBrojaUjxvkaUpakD82phsA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", + "integrity": "sha512-BL+jYxUFIbuYwy+4fF86k5vdT9lT0CNJ6HtwrIvGh0PhH8s0yy5rjaKH2fDCrz5ITHy07WCzVGNvAmjJh4IJFA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.46.1", - "@typescript-eslint/type-utils": "5.46.1", - "@typescript-eslint/utils": "5.46.1", + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/type-utils": "5.59.7", + "@typescript-eslint/utils": "5.59.7", "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" } }, "@typescript-eslint/parser": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.1.tgz", - "integrity": "sha512-RelQ5cGypPh4ySAtfIMBzBGyrNerQcmfA1oJvPj5f+H4jI59rl9xxpn4bonC0tQvUKOEN7eGBFWxFLK3Xepneg==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", + "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.46.1", - "@typescript-eslint/types": "5.46.1", - "@typescript-eslint/typescript-estree": "5.46.1", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.46.1.tgz", - "integrity": "sha512-iOChVivo4jpwUdrJZyXSMrEIM/PvsbbDOX1y3UCKjSgWn+W89skxWaYXACQfxmIGhPVpRWK/VWPYc+bad6smIA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", + "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.46.1", - "@typescript-eslint/visitor-keys": "5.46.1" + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7" } }, "@typescript-eslint/type-utils": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.46.1.tgz", - "integrity": "sha512-V/zMyfI+jDmL1ADxfDxjZ0EMbtiVqj8LUGPAGyBkXXStWmCUErMpW873zEHsyguWCuq2iN4BrlWUkmuVj84yng==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.7.tgz", + "integrity": "sha512-ozuz/GILuYG7osdY5O5yg0QxXUAEoI4Go3Do5xeu+ERH9PorHBPSdvD3Tjp2NN2bNLh1NJQSsQu2TPu/Ly+HaQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.46.1", - "@typescript-eslint/utils": "5.46.1", + "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/utils": "5.59.7", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.46.1.tgz", - "integrity": "sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", + "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.46.1.tgz", - "integrity": "sha512-j9W4t67QiNp90kh5Nbr1w92wzt+toiIsaVPnEblB2Ih2U9fqBTyqV9T3pYWZBRt6QoMh/zVWP59EpuCjc4VRBg==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", + "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.46.1", - "@typescript-eslint/visitor-keys": "5.46.1", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -10622,31 +10954,36 @@ } }, "@typescript-eslint/utils": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.46.1.tgz", - "integrity": "sha512-RBdBAGv3oEpFojaCYT4Ghn4775pdjvwfDOfQ2P6qzNVgQOVrnSPe5/Pb88kv7xzYQjoio0eKHKB9GJ16ieSxvA==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", + "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", "dev": true, "requires": { + "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.46.1", - "@typescript-eslint/types": "5.46.1", - "@typescript-eslint/typescript-estree": "5.46.1", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.46.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.46.1.tgz", - "integrity": "sha512-jczZ9noovXwy59KjRTk1OftT78pwygdcmCuBf8yMoWt/8O8l+6x2LSEze0E4TeepXK4MezW3zGSyoDRZK7Y9cg==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", + "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/types": "5.59.7", "eslint-visitor-keys": "^3.3.0" } }, + "@vladfrangu/async_event_emitter": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.2.tgz", + "integrity": "sha512-HIzRG7sy88UZjBJamssEczH5q7t5+axva19UbZLO6u0ySbYPrwzWiXBcC0WuHyhKKoeCyneH+FvYzKQq/zTtkQ==" + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -10654,9 +10991,9 @@ "dev": true }, "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true }, "acorn-jsx": { @@ -10757,6 +11094,16 @@ "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", "dev": true }, + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } + }, "array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -10794,6 +11141,18 @@ "es-shim-unscopables": "^1.0.0" } }, + "array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + } + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -10816,10 +11175,16 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, "axios": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz", - "integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "requires": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -10881,6 +11246,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -10930,9 +11296,9 @@ } }, "chance": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.9.tgz", - "integrity": "sha512-TfxnA/DcZXRTA4OekA2zL9GH8qscbbl6X0ZqU4tXhGveVY/mXWvEQLt5GwZcYXTEyEFflVtj+pG8nc8EwSm1RQ==" + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.11.tgz", + "integrity": "sha512-kqTg3WWywappJPqtgrdvbA380VoXO2eu9VCV895JgbyHsaErXdyHK9LOZ911OvAk6L0obK7kDk9CGs8+oBawVA==" }, "chokidar": { "version": "3.5.3", @@ -11022,13 +11388,13 @@ } }, "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "requires": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" }, "dependencies": { @@ -11105,9 +11471,9 @@ } }, "colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, "colorspace": { @@ -11128,9 +11494,9 @@ } }, "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": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true }, "compare-func": { @@ -11149,6 +11515,16 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "conventional-changelog-angular": { "version": "5.0.13", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", @@ -11215,33 +11591,23 @@ "dev": true }, "cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", "dev": true, "requires": { - "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "dependencies": { - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - } + "path-type": "^4.0.0" } }, "cron-parser": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz", - "integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.8.1.tgz", + "integrity": "sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ==", "requires": { - "is-nan": "^1.3.2", - "luxon": "^1.26.0" + "luxon": "^3.2.1" } }, "cross-spawn": { @@ -11262,9 +11628,12 @@ "dev": true }, "date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "requires": { + "@babel/runtime": "^7.21.0" + } }, "dateformat": { "version": "3.0.3", @@ -11318,9 +11687,10 @@ "dev": true }, "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, "requires": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" @@ -11363,27 +11733,29 @@ } }, "discord-api-types": { - "version": "0.37.22", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.22.tgz", - "integrity": "sha512-1FSm5hIUaxt3e+3H6lhY5Hg32DTJCPp3Q5gf3CM2CPSr95ZnqkSNEV0s7EdiBrlv5QoPrpcPIDYC3hWqZT2mIg==" + "version": "0.37.42", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.42.tgz", + "integrity": "sha512-1Huaj9cQ1W7/uryS8MZs/tZemnoKB94thM1cE40lep3rpU3q7WHqkdjN/veX0prTkYlPhcyLd/DeF/pBO8X8oQ==" }, "discord.js": { - "version": "14.7.1", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.1.tgz", - "integrity": "sha512-1FECvqJJjjeYcjSm0IGMnPxLqja/pmG1B0W2l3lUY2Gi4KXiyTeQmU1IxWcbXHn2k+ytP587mMWqva2IA87EbA==", + "version": "14.11.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.11.0.tgz", + "integrity": "sha512-CkueWYFQ28U38YPR8HgsBR/QT35oPpMbEsTNM30Fs8loBIhnA4s70AwQEoy6JvLcpWWJO7GY0y2BUzZmuBMepQ==", "requires": { - "@discordjs/builders": "^1.4.0", - "@discordjs/collection": "^1.3.0", - "@discordjs/rest": "^1.4.0", - "@discordjs/util": "^0.1.0", - "@sapphire/snowflake": "^3.2.2", - "@types/ws": "^8.5.3", - "discord-api-types": "^0.37.20", + "@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.1", - "undici": "^5.13.0", - "ws": "^8.11.0" + "tslib": "^2.5.0", + "undici": "^5.22.0", + "ws": "^8.13.0" } }, "doctrine": { @@ -11416,38 +11788,6 @@ "dev": true, "requires": { "readable-stream": "^2.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "eastasianwidth": { @@ -11468,73 +11808,78 @@ "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, "env-ci": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-5.5.0.tgz", - "integrity": "sha512-o0JdWIbOLP+WJKIUt36hz1ImQQFuN92nhsfTkHHap+J8CiI8WgGpH/a9jEGHh4/TU5BUUGjlnKXNoDb57+ne+A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-8.0.0.tgz", + "integrity": "sha512-W+3BqGZozFua9MPeXpmTm5eYEBtGgL76jGu/pwMVp/L8PdECSCEWaIp7d4Mw7kuUrbUldK0oV0bNd6ZZjLiMiA==", "dev": true, "requires": { - "execa": "^5.0.0", - "fromentries": "^1.3.2", - "java-properties": "^1.0.0" + "execa": "^6.1.0", + "java-properties": "^1.0.2" }, "dependencies": { "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", "dev": true, "requires": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" } }, "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", "dev": true }, "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true }, "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true }, "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", "dev": true, "requires": { - "path-key": "^3.0.0" + "path-key": "^4.0.0" } }, "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, "requires": { - "mimic-fn": "^2.1.0" + "mimic-fn": "^4.0.0" } }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true } } @@ -11549,36 +11894,56 @@ } }, "es-abstract": { - "version": "1.20.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.5.tgz", - "integrity": "sha512-7h8MM2EQhsCA7pU/Nv78qOXFpD8Rhqd12gYiSJVkrH9+e8VuA8JlPJK/hQjjlLv6pJvx/z1iRFKzYb0XT/RuAQ==", + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", "dev": true, "requires": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.0", "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", "gopd": "^1.0.1", "has": "^1.0.3", "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "object-inspect": "^1.12.3", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.4.3", "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", "string.prototype.trimend": "^1.0.6", "string.prototype.trimstart": "^1.0.6", - "unbox-primitive": "^1.0.2" + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + } + }, + "es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" } }, "es-shim-unscopables": { @@ -11614,13 +11979,16 @@ "dev": true }, "eslint": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz", - "integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.11.6", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.41.0", + "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", @@ -11629,24 +11997,22 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.15.0", - "grapheme-splitter": "^1.0.4", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -11654,16 +12020,15 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "dependencies": { "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -11686,13 +12051,14 @@ "requires": {} }, "eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", "dev": true, "requires": { "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" }, "dependencies": { "debug": { @@ -11707,9 +12073,9 @@ } }, "eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, "requires": { "debug": "^3.2.7" @@ -11727,33 +12093,35 @@ } }, "eslint-plugin-import": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", - "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", + "version": "2.27.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.4.tgz", + "integrity": "sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==", "dev": true, "requires": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.0", + "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", "has": "^1.0.3", - "is-core-module": "^2.8.1", + "is-core-module": "^2.11.0", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", "tsconfig-paths": "^3.14.1" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "doctrine": { @@ -11765,10 +12133,10 @@ "esutils": "^2.0.2" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -11799,38 +12167,21 @@ "estraverse": "^4.1.1" } }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true }, "espree": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", - "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "requires": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" } }, "esprima": { @@ -11840,9 +12191,9 @@ "dev": true }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -11886,20 +12237,20 @@ "dev": true }, "execa": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", - "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "requires": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^3.0.1", - "is-stream": "^3.0.0", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" } }, "fast-deep-equal": { @@ -11908,9 +12259,9 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true }, "fast-glob": { @@ -11950,9 +12301,9 @@ "dev": true }, "fastq": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", - "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -11964,18 +12315,19 @@ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5" + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" }, "dependencies": { "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true } } @@ -11998,9 +12350,9 @@ } }, "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.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.4.0.tgz", + "integrity": "sha512-o6MQrZKTAK6WpvmQk3jqTVUmqxYBxW5bloUfrdH1ZnRFDvvAPNr+l+rgOxM3nkqWT+3khaj3FRMDydWe0xhu+w==", "requires": { "readable-web-to-node-stream": "^3.0.2", "strtok3": "^7.0.0", @@ -12027,12 +12379,12 @@ } }, "find-versions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", - "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", + "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==", "dev": true, "requires": { - "semver-regex": "^3.1.2" + "semver-regex": "^4.0.5" } }, "flat-cache": { @@ -12061,6 +12413,15 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, "form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -12079,50 +12440,12 @@ "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, - "fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true - }, "fs-extra": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", - "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", "dev": true, "requires": { "graceful-fs": "^4.2.0", @@ -12146,7 +12469,8 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "function.prototype.name": { "version": "1.1.5", @@ -12173,12 +12497,14 @@ "dev": true }, "get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" } }, @@ -12212,27 +12538,6 @@ "traverse": "~0.6.6" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "split2": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", @@ -12242,15 +12547,6 @@ "through2": "~2.0.0" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -12287,14 +12583,23 @@ } }, "globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "requires": { "type-fest": "^0.20.2" } }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, "globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -12319,9 +12624,9 @@ } }, "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "grapheme-splitter": { @@ -12330,6 +12635,12 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "handlebars": { "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", @@ -12353,6 +12664,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -12373,14 +12685,22 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, "requires": { "get-intrinsic": "^1.1.1" } }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true + }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true }, "has-tostringtag": { "version": "1.0.0", @@ -12392,9 +12712,9 @@ } }, "hook-std": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-2.0.0.tgz", - "integrity": "sha512-zZ6T5WcuBMIUVh49iPQS9t977t7C0l7OtHrpeMb5uk48JdflRX0NSFvCekfYNmGQETnLq9W/isMyHl69kxGi8g==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz", + "integrity": "sha512-jHRQzjSDzMtFy34AGj1DN+vq54WVuhSvKgrHf0OMiFQTwDD4L/qqofVEWjLOBMTn5+lCD3fPg32W9yOfnEJTTw==", "dev": true }, "hosted-git-info": { @@ -12428,9 +12748,9 @@ } }, "human-signals": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", - "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, "i18next": { @@ -12447,9 +12767,9 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", - "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, "ignore-by-default": { @@ -12508,12 +12828,12 @@ "dev": true }, "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "dev": true, "requires": { - "get-intrinsic": "^1.1.0", + "get-intrinsic": "^1.2.0", "has": "^1.0.3", "side-channel": "^1.0.4" } @@ -12528,6 +12848,17 @@ "p-is-promise": "^3.0.0" } }, + "is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -12569,9 +12900,9 @@ "dev": true }, "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", "dev": true, "requires": { "has": "^1.0.3" @@ -12607,15 +12938,6 @@ "is-extglob": "^2.1.1" } }, - "is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - } - }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -12687,10 +13009,9 @@ } }, "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" }, "is-string": { "version": "1.0.7", @@ -12719,6 +13040,25 @@ "text-extensions": "^1.0.0" } }, + "is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, + "is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true + }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -12759,12 +13099,6 @@ "integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==", "dev": true }, - "js-sdsl": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", - "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==", - "dev": true - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -12811,9 +13145,9 @@ "dev": true }, "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "requires": { "minimist": "^1.2.0" @@ -12879,9 +13213,9 @@ "dev": true }, "lint-staged": { - "version": "13.0.4", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.0.4.tgz", - "integrity": "sha512-HxlHCXoYRsq9QCby5wFozmZW00hMs/9e3l+/dz6Qr8Kle4UH0kJTdABAbqhzG+3pcG6QjL9kz7NgGBfph+a5dw==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.1.0.tgz", + "integrity": "sha512-pn/sR8IrcF/T0vpWLilih8jmVouMlxqXxKuAojmbiGX5n/gDnz+abdPptlj0vYnbfE0SQNl3CY/HwtM0+yfOVQ==", "dev": true, "requires": { "cli-truncate": "^3.1.0", @@ -12897,12 +13231,79 @@ "pidtree": "^0.6.0", "string-argv": "^0.3.1", "yaml": "^2.1.3" + }, + "dependencies": { + "execa": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + } } }, "listr2": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.6.tgz", - "integrity": "sha512-u60KxKBy1BR2uLJNTWNptzWQ1ob/gjMzIJPZffAENzpZqbMZ/5PrXXOomDcevIS/+IB7s1mmCEtSlT2qHWMqag==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", + "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", "dev": true, "requires": { "cli-truncate": "^2.1.0", @@ -12910,7 +13311,7 @@ "log-update": "^4.0.0", "p-map": "^4.0.0", "rfdc": "^1.3.0", - "rxjs": "^7.5.7", + "rxjs": "^7.8.0", "through": "^2.3.8", "wrap-ansi": "^7.0.0" }, @@ -12999,6 +13400,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true + }, "lodash.capitalize": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", @@ -13106,11 +13513,12 @@ } }, "logform": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.4.2.tgz", - "integrity": "sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", + "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", "requires": { "@colors/colors": "1.5.0", + "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", @@ -13132,9 +13540,9 @@ } }, "luxon": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", - "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz", + "integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==" }, "map-obj": { "version": "4.3.0", @@ -13143,32 +13551,32 @@ "dev": true }, "marked": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.4.tgz", - "integrity": "sha512-Wcc9ikX7Q5E4BYDPvh1C6QNSxrjC9tBgz+A/vAhp59KXUgachw++uMvMKiSW8oA85nopmPZcEvBoex/YLMsiyA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true }, "marked-terminal": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.1.1.tgz", - "integrity": "sha512-+cKTOx9P4l7HwINYhzbrBSyzgxO2HaHKGZGuB1orZsMIgXYaJyfidT81VXRdpelW/PcHEWxywscePVgI/oUF6g==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.2.0.tgz", + "integrity": "sha512-Piv6yNwAQXGFjZSaiNljyNFw7jKDdGrw70FSbtxEyldLsyeuV5ZHm/1wW++kWbrOF1VPnUgYOhB2oLL0ZpnekA==", "dev": true, "requires": { - "ansi-escapes": "^5.0.0", + "ansi-escapes": "^6.2.0", "cardinal": "^2.1.1", - "chalk": "^5.0.0", - "cli-table3": "^0.6.1", + "chalk": "^5.2.0", + "cli-table3": "^0.6.3", "node-emoji": "^1.11.0", - "supports-hyperlinks": "^2.2.0" + "supports-hyperlinks": "^2.3.0" }, "dependencies": { "ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", "dev": true, "requires": { - "type-fest": "^1.0.2" + "type-fest": "^3.0.0" } }, "chalk": { @@ -13178,9 +13586,9 @@ "dev": true }, "type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.11.0.tgz", + "integrity": "sha512-JaPw5U9ixP0XcpUbQoVSbxSDcK/K4nww20C3kjm9yE6cDRRhptU28AH60VWf9ltXmCrIfIbtt9J+2OUk2Uqiaw==", "dev": true } } @@ -13254,9 +13662,9 @@ } }, "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, "min-indent": { @@ -13275,9 +13683,9 @@ } }, "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, "minimist-options": { @@ -13341,20 +13749,20 @@ } }, "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "dev": true, "requires": { "whatwg-url": "^5.0.0" } }, "node-schedule": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.0.tgz", - "integrity": "sha512-nl4JTiZ7ZQDc97MmpTq9BQjYhq7gOtoh7SiPH069gBFBj0PzD8HI7zyFs6rzqL8Y5tTiEEYLxgtbx034YPrbyQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.1.tgz", + "integrity": "sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==", "requires": { - "cron-parser": "^3.5.0", + "cron-parser": "^4.2.0", "long-timeout": "0.1.1", "sorted-array-functions": "^1.3.0" } @@ -13443,9 +13851,9 @@ "dev": true }, "npm": { - "version": "8.19.3", - "resolved": "https://registry.npmjs.org/npm/-/npm-8.19.3.tgz", - "integrity": "sha512-0QjmyPtDxSyMWWD8I91QGbrgx9KzbV6C9FK1liEb/K0zppiZkr5KxXc990G+LzPwBHDfRjUBlO9T1qZ08vl9mA==", + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/npm/-/npm-8.19.4.tgz", + "integrity": "sha512-3HANl8i9DKnUA89P4KEgVNN28EjSeDCmvEqbzOAuxCFDzdBZzjUl99zgnGpOUumvW5lvJo2HKcjrsc+tfyv1Hw==", "dev": true, "requires": { "@isaacs/string-locale-compare": "^1.1.0", @@ -14142,7 +14550,7 @@ } }, "http-cache-semantics": { - "version": "4.1.0", + "version": "4.1.1", "bundled": true, "dev": true }, @@ -15232,20 +15640,12 @@ } }, "npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "requires": { - "path-key": "^4.0.0" - }, - "dependencies": { - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true - } + "path-key": "^3.0.0" } }, "object-hash": { @@ -15254,15 +15654,16 @@ "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==" }, "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "dev": true }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, "object.assign": { "version": "4.1.4", @@ -15305,12 +15706,12 @@ } }, "onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { - "mimic-fn": "^4.0.0" + "mimic-fn": "^2.1.0" } }, "optionator": { @@ -15328,9 +15729,9 @@ } }, "p-each-series": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", - "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-3.0.0.tgz", + "integrity": "sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==", "dev": true }, "p-filter": { @@ -15541,9 +15942,9 @@ "dev": true }, "prettier": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.0.tgz", - "integrity": "sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.2.tgz", + "integrity": "sha512-BtRV9BcncDyI2tsuS19zzhzoxD8Dh8LiCx7j7tHzrkz8GFXAexeWFdi22mjE1d16dftH2qNaytVxqiRTGlMfpw==", "dev": true }, "prettier-linter-helpers": { @@ -15556,12 +15957,12 @@ } }, "prisma": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.7.1.tgz", - "integrity": "sha512-CCQP+m+1qZOGIZlvnL6T3ZwaU0LAleIHYFPN9tFSzjs/KL6vH9rlYbGOkTuG9Q1s6Ki5D0LJlYlW18Z9EBUpGg==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.14.1.tgz", + "integrity": "sha512-z6hxzTMYqT9SIKlzD08dhzsLUpxjFKKsLpp5/kBDnSqiOjtUyyl/dC5tzxLcOa3jkEHQ8+RpB/fE3w8bgNP51g==", "devOptional": true, "requires": { - "@prisma/engines": "4.7.1" + "@prisma/engines": "4.14.1" } }, "process-nextick-args": { @@ -15570,6 +15971,12 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -15582,9 +15989,9 @@ "dev": true }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true }, "q": { @@ -15732,13 +16139,18 @@ } }, "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": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "readable-web-to-node-stream": { @@ -15747,6 +16159,18 @@ "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", "requires": { "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "readdirp": { @@ -15783,29 +16207,23 @@ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" } }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, "registry-auth-token": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", - "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", "dev": true, "requires": { - "rc": "1.2.8" + "@pnpm/npm-conf": "^2.1.0" } }, "require-directory": { @@ -15815,12 +16233,12 @@ "dev": true }, "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dev": true, "requires": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -15839,23 +16257,6 @@ "requires": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" - }, - "dependencies": { - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - } } }, "retry": { @@ -15895,18 +16296,18 @@ } }, "rxjs": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.6.0.tgz", - "integrity": "sha512-DDa7d8TFNUalGC9VqXvQ1euWNN7sc63TrUCuM9J998+ViviahMIjKSOU7rfcgFOF+FCD71BhDRv4hrFz+ImDLQ==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, "requires": { "tslib": "^2.1.0" } }, "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safe-regex-test": { "version": "1.0.0", @@ -15920,14 +16321,14 @@ } }, "safe-stable-stringify": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.1.tgz", - "integrity": "sha512-dVHE6bMtS/bnL2mwualjc6IxEv1F+OCUpA46pKUj6F8uDbUM0jCCulPqRNPSnWwGNKx5etqMjZYdXtrm5KJZGA==" + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==" }, "semantic-release": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.5.tgz", - "integrity": "sha512-NMPKdfpXTnPn49FDogMBi36SiBfXkSOJqCkk0E4iWOY1tusvvgBwqUmxTX1kmlT6kIYed9YwNKD1sfPpqa5yaA==", + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-20.1.3.tgz", + "integrity": "sha512-sMIK9IaOdLP9hxzTxdTVHxINsazlDgv2gjZ1yeyRZXpIT3xAnuQUDEez8k+AC+lFUtGnfzA2Ct3V5lDyiMestw==", "dev": true, "requires": { "@semantic-release/commit-analyzer": "^9.0.2", @@ -15935,82 +16336,206 @@ "@semantic-release/github": "^8.0.0", "@semantic-release/npm": "^9.0.0", "@semantic-release/release-notes-generator": "^10.0.0", - "aggregate-error": "^3.0.0", - "cosmiconfig": "^7.0.0", + "aggregate-error": "^4.0.1", + "cosmiconfig": "^8.0.0", "debug": "^4.0.0", - "env-ci": "^5.0.0", - "execa": "^5.0.0", - "figures": "^3.0.0", - "find-versions": "^4.0.0", + "env-ci": "^8.0.0", + "execa": "^7.0.0", + "figures": "^5.0.0", + "find-versions": "^5.1.0", "get-stream": "^6.0.0", "git-log-parser": "^1.2.0", - "hook-std": "^2.0.0", - "hosted-git-info": "^4.0.0", - "lodash": "^4.17.21", - "marked": "^4.0.10", - "marked-terminal": "^5.0.0", + "hook-std": "^3.0.0", + "hosted-git-info": "^6.0.0", + "lodash-es": "^4.17.21", + "marked": "^4.1.0", + "marked-terminal": "^5.1.1", "micromatch": "^4.0.2", - "p-each-series": "^2.1.0", - "p-reduce": "^2.0.0", - "read-pkg-up": "^7.0.0", + "p-each-series": "^3.0.0", + "p-reduce": "^3.0.0", + "read-pkg-up": "^9.1.0", "resolve-from": "^5.0.0", "semver": "^7.3.2", - "semver-diff": "^3.1.1", + "semver-diff": "^4.0.0", "signale": "^1.2.1", - "yargs": "^16.2.0" + "yargs": "^17.5.1" }, "dependencies": { + "aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "requires": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + } + }, + "clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "requires": { + "escape-string-regexp": "5.0.0" + } + }, + "escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true + }, "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", + "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", "dev": true, "requires": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "requires": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + } + }, + "hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, + "requires": { + "lru-cache": "^7.5.1" } }, "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true + }, + "indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "dev": true }, "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "requires": { + "p-locate": "^6.0.0" + } + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true }, "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true }, "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", "dev": true, "requires": { - "path-key": "^3.0.0" + "path-key": "^4.0.0" } }, "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, "requires": { - "mimic-fn": "^2.1.0" + "mimic-fn": "^4.0.0" + } + }, + "p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "requires": { + "yocto-queue": "^1.0.0" + } + }, + "p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "requires": { + "p-limit": "^4.0.0" + } + }, + "p-reduce": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", + "integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==", + "dev": true + }, + "path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "read-pkg": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz", + "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.1", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz", + "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==", + "dev": true, + "requires": { + "find-up": "^6.3.0", + "read-pkg": "^7.1.0", + "type-fest": "^2.5.0" } }, "resolve-from": { @@ -16020,43 +16545,47 @@ "dev": true }, "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + }, + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true + }, + "yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", "dev": true } } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, "semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", "dev": true, "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "semver": "^7.3.5" } }, "semver-regex": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", - "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", + "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", "dev": true }, "shebang-command": { @@ -16243,9 +16772,9 @@ "dev": true }, "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -16269,9 +16798,9 @@ } }, "spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, "split": { @@ -16290,6 +16819,19 @@ "dev": true, "requires": { "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "stack-trace": { @@ -16305,38 +16847,6 @@ "requires": { "duplexer2": "~0.1.0", "readable-stream": "^2.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "streamsearch": { @@ -16345,17 +16855,17 @@ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" }, "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "~5.2.0" + "safe-buffer": "~5.1.0" } }, "string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true }, "string-width": { @@ -16386,6 +16896,17 @@ } } }, + "string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, "string.prototype.trimend": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", @@ -16424,9 +16945,9 @@ "dev": true }, "strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true }, "strip-indent": { @@ -16497,12 +17018,6 @@ "unique-string": "^2.0.0" }, "dependencies": { - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, "type-fest": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", @@ -16541,6 +17056,19 @@ "dev": true, "requires": { "readable-stream": "3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "to-regex-range": { @@ -16594,26 +17122,26 @@ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "ts-mixer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.2.tgz", - "integrity": "sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A==" + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", + "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" }, "tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", "dev": true, "requires": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", + "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" }, "tsutils": { "version": "3.21.0", @@ -16647,10 +17175,21 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, "typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" }, "uglify-js": { "version": "3.17.4", @@ -16678,9 +17217,9 @@ "dev": true }, "undici": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.14.0.tgz", - "integrity": "sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==", + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", + "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", "requires": { "busboy": "^1.6.0" } @@ -16741,6 +17280,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "voca": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/voca/-/voca-1.4.1.tgz", + "integrity": "sha512-NJC/BzESaHT1p4B5k4JykxedeltmNbau4cummStd4RjFojgq/kLew5TzYge9N2geeWyI2w8T30wUET5v+F7ZHA==" + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -16779,6 +17323,20 @@ "is-symbol": "^1.0.3" } }, + "which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + } + }, "winston": { "version": "3.8.2", "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz", @@ -16797,10 +17355,15 @@ "winston-transport": "^4.5.0" }, "dependencies": { - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } } } }, @@ -16823,6 +17386,18 @@ "logform": "^2.3.2", "readable-stream": "^3.6.0", "triple-beam": "^1.3.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "word-wrap": { @@ -16880,9 +17455,9 @@ "dev": true }, "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==", "requires": {} }, "xtend": { @@ -16904,24 +17479,24 @@ "dev": true }, "yaml": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz", - "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.0.tgz", + "integrity": "sha512-8/1wgzdKc7bc9E6my5wZjmdavHLvO/QOmLG1FBugblEvY4IXrLjlViIOmL24HthU042lWTDRO90Fz1Yp66UnMw==", "dev": true }, "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "dependencies": { "emoji-regex": { @@ -16946,6 +17521,12 @@ "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true } } }, diff --git a/package.json b/package.json index 3f9959b..4e6e5eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xyter", - "version": "1.3.5", + "version": "1.4.4", "private": true, "description": "A multi purpose Discord bot written in TypeScript with Discord.js", "main": "dist/index.js", @@ -36,7 +36,7 @@ "dependencies": { "@prisma/client": "^4.7.1", "@types/i18next-fs-backend": "^1.1.2", - "axios": "^1.2.1", + "axios": "^1.4.0", "chance": "^1.1.9", "date-fns": "^2.29.3", "discord.js": "^14.7.1", @@ -44,26 +44,30 @@ "node-schedule": "^2.1.0", "typescript": "^4.9.4", "uuid": "^9.0.0", + "voca": "^1.4.0", "winston": "^3.8.2", "winston-daily-rotate-file": "^4.7.1" }, "devDependencies": { + "@semantic-release/git": "^10.0.1", + "@semantic-release/release-notes-generator": "^10.0.3", + "@types/axios": "^0.14.0", "@types/chance": "1.1.3", "@types/node-schedule": "2.1.0", "@types/uuid": "9.0.0", + "@types/voca": "^1.4.2", "@typescript-eslint/eslint-plugin": "^5.46.1", "@typescript-eslint/parser": "^5.46.1", "eslint": "^8.29.0", "eslint-config-prettier": "8.5.0", - "eslint-plugin-import": "2.26.0", + "eslint-plugin-import": "2.27.4", "eslint-plugin-no-loops": "0.3.0", "eslint-plugin-prettier": "4.2.1", - "lint-staged": "13.0.4", + "lint-staged": "13.1.0", "nodemon": "2.0.20", - "prettier": "2.8.0", - "prisma": "^4.7.1", - "semantic-release": "^19.0.5", - "@semantic-release/git": "^10.0.1" + "prettier": "2.8.2", + "prisma": "^4.9.0", + "semantic-release": "^20.0.0" }, "lint-staged": { "*.ts": "eslint --cache --fix" diff --git a/prisma/migrations/20221023164351_init/migration.sql b/prisma/migrations/20221023164351_init/migration.sql deleted file mode 100644 index 6c8b330..0000000 --- a/prisma/migrations/20221023164351_init/migration.sql +++ /dev/null @@ -1,158 +0,0 @@ --- CreateTable -CREATE TABLE `Guild` ( - `id` VARCHAR(191) NOT NULL, - `embedColorSuccess` VARCHAR(191) NOT NULL DEFAULT '#22bb33', - `embedColorWait` VARCHAR(191) NOT NULL DEFAULT '#f0ad4e', - `embedColorError` VARCHAR(191) NOT NULL DEFAULT '#bb2124', - `embedFooterText` VARCHAR(191) NOT NULL DEFAULT 'https://github.com/ZynerOrg/xyter', - `embedFooterIcon` VARCHAR(191) NOT NULL DEFAULT 'https://github.com/ZynerOrg.png', - `creditsEnabled` BOOLEAN NOT NULL DEFAULT FALSE, - `creditsRate` INTEGER NOT NULL DEFAULT 1, - `creditsTimeout` INTEGER NOT NULL DEFAULT 5, - `creditsWorkRate` INTEGER NOT NULL DEFAULT 25, - `creditsWorkTimeout` INTEGER NOT NULL DEFAULT 86400, - `creditsMinimumLength` INTEGER NOT NULL DEFAULT 5, - `pointsEnabled` BOOLEAN NOT NULL DEFAULT FALSE, - `pointsRate` INTEGER NOT NULL DEFAULT 1, - `pointsTimeout` INTEGER NOT NULL DEFAULT 5, - `pointsMinimumLength` INTEGER NOT NULL DEFAULT 5, - `reputationsEnabled` BOOLEAN NOT NULL DEFAULT FALSE, - `countersEnabled` BOOLEAN NOT NULL DEFAULT FALSE, - `apiCpggUrlIv` VARCHAR(191) NULL, - `apiCpggUrlContent` VARCHAR(191) NULL, - `apiCpggTokenIv` VARCHAR(191) NULL, - `apiCpggTokenContent` VARCHAR(191) NULL, - `auditsEnabled` BOOLEAN NOT NULL DEFAULT FALSE, - `auditsChannelId` VARCHAR(191) NULL, - `shopRolesEnabled` BOOLEAN NOT NULL DEFAULT FALSE, - `shopRolesPricePerHour` INTEGER NOT NULL DEFAULT 5, - `welcomeEnabled` BOOLEAN NOT NULL DEFAULT FALSE, - `welcomeJoinChannelId` VARCHAR(191) NULL, - `welcomeJoinChannelMessage` VARCHAR(191) NULL, - `welcomeLeaveChannelId` VARCHAR(191) NULL, - `welcomeLeaveChannelMessage` VARCHAR(191) NULL, - `createdAt` DATETIME (3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - `updatedAt` DATETIME (3) NOT NULL, - UNIQUE INDEX `Guild_id_key` (`id`)) -DEFAULT CHARACTER -SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- CreateTable - -CREATE TABLE `User` ( - `id` VARCHAR(191) NOT NULL, - `reputationsEarned` INTEGER NOT NULL DEFAULT 0, - `createdAt` DATETIME (3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - `updatedAt` DATETIME (3) NOT NULL, - UNIQUE INDEX `User_id_key` (`id`)) -DEFAULT CHARACTER -SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- CreateTable - -CREATE TABLE `GuildMember` ( - `userId` VARCHAR(191) NOT NULL, - `guildId` VARCHAR(191) NOT NULL, - `creditsEarned` INTEGER NOT NULL DEFAULT 0, - `pointsEarned` INTEGER NOT NULL DEFAULT 0, - `createdAt` DATETIME (3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - `updatedAt` DATETIME (3) NOT NULL, - UNIQUE INDEX `GuildMember_userId_guildId_key` (`userId`, `guildId`)) -DEFAULT CHARACTER -SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- CreateTable - -CREATE TABLE `GuildCounter` ( - `guildId` VARCHAR(191) NOT NULL, - `channelId` VARCHAR(191) NOT NULL, - `triggerWord` VARCHAR(191) NOT NULL, - `count` INTEGER NOT NULL DEFAULT 0, - `createdAt` DATETIME (3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - `updatedAt` DATETIME (3) NOT NULL, - UNIQUE INDEX `GuildCounter_guildId_channelId_key` (`guildId`, `channelId`)) -DEFAULT CHARACTER -SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- CreateTable - -CREATE TABLE `Cooldown` ( - `guildId` VARCHAR(191) NOT NULL, - `userId` VARCHAR(191) NOT NULL, - `cooldown` INTEGER NOT NULL, - `timeoutId` VARCHAR(191) NOT NULL, - `createdAt` DATETIME (3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - `updatedAt` DATETIME (3) NOT NULL, - UNIQUE INDEX `Cooldown_guildId_userId_timeoutId_key` (`guildId`, `userId`, `timeoutId`)) -DEFAULT CHARACTER -SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- CreateTable - -CREATE TABLE `GuildShopRoles` ( - `guildId` VARCHAR(191) NOT NULL, - `roleId` VARCHAR(191) NOT NULL, - `userId` VARCHAR(191) NOT NULL, - `pricePerHour` INTEGER NOT NULL DEFAULT 5, - `lastPayed` DATETIME (3) NOT NULL, - `createdAt` DATETIME (3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - `updatedAt` DATETIME (3) NOT NULL, - UNIQUE INDEX `GuildShopRoles_guildId_userId_roleId_key` (`guildId`, `userId`, `roleId`)) -DEFAULT CHARACTER -SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- AddForeignKey - -ALTER TABLE `GuildMember` - ADD CONSTRAINT `GuildMember_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) ON DELETE RESTRICT ON - UPDATE - CASCADE; - --- AddForeignKey - -ALTER TABLE `GuildMember` - ADD CONSTRAINT `GuildMember_guildId_fkey` FOREIGN KEY (`guildId`) REFERENCES `Guild` (`id`) ON DELETE RESTRICT ON - UPDATE - CASCADE; - --- AddForeignKey - -ALTER TABLE `GuildCounter` - ADD CONSTRAINT `GuildCounter_guildId_fkey` FOREIGN KEY (`guildId`) REFERENCES `Guild` (`id`) ON DELETE RESTRICT ON - UPDATE - CASCADE; - --- AddForeignKey - -ALTER TABLE `Cooldown` - ADD CONSTRAINT `Cooldown_guildId_fkey` FOREIGN KEY (`guildId`) REFERENCES `Guild` (`id`) ON DELETE RESTRICT ON - UPDATE - CASCADE; - --- AddForeignKey - -ALTER TABLE `Cooldown` - ADD CONSTRAINT `Cooldown_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) ON DELETE RESTRICT ON - UPDATE - CASCADE; - --- AddForeignKey - -ALTER TABLE `GuildShopRoles` - ADD CONSTRAINT `GuildShopRoles_guildId_fkey` FOREIGN KEY (`guildId`) REFERENCES `Guild` (`id`) ON DELETE RESTRICT ON - UPDATE - CASCADE; - --- AddForeignKey - -ALTER TABLE `GuildShopRoles` - ADD CONSTRAINT `GuildShopRoles_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) ON DELETE RESTRICT ON - UPDATE - CASCADE; - --- AddForeignKey - -ALTER TABLE `GuildShopRoles` - ADD CONSTRAINT `GuildShopRoles_userId_guildId_fkey` FOREIGN KEY (`userId`, `guildId`) REFERENCES `GuildMember` (`userId`, `guildId`) ON DELETE RESTRICT ON - UPDATE - CASCADE; diff --git a/prisma/migrations/20230524131536_init/migration.sql b/prisma/migrations/20230524131536_init/migration.sql new file mode 100644 index 0000000..46ab7fd --- /dev/null +++ b/prisma/migrations/20230524131536_init/migration.sql @@ -0,0 +1,153 @@ +-- CreateTable +CREATE TABLE `Guild` ( + `id` VARCHAR(191) NOT NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + + UNIQUE INDEX `Guild_id_key`(`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `User` ( + `id` VARCHAR(191) NOT NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + + UNIQUE INDEX `User_id_key`(`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `GuildMember` ( + `guildId` VARCHAR(191) NOT NULL, + `userId` VARCHAR(191) NOT NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + + UNIQUE INDEX `GuildMember_guildId_userId_key`(`guildId`, `userId`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `GuildMemberCredit` ( + `guildId` VARCHAR(191) NOT NULL, + `userId` VARCHAR(191) NOT NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `balance` INTEGER NOT NULL DEFAULT 0, + + UNIQUE INDEX `GuildMemberCredit_guildId_userId_key`(`guildId`, `userId`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `UserReputation` ( + `id` VARCHAR(191) NOT NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `negative` INTEGER NOT NULL DEFAULT 0, + `positive` INTEGER NOT NULL DEFAULT 0, + + UNIQUE INDEX `UserReputation_id_key`(`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `GuildSettings` ( + `id` VARCHAR(191) NOT NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + `guildCreditsSettingsId` VARCHAR(191) NULL, + + UNIQUE INDEX `GuildSettings_id_key`(`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `GuildCreditsSettings` ( + `id` VARCHAR(191) NOT NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + `workBonusChance` INTEGER NOT NULL DEFAULT 30, + `workPenaltyChance` INTEGER NOT NULL DEFAULT 10, + `status` BOOLEAN NOT NULL DEFAULT false, + `rate` INTEGER NOT NULL DEFAULT 1, + `timeout` INTEGER NOT NULL DEFAULT 5, + `workRate` INTEGER NOT NULL DEFAULT 25, + `workTimeout` INTEGER NOT NULL DEFAULT 86400, + `minimumLength` INTEGER NOT NULL DEFAULT 5, + + UNIQUE INDEX `GuildCreditsSettings_id_key`(`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `ApiCredentials` ( + `id` VARCHAR(191) NOT NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + `guildId` VARCHAR(191) NULL, + `userId` VARCHAR(191) NULL, + `apiName` VARCHAR(191) NOT NULL, + `credentials` JSON NOT NULL, + + UNIQUE INDEX `ApiCredentials_guildId_apiName_key`(`guildId`, `apiName`), + UNIQUE INDEX `ApiCredentials_userId_apiName_key`(`userId`, `apiName`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `Cooldown` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `cooldownItem` VARCHAR(191) NOT NULL, + `expiresAt` DATETIME(3) NOT NULL, + `guildId` VARCHAR(191) NULL, + `userId` VARCHAR(191) NULL, + + INDEX `cooldownItem_guildId_idx`(`cooldownItem`, `guildId`), + INDEX `cooldownItem_userId_idx`(`cooldownItem`, `userId`), + INDEX `cooldownItem_guildId_userId_idx`(`cooldownItem`, `guildId`, `userId`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `ImportOldData` ( + `id` VARCHAR(191) NOT NULL, + `done` BOOLEAN NOT NULL DEFAULT false, + `beforeMessageId` VARCHAR(191) NULL, + + UNIQUE INDEX `ImportOldData_id_key`(`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- AddForeignKey +ALTER TABLE `GuildMember` ADD CONSTRAINT `GuildMember_guildId_fkey` FOREIGN KEY (`guildId`) REFERENCES `Guild`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `GuildMember` ADD CONSTRAINT `GuildMember_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `GuildMemberCredit` ADD CONSTRAINT `GuildMemberCredit_guildId_userId_fkey` FOREIGN KEY (`guildId`, `userId`) REFERENCES `GuildMember`(`guildId`, `userId`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `UserReputation` ADD CONSTRAINT `UserReputation_id_fkey` FOREIGN KEY (`id`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `GuildSettings` ADD CONSTRAINT `GuildSettings_id_fkey` FOREIGN KEY (`id`) REFERENCES `Guild`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `GuildSettings` ADD CONSTRAINT `GuildSettings_guildCreditsSettingsId_fkey` FOREIGN KEY (`guildCreditsSettingsId`) REFERENCES `GuildCreditsSettings`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `GuildCreditsSettings` ADD CONSTRAINT `GuildCreditsSettings_id_fkey` FOREIGN KEY (`id`) REFERENCES `Guild`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ApiCredentials` ADD CONSTRAINT `ApiCredentials_guildId_fkey` FOREIGN KEY (`guildId`) REFERENCES `Guild`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ApiCredentials` ADD CONSTRAINT `ApiCredentials_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `User`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ApiCredentials` ADD CONSTRAINT `ApiCredentials_guildId_userId_fkey` FOREIGN KEY (`guildId`, `userId`) REFERENCES `GuildMember`(`guildId`, `userId`) ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `Cooldown` ADD CONSTRAINT `Cooldown_guildId_fkey` FOREIGN KEY (`guildId`) REFERENCES `Guild`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `Cooldown` ADD CONSTRAINT `Cooldown_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `User`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `Cooldown` ADD CONSTRAINT `Cooldown_guildId_userId_fkey` FOREIGN KEY (`guildId`, `userId`) REFERENCES `GuildMember`(`guildId`, `userId`) ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20230524151822_axewr4et5r6ytu7yiuoi/migration.sql b/prisma/migrations/20230524151822_axewr4et5r6ytu7yiuoi/migration.sql new file mode 100644 index 0000000..484ef11 --- /dev/null +++ b/prisma/migrations/20230524151822_axewr4et5r6ytu7yiuoi/migration.sql @@ -0,0 +1,4 @@ +-- AlterTable +ALTER TABLE `GuildCreditsSettings` ADD COLUMN `dailyBonusAmount` INTEGER NOT NULL DEFAULT 25, + ADD COLUMN `monthlyBonusAmount` INTEGER NOT NULL DEFAULT 150, + ADD COLUMN `weeklyBonusAmount` INTEGER NOT NULL DEFAULT 50; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml index 9bee74d..e5a788a 100644 --- a/prisma/migrations/migration_lock.toml +++ b/prisma/migrations/migration_lock.toml @@ -1,3 +1,3 @@ # Please do not edit this file manually # It should be added in your version-control system (i.e. Git) -provider = "mysql" +provider = "mysql" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 7427a82..6165e35 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,9 +1,5 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - generator client { - provider = "prisma-client-js" - binaryTargets = ["native", "linux-musl"] + provider = "prisma-client-js" } datasource db { @@ -12,133 +8,136 @@ datasource db { } model Guild { - id String @unique - guildMembers GuildMember[] - cooldowns Cooldown[] - - // Settings - embedColorSuccess String @default("#22bb33") - embedColorWait String @default("#f0ad4e") - embedColorError String @default("#bb2124") - embedFooterText String @default("https://github.com/ZynerOrg/xyter") - embedFooterIcon String @default("https://github.com/ZynerOrg.png") - - // Modules - creditsEnabled Boolean @default(false) - creditsRate Int @default(1) - creditsTimeout Int @default(5) - creditsWorkRate Int @default(25) - creditsWorkTimeout Int @default(86400) - creditsMinimumLength Int @default(5) - - pointsEnabled Boolean @default(false) - pointsRate Int @default(1) - pointsTimeout Int @default(5) - pointsMinimumLength Int @default(5) - - reputationsEnabled Boolean @default(false) - - countersEnabled Boolean @default(false) - counters GuildCounter[] - - apiCpggUrlIv String? - apiCpggUrlContent String? - apiCpggTokenIv String? - apiCpggTokenContent String? - - auditsEnabled Boolean @default(false) - auditsChannelId String? - - shopRolesEnabled Boolean @default(false) - shopRolesPricePerHour Int @default(5) - - welcomeEnabled Boolean @default(false) - welcomeJoinChannelId String? - welcomeJoinChannelMessage String? - welcomeLeaveChannelId String? - welcomeLeaveChannelMessage String? - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - GuildShopRoles GuildShopRoles[] + id String @unique + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + guildMembers GuildMember[] + guildSettings GuildSettings? + guildCreditsSettings GuildCreditsSettings? + apiCredentials ApiCredentials[] + cooldowns Cooldown[] } model User { - id String @unique - GuildMember GuildMember[] - - // Settings - - // Modules - reputationsEarned Int @default(0) - Cooldown Cooldown[] - + id String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - GuildShopRoles GuildShopRoles[] + guildMembers GuildMember[] + apiCredentials ApiCredentials[] + cooldowns Cooldown[] + + userReputation UserReputation? } model GuildMember { - userId String - guildId String + guildId String + userId String + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) + guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + guildMemberCredit GuildMemberCredit? + apiCredentials ApiCredentials[] + cooldowns Cooldown[] - user User @relation(fields: [userId], references: [id]) - guild Guild @relation(fields: [guildId], references: [id]) - - // Settings - - // Modules - creditsEarned Int @default(0) - pointsEarned Int @default(0) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - GuildShopRoles GuildShopRoles[] - - // Unique Identifier - @@unique([userId, guildId]) + @@unique([guildId, userId]) } -model GuildCounter { - guildId String - channelId String - triggerWord String - count Int @default(0) - guild Guild @relation(fields: [guildId], references: [id]) +model GuildMemberCredit { + guildId String + userId String + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) + guildMember GuildMember @relation(fields: [guildId, userId], references: [guildId, userId], onDelete: Cascade) + balance Int @default(0) + + @@unique([guildId, userId]) +} + +model UserReputation { + id String @unique + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) + + user User @relation(fields: [id], references: [id], onDelete: Cascade) + + negative Int @default(0) + positive Int @default(0) +} + +model GuildSettings { + id String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - @@unique([guildId, channelId]) + guild Guild @relation(fields: [id], references: [id], onDelete: Cascade) + creditsSettings GuildCreditsSettings? @relation(fields: [guildCreditsSettingsId], references: [id], onDelete: Cascade) + guildCreditsSettingsId String? +} + +model GuildCreditsSettings { + id String @unique + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + guild Guild @relation(fields: [id], references: [id], onDelete: Cascade) + + // Work commands + workBonusChance Int @default(30) + workPenaltyChance Int @default(10) + + // Bonus commands + dailyBonusAmount Int @default(25) + weeklyBonusAmount Int @default(50) + monthlyBonusAmount Int @default(150) + + status Boolean @default(false) + rate Int @default(1) + timeout Int @default(5) + workRate Int @default(25) + workTimeout Int @default(86400) + minimumLength Int @default(5) + guildSettings GuildSettings[] +} + +model ApiCredentials { + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + guild Guild? @relation(fields: [guildId], references: [id], onDelete: Cascade) + guildId String? + + user User? @relation(fields: [userId], references: [id], onDelete: Cascade) + userId String? + + guildMember GuildMember? @relation(fields: [guildId, userId], references: [guildId, userId], onDelete: Cascade) + + apiName String + credentials Json + + @@unique([guildId, apiName]) + @@unique([userId, apiName]) } model Cooldown { - guild Guild @relation(fields: [guildId], references: [id]) - user User @relation(fields: [userId], references: [id]) - guildId String - userId String - cooldown Int - timeoutId String + id Int @id @default(autoincrement()) + cooldownItem String + expiresAt DateTime + guild Guild? @relation(fields: [guildId], references: [id], onDelete: Cascade) + guildId String? + user User? @relation(fields: [userId], references: [id], onDelete: Cascade) + userId String? + guildMember GuildMember? @relation(fields: [guildId, userId], references: [guildId, userId], onDelete: Cascade) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@unique([guildId, userId, timeoutId]) + @@index([cooldownItem, guildId], name: "cooldownItem_guildId_idx") + @@index([cooldownItem, userId], name: "cooldownItem_userId_idx") + @@index([cooldownItem, guildId, userId], name: "cooldownItem_guildId_userId_idx") } -model GuildShopRoles { - guildId String - roleId String - userId String - pricePerHour Int @default(5) - lastPayed DateTime - - guild Guild @relation(fields: [guildId], references: [id]) - user User @relation(fields: [userId], references: [id]) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - member GuildMember? @relation(fields: [userId, guildId], references: [userId, guildId]) - - @@unique([guildId, userId, roleId]) +model ImportOldData { + id String @unique + done Boolean @default(false) + beforeMessageId String? } diff --git a/src/buttons/primary/index.ts b/src/buttons/primary/index.ts index 6e95e0e..d5c17c8 100644 --- a/src/buttons/primary/index.ts +++ b/src/buttons/primary/index.ts @@ -1,5 +1,5 @@ import { ButtonInteraction } from "discord.js"; -import logger from "../../middlewares/logger"; +import logger from "../../utils/logger"; export const metadata = { guildOnly: false, ephemeral: false }; diff --git a/src/commands/config/index.ts b/src/commands/config/index.ts deleted file mode 100644 index 815aa7c..0000000 --- a/src/commands/config/index.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; - -// Modules -import moduleAudits from "./modules/audits"; -import moduleCpgg from "./modules/cpgg"; -import moduleCredits from "./modules/credits"; -import moduleEmbeds from "./modules/embeds"; -import modulePoints from "./modules/points"; -import moduleShop from "./modules/shop"; -import moduleWelcome from "./modules/welcome"; - -export const builder = new SlashCommandBuilder() - .setName("config") - .setDescription("Manage guild configurations.") - .setDMPermission(false) - - // Modules - .addSubcommand(moduleAudits.builder) - .addSubcommand(moduleCpgg.builder) - .addSubcommand(moduleCredits.builder) - .addSubcommand(moduleEmbeds.builder) - .addSubcommand(modulePoints.builder) - .addSubcommand(moduleShop.builder) - .addSubcommand(moduleWelcome.builder); - -// Execute function -export const execute = async (interaction: ChatInputCommandInteraction) => { - switch (interaction.options.getSubcommand()) { - case "audits": - await moduleAudits.execute(interaction); - break; - case "cpgg": - await moduleCpgg.execute(interaction); - break; - case "credits": - await moduleCredits.execute(interaction); - break; - case "embeds": - await moduleEmbeds.execute(interaction); - break; - case "points": - await modulePoints.execute(interaction); - break; - case "shop": - await moduleShop.execute(interaction); - break; - case "welcome": - await moduleWelcome.execute(interaction); - break; - default: - throw new Error("No module found for that specific command."); - } -}; diff --git a/src/commands/config/modules/audits/index.ts b/src/commands/config/modules/audits/index.ts deleted file mode 100644 index ef8d46c..0000000 --- a/src/commands/config/modules/audits/index.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { - ChannelType, - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import checkPermission from "../../../../helpers/checkPermission"; -import getEmbedConfig from "../../../../helpers/getEmbedData"; -import logger from "../../../../middlewares/logger"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("audits") - .setDescription("Audits") - .addBooleanOption((option) => - option - .setName("status") - .setDescription("Should audits be enabled?") - .setRequired(true) - ) - .addChannelOption((option) => - option - .setName("channel") - .setDescription("Channel for audit messages.") - .addChannelTypes(ChannelType.GuildText) - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - const { guild, options } = interaction; - const { successColor, footerText, footerIcon } = await getEmbedConfig( - guild - ); - const status = options.getBoolean("status"); - const channel = options.getChannel("channel"); - - if (!guild) throw new Error("Guild not found."); - if (!channel) throw new Error("Channel not found."); - if (status === null) throw new Error("Status not found."); - - const createGuild = await prisma.guild.upsert({ - where: { - id: guild.id, - }, - update: { - auditsEnabled: status, - auditsChannelId: channel.id, - }, - create: { - id: guild.id, - auditsEnabled: status, - auditsChannelId: channel.id, - }, - }); - - logger.silly(createGuild); - - const embedSuccess = new EmbedBuilder() - .setTitle("[:hammer:] Audits") - .setDescription("Guild configuration updated successfully.") - .setColor(successColor) - .addFields( - { - name: "🤖 Status", - value: `${ - createGuild.auditsEnabled - ? ":white_check_mark: Enabled" - : ":x: Disabled" - }`, - inline: true, - }, - { - name: "🌊 Channel", - value: `<#${createGuild.auditsChannelId}>`, - inline: true, - } - ) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - - await interaction.editReply({ - embeds: [embedSuccess], - }); - return; - }, -}; diff --git a/src/commands/config/modules/cpgg/index.ts b/src/commands/config/modules/cpgg/index.ts deleted file mode 100644 index 616b9bc..0000000 --- a/src/commands/config/modules/cpgg/index.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import checkPermission from "../../../../helpers/checkPermission"; -import encryption from "../../../../helpers/encryption"; -import getEmbedConfig from "../../../../helpers/getEmbedData"; -import logger from "../../../../middlewares/logger"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("cpgg") - .setDescription("Controlpanel.gg") - .addStringOption((option) => - option - .setName("scheme") - .setDescription(`Controlpanel.gg Scheme`) - .setRequired(true) - .setChoices( - { name: "HTTPS (secure)", value: "https" }, - { name: "HTTP (insecure)", value: "http" } - ) - ) - .addStringOption((option) => - option - .setName("domain") - .setDescription(`Controlpanel.gg Domain`) - .setRequired(true) - ) - .addStringOption((option) => - option - .setName("token") - .setDescription(`Controlpanel.gg Application API`) - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); - const { options, guild } = interaction; - - const tokenData = options.getString("token"); - const scheme = options.getString("scheme"); - const domain = options.getString("domain"); - const token = tokenData && encryption.encrypt(tokenData); - const url = scheme && domain && encryption.encrypt(`${scheme}://${domain}`); - - if (!guild) throw new Error("No guild found"); - if (!token) throw new Error("Token not found"); - if (!url) throw new Error("URL not found"); - - const createGuild = await prisma.guild.upsert({ - where: { - id: guild.id, - }, - update: { - apiCpggTokenIv: token.iv, - apiCpggTokenContent: token.content, - apiCpggUrlIv: url.iv, - apiCpggUrlContent: url.content, - }, - create: { - id: guild.id, - apiCpggTokenIv: token.iv, - apiCpggTokenContent: token.content, - apiCpggUrlIv: url.iv, - apiCpggUrlContent: url.content, - }, - }); - - logger.silly(createGuild); - - logger?.silly(`Updated API credentials.`); - - const interactionEmbed = new EmbedBuilder() - .setTitle("[:tools:] CPGG") - .setDescription( - `The following configuration will be used. - -**Scheme**: ${scheme} -**Domain**: ${domain} -**Token**: ends with ${tokenData?.slice(-4)}` - ) - .setColor(successColor) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - - await interaction?.editReply({ - embeds: [interactionEmbed], - }); - return; - }, -}; diff --git a/src/commands/config/modules/credits/index.ts b/src/commands/config/modules/credits/index.ts deleted file mode 100644 index 9d9360c..0000000 --- a/src/commands/config/modules/credits/index.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import checkPermission from "../../../../helpers/checkPermission"; -import getEmbedConfig from "../../../../helpers/getEmbedData"; -import logger from "../../../../middlewares/logger"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("credits") - .setDescription(`Configure this guild's credits module.`) - .addBooleanOption((option) => - option - .setName("enabled") - .setDescription("Do you want to activate the credit module?") - .setRequired(true) - ) - .addNumberOption((option) => - option - .setName("rate") - .setDescription("Credit rate per message.") - .setRequired(true) - .setMinValue(1) - ) - .addNumberOption((option) => - option - .setName("minimum-length") - .setDescription("Minimum message length to receive credit.") - .setRequired(true) - ) - .addNumberOption((option) => - option - .setName("work-rate") - .setDescription( - "The maximum amount of credit that can be obtained within a working day." - ) - .setRequired(true) - .setMinValue(1) - ) - .addNumberOption((option) => - option - .setName("work-timeout") - .setDescription( - "How long you need to wait before you can work again provided in seconds." - ) - .setRequired(true) - ) - .addNumberOption((option) => - option - .setName("timeout") - .setDescription( - "How long you need to wait before you can earn more credits." - ) - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); - const { guild, options } = interaction; - - const enabled = options.getBoolean("enabled"); - const rate = options.getNumber("rate"); - const timeout = options.getNumber("timeout"); - const minimumLength = options.getNumber("minimum-length"); - const workRate = options.getNumber("work-rate"); - const workTimeout = options.getNumber("work-timeout"); - - if (!guild) throw new Error("Guild not found."); - if (typeof enabled !== "boolean") - throw new Error("Enabled option is not a boolean."); - if (typeof rate !== "number") throw new Error("Rate is not a number."); - if (typeof workRate !== "number") - throw new Error("Work rate is not a number."); - if (typeof workTimeout !== "number") - throw new Error("Work timeout is not a number."); - if (typeof timeout !== "number") - throw new Error("Timeout is not a number."); - if (typeof minimumLength !== "number") - throw new Error("Minimum length is not a number."); - - const createGuild = await prisma.guild.upsert({ - where: { - id: guild.id, - }, - update: { - creditsEnabled: enabled, - creditsRate: rate, - creditsTimeout: timeout, - creditsWorkRate: workRate, - creditsWorkTimeout: workTimeout, - creditsMinimumLength: minimumLength, - }, - create: { - id: guild.id, - creditsEnabled: enabled, - creditsRate: rate, - creditsTimeout: timeout, - creditsWorkRate: workRate, - creditsWorkTimeout: workTimeout, - creditsMinimumLength: minimumLength, - }, - }); - - logger.silly(createGuild); - - const interactionEmbed = new EmbedBuilder() - .setTitle("[:tools:] Credits") - .setDescription("Credits settings updated") - .setColor(successColor) - .addFields( - { - name: "🤖 Enabled?", - value: `${createGuild.creditsEnabled}`, - inline: true, - }, - { - name: "📈 Rate", - value: `${createGuild.creditsRate}`, - inline: true, - }, - { - name: "📈 Work Rate", - value: `${createGuild.creditsWorkRate}`, - inline: true, - }, - { - name: "🔨 Minimum Length", - value: `${createGuild.creditsMinimumLength}`, - inline: true, - }, - { - name: "⏰ Timeout", - value: `${createGuild.creditsTimeout}`, - inline: true, - }, - { - name: "⏰ Work Timeout", - value: `${createGuild.creditsWorkTimeout}`, - inline: true, - } - ) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - - await interaction.editReply({ - embeds: [interactionEmbed], - }); - return; - }, -}; diff --git a/src/commands/config/modules/embeds/components/getValues/index.ts b/src/commands/config/modules/embeds/components/getValues/index.ts deleted file mode 100644 index ae35157..0000000 --- a/src/commands/config/modules/embeds/components/getValues/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { ChatInputCommandInteraction, ColorResolvable } from "discord.js"; -import prisma from "../../../../../../handlers/database"; -import getEmbedConfig from "../../../../../../helpers/getEmbedData"; -import logger from "../../../../../../middlewares/logger"; - -export default async (interaction: ChatInputCommandInteraction) => { - const { options, guild } = interaction; - - if (!guild) throw new Error("Guild not found"); - - const embedConfig = await getEmbedConfig(guild); - if (!embedConfig) throw new Error("Embed config not found"); - - const newSuccessColor = options.getString("success-color"); - const newWaitColor = options.getString("wait-color"); - const newErrorColor = options.getString("error-color"); - const newFooterIcon = options.getString("footer-icon"); - const newFooterText = options.getString("footer-text"); - - if (!newSuccessColor) throw new Error("Success color not found"); - if (!newWaitColor) throw new Error("Wait color not found"); - if (!newErrorColor) throw new Error("Error color not found"); - if (!newFooterIcon) throw new Error("Footer icon not found"); - if (!newFooterText) throw new Error("Footer text not found"); - - const createGuild = await prisma.guild.upsert({ - where: { - id: guild.id, - }, - update: { - embedColorSuccess: newSuccessColor, - embedColorWait: newWaitColor, - embedColorError: newErrorColor, - embedFooterIcon: newFooterIcon, - embedFooterText: newFooterText, - }, - create: { - id: guild.id, - embedColorSuccess: newSuccessColor, - embedColorWait: newWaitColor, - embedColorError: newErrorColor, - embedFooterIcon: newFooterIcon, - embedFooterText: newFooterText, - }, - }); - - logger.silly(createGuild); - - const successColor = createGuild.embedColorSuccess; - const waitColor = createGuild.embedColorWait; - const errorColor = createGuild.embedColorError; - const footerText = createGuild.embedFooterText; - const footerIcon = createGuild.embedFooterIcon; - - return { successColor, waitColor, errorColor, footerText, footerIcon }; -}; diff --git a/src/commands/config/modules/embeds/index.ts b/src/commands/config/modules/embeds/index.ts deleted file mode 100644 index acff478..0000000 --- a/src/commands/config/modules/embeds/index.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; - -import deferReply from "../../../../handlers/deferReply"; -import checkPermission from "../../../../helpers/checkPermission"; -import getValues from "./components/getValues"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("embeds") - .setDescription(`Embeds`) - .addStringOption((option) => - option - .setName("success-color") - .setDescription("No provided description") - .setRequired(true) - ) - .addStringOption((option) => - option - .setName("wait-color") - .setDescription("No provided description") - .setRequired(true) - ) - .addStringOption((option) => - option - .setName("error-color") - .setDescription("No provided description") - .setRequired(true) - ) - .addStringOption((option) => - option - .setName("footer-icon") - .setDescription("No provided description") - .setRequired(true) - ) - .addStringOption((option) => - option - .setName("footer-text") - .setDescription("No provided description") - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - const { guild } = interaction; - if (!guild) throw new Error("Guild not found"); - - const { successColor, waitColor, errorColor, footerText, footerIcon } = - await getValues(interaction); - - const embed = new EmbedBuilder() - .setTitle("[:tools:] Embeds") - .setFooter({ text: footerText, iconURL: footerIcon }) - .setTimestamp(new Date()); - - embed - .setDescription("Following embed configuration will be used.") - .setColor(successColor) - .addFields([ - { - name: "🟢 Success Color", - value: `${successColor}`, - inline: true, - }, - { - name: "🟡 Wait Color", - value: `${waitColor}`, - inline: true, - }, - { - name: "🔴 Error Color", - value: `${errorColor}`, - inline: true, - }, - { - name: "🖼️ Footer Icon", - value: `${footerIcon}`, - inline: true, - }, - { - name: "📄 Footer Text", - value: `${footerText}`, - inline: true, - }, - ]); - - await interaction.editReply({ - embeds: [embed], - }); - return; - }, -}; diff --git a/src/commands/config/modules/points/index.ts b/src/commands/config/modules/points/index.ts deleted file mode 100644 index 4a411f7..0000000 --- a/src/commands/config/modules/points/index.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import checkPermission from "../../../../helpers/checkPermission"; -import getEmbedConfig from "../../../../helpers/getEmbedData"; -import logger from "../../../../middlewares/logger"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("points") - .setDescription("Points") - .addBooleanOption((option) => - option - .setName("status") - .setDescription("Should credits be enabled?") - .setRequired(true) - ) - .addNumberOption((option) => - option - .setName("rate") - .setDescription("Amount of credits per message.") - .setRequired(true) - ) - .addNumberOption((option) => - option - .setName("minimum-length") - .setDescription("Minimum length of message to earn credits.") - .setRequired(true) - ) - .addNumberOption((option) => - option - .setName("timeout") - .setDescription("Timeout between earning credits (milliseconds).") - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); - - const { options, guild } = interaction; - - const status = options?.getBoolean("status"); - const rate = options?.getNumber("rate"); - const timeout = options?.getNumber("timeout"); - const minimumLength = options?.getNumber("minimum-length"); - - if (!guild) throw new Error("Guild is required"); - if (status === null) throw new Error("Status must be specified"); - if (!rate) throw new Error("Rate must be specified"); - if (!timeout) throw new Error("Timeout must be specified"); - if (!minimumLength) throw new Error("Minimum length must be specified"); - - const createGuild = await prisma.guild.upsert({ - where: { - id: guild.id, - }, - update: { - pointsEnabled: status, - pointsRate: rate, - pointsTimeout: timeout, - pointsMinimumLength: minimumLength, - }, - create: { - id: guild.id, - pointsEnabled: status, - pointsRate: rate, - pointsTimeout: timeout, - pointsMinimumLength: minimumLength, - }, - }); - - logger.silly(createGuild); - - const interactionEmbed = new EmbedBuilder() - .setTitle("[:tools:] Points") - .setDescription("Points settings updated") - .setColor(successColor) - .addFields( - { - name: "🤖 Status", - value: `${createGuild.pointsEnabled}`, - inline: true, - }, - { - name: "📈 Rate", - value: `${createGuild.pointsRate}`, - inline: true, - }, - { - name: "🔨 Minimum Length", - value: `${createGuild.pointsMinimumLength}`, - inline: true, - }, - { - name: "⏰ Timeout", - value: `${createGuild.pointsTimeout}`, - inline: true, - } - ) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - - await interaction?.editReply({ - embeds: [interactionEmbed], - }); - return; - }, -}; diff --git a/src/commands/config/modules/shop/index.ts b/src/commands/config/modules/shop/index.ts deleted file mode 100644 index 21c1b27..0000000 --- a/src/commands/config/modules/shop/index.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import checkPermission from "../../../../helpers/checkPermission"; -import getEmbedConfig from "../../../../helpers/getEmbedData"; -import logger from "../../../../middlewares/logger"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("shop") - .setDescription("Shop") - .addBooleanOption((option) => - option - .setName("roles-status") - .setDescription("Should roles be enabled?") - .setRequired(true) - ) - .addNumberOption((option) => - option - .setName("roles-price-per-hour") - .setDescription("Price per hour for roles.") - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); - const { options, guild } = interaction; - - const rolesStatus = options?.getBoolean("roles-status"); - const rolesPricePerHour = options?.getNumber("roles-price-per-hour"); - - if (!guild) throw new Error("Guild not found"); - if (rolesStatus === null) throw new Error("Status must be provided"); - if (!rolesPricePerHour) - throw new Error("Roles price per hour must be provided"); - - const createGuild = await prisma.guild.upsert({ - where: { - id: guild.id, - }, - update: { - shopRolesEnabled: rolesStatus, - shopRolesPricePerHour: rolesPricePerHour, - }, - create: { - id: guild.id, - shopRolesEnabled: rolesStatus, - shopRolesPricePerHour: rolesPricePerHour, - }, - }); - - logger.silly(createGuild); - - const interactionEmbed = new EmbedBuilder() - .setTitle("[:tools:] Shop") - .setDescription("Shop settings updated") - .setColor(successColor) - .addFields( - { - name: "🤖 Roles Status", - value: `${createGuild.shopRolesEnabled}`, - inline: true, - }, - { - name: "🌊 Roles Price Per Hour", - value: `${createGuild.shopRolesPricePerHour}`, - inline: true, - } - ) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - - await interaction?.editReply({ - embeds: [interactionEmbed], - }); - return; - }, -}; diff --git a/src/commands/config/modules/welcome/index.ts b/src/commands/config/modules/welcome/index.ts deleted file mode 100644 index 73efefe..0000000 --- a/src/commands/config/modules/welcome/index.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { - ChannelType, - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import checkPermission from "../../../../helpers/checkPermission"; -import getEmbedConfig from "../../../../helpers/getEmbedData"; -import logger from "../../../../middlewares/logger"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("welcome") - .setDescription("Welcome") - .addBooleanOption((option) => - option - .setName("status") - .setDescription("Should welcome be enabled?") - .setRequired(true) - ) - .addChannelOption((option) => - option - .setName("join-channel") - .setDescription("Channel for join messages.") - .addChannelTypes(ChannelType.GuildText) - .setRequired(true) - ) - - .addChannelOption((option) => - option - .setName("leave-channel") - .setDescription("Channel for leave messages.") - .addChannelTypes(ChannelType.GuildText) - .setRequired(true) - ) - - .addStringOption((option) => - option - .setName("leave-message") - .setDescription("Message for leave messages.") - .setRequired(true) - ) - .addStringOption((option) => - option - .setName("join-message") - .setDescription("Message for join messages.") - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); - const { options, guild } = interaction; - - const status = options?.getBoolean("status"); - const joinChannel = options?.getChannel("join-channel"); - const leaveChannel = options?.getChannel("leave-channel"); - const joinChannelMessage = options?.getString("join-message"); - const leaveChannelMessage = options?.getString("leave-message"); - - if (!guild) throw new Error("Guild not found"); - if (status === null) throw new Error("Status not specified"); - if (!joinChannel) throw new Error("Join channel not specified"); - if (!joinChannelMessage) - throw new Error("Join channel message not specified"); - if (!leaveChannel) throw new Error("Leave channel not specified"); - if (!leaveChannelMessage) - throw new Error("Leave channel message not specified"); - - const createGuild = await prisma.guild.upsert({ - where: { - id: guild.id, - }, - update: { - welcomeEnabled: status, - welcomeJoinChannelId: joinChannel.id, - welcomeJoinChannelMessage: joinChannelMessage, - welcomeLeaveChannelId: leaveChannel.id, - welcomeLeaveChannelMessage: leaveChannelMessage, - }, - create: { - id: guild.id, - welcomeEnabled: status, - welcomeJoinChannelId: joinChannel.id, - welcomeJoinChannelMessage: joinChannelMessage, - welcomeLeaveChannelId: leaveChannel.id, - welcomeLeaveChannelMessage: leaveChannelMessage, - }, - }); - - logger.silly(createGuild); - - const interactionEmbedDisabled = new EmbedBuilder() - .setTitle("[:tools:] Welcome") - .setDescription( - "This module is currently disabled, please enable it to continue." - ) - .setColor(successColor) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - - if (!createGuild.welcomeEnabled) { - return interaction?.editReply({ - embeds: [interactionEmbedDisabled], - }); - } - - const interactionEmbed = new EmbedBuilder() - .setTitle("[:tools:] Welcome") - .setDescription( - `The following configuration will be used. - - [👋] **Welcome** - - ㅤ**Channel**: <#${createGuild.welcomeJoinChannelId}> - ㅤ**Message**: ${createGuild.welcomeJoinChannelMessage} - - [🚪] **Leave** - - ㅤ**Channel**: <#${createGuild.welcomeLeaveChannelId}> - ㅤ**Message**: ${createGuild.welcomeLeaveChannelMessage}` - ) - .setColor(successColor) - .setTimestamp() - .setFooter({ - iconURL: footerIcon, - text: footerText, - }); - - await interaction?.editReply({ - embeds: [interactionEmbed], - }); - return true; - }, -}; diff --git a/src/commands/counters/index.ts b/src/commands/counters/index.ts deleted file mode 100644 index bcb2991..0000000 --- a/src/commands/counters/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; - -// Modules -import { builder as ViewBuilder, execute as ViewExecute } from "./modules/view"; - -// -export const builder = new SlashCommandBuilder() - .setName("counters") - .setDescription("View guild counters") - .setDMPermission(false) - - // Modules - .addSubcommand(ViewBuilder); - -// Execute function -export const execute = async (interaction: ChatInputCommandInteraction) => { - switch (interaction.options.getSubcommand()) { - case "view": - await ViewExecute(interaction); - break; - default: - throw new Error("No module found for that command."); - } -}; diff --git a/src/commands/counters/modules/view/index.ts b/src/commands/counters/modules/view/index.ts deleted file mode 100644 index f62ccfb..0000000 --- a/src/commands/counters/modules/view/index.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { - ChannelType, - ChatInputCommandInteraction, - SlashCommandSubcommandBuilder, -} from "discord.js"; - -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import { success as BaseEmbedSuccess } from "../../../../helpers/baseEmbeds"; - -// 1. Create builder function. -export const builder = (command: SlashCommandSubcommandBuilder) => { - return command - .setName("view") - .setDescription(`View a guild counter`) - .addChannelOption((option) => - option - .setName("channel") - .setDescription( - `The channel that contains the counter you want to view` - ) - .setRequired(true) - .addChannelTypes(ChannelType.GuildText) - ); -}; - -// 2. Create execute function. -export const execute = async (interaction: ChatInputCommandInteraction) => { - // 1. Defer reply as permanent. - await deferReply(interaction, false); - - // 2. Destructure interaction object - const { options, guild } = interaction; - if (!guild) throw new Error(`Guild not found`); - if (!options) throw new Error(`Options not found`); - - // 3. Get options - const discordChannel = options.getChannel("channel"); - if (!discordChannel) throw new Error(`Channel not found`); - - // 4. Create base embeds. - const EmbedSuccess = await BaseEmbedSuccess(guild, "[:1234:] View"); - - // 5. Get counter from database. - const channelCounter = await prisma.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: discordChannel.id, - }, - }, - }); - if (!channelCounter) throw new Error("No counter found for channel"); - - // 6. Send embed. - await interaction.editReply({ - embeds: [ - EmbedSuccess.setDescription( - `Viewing counter for channel ${discordChannel}: ${channelCounter.count}!` - ), - ], - }); -}; diff --git a/src/commands/credits/groups/bonus/index.ts b/src/commands/credits/groups/bonus/index.ts new file mode 100644 index 0000000..3be82fd --- /dev/null +++ b/src/commands/credits/groups/bonus/index.ts @@ -0,0 +1,19 @@ +import { SlashCommandSubcommandGroupBuilder } from "discord.js"; +import * as daily from "./subcommands/daily"; +import * as monthly from "./subcommands/monthly"; +import * as weekly from "./subcommands/weekly"; + +export const builder = (group: SlashCommandSubcommandGroupBuilder) => { + return group + .setName("bonus") + .setDescription("Get bonuses") + .addSubcommand(daily.builder) + .addSubcommand(weekly.builder) + .addSubcommand(monthly.builder); +}; + +export const subcommands = { + daily, + weekly, + monthly, +}; diff --git a/src/commands/credits/groups/bonus/subcommands/daily/index.ts b/src/commands/credits/groups/bonus/subcommands/daily/index.ts new file mode 100644 index 0000000..4ba70e1 --- /dev/null +++ b/src/commands/credits/groups/bonus/subcommands/daily/index.ts @@ -0,0 +1,71 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import CooldownManager from "../../../../../../handlers/CooldownManager"; +import CreditsManager from "../../../../../../handlers/CreditsManager"; +import prisma from "../../../../../../handlers/prisma"; +import generateCooldownName from "../../../../../../helpers/generateCooldownName"; +import deferReply from "../../../../../../utils/deferReply"; +import sendResponse from "../../../../../../utils/sendResponse"; + +const cooldownManager = new CooldownManager(); +const creditsManager = new CreditsManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command.setName("daily").setDescription("Claim your daily treasure!"); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + const { guild, user } = interaction; + + await deferReply(interaction, false); + + if (!guild) { + throw new Error( + "Oops! It looks like you're not part of a guild. Join a guild to embark on this adventure!" + ); + } + + if (!user) { + throw new Error( + "Oops! We couldn't find your user information. Please try again or contact support for assistance." + ); + } + + const guildCreditsSettings = await prisma.guildCreditsSettings.upsert({ + where: { id: guild.id }, + update: {}, + create: { id: guild.id }, + }); + + const dailyBonusAmount = guildCreditsSettings.dailyBonusAmount; + const userEconomy = await creditsManager.give(guild, user, dailyBonusAmount); + + const embed = new EmbedBuilder() + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setAuthor({ + name: "🌟 Daily Treasure Claimed", + }) + .setThumbnail(user.displayAvatarURL()) + .setDescription( + `You've just claimed your daily treasure of **${dailyBonusAmount} credits**! 🎉\nEmbark on an epic adventure and spend your riches wisely.\n\n💰 **Your balance**: ${userEconomy.balance} credits` + ) + .setFooter({ + text: `Claimed by ${user.username}`, + iconURL: user.displayAvatarURL() || "", + }) + .setTimestamp(); + + await sendResponse(interaction, { embeds: [embed] }); + + const cooldownDuration = 24 * 60 * 60; // 24 hours in seconds + const cooldownName = await generateCooldownName(interaction); + await cooldownManager.setCooldown( + cooldownName, + guild, + user, + cooldownDuration + ); +}; diff --git a/src/commands/credits/groups/bonus/subcommands/monthly/index.ts b/src/commands/credits/groups/bonus/subcommands/monthly/index.ts new file mode 100644 index 0000000..cc88303 --- /dev/null +++ b/src/commands/credits/groups/bonus/subcommands/monthly/index.ts @@ -0,0 +1,77 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import CooldownManager from "../../../../../../handlers/CooldownManager"; +import CreditsManager from "../../../../../../handlers/CreditsManager"; +import prisma from "../../../../../../handlers/prisma"; +import generateCooldownName from "../../../../../../helpers/generateCooldownName"; +import deferReply from "../../../../../../utils/deferReply"; +import sendResponse from "../../../../../../utils/sendResponse"; + +const cooldownManager = new CooldownManager(); +const creditsManager = new CreditsManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("monthly") + .setDescription("Claim your monthly treasure!"); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + const { guild, user } = interaction; + + await deferReply(interaction, false); + + if (!guild) { + throw new Error( + "Oops! It looks like you're not part of a guild. Join a guild to embark on this adventure!" + ); + } + + if (!user) { + throw new Error( + "Oops! We couldn't find your user information. Please try again or contact support for assistance." + ); + } + + const guildCreditsSettings = await prisma.guildCreditsSettings.upsert({ + where: { id: guild.id }, + update: {}, + create: { id: guild.id }, + }); + + const monthlyBonusAmount = guildCreditsSettings.monthlyBonusAmount; + const userEconomy = await creditsManager.give( + guild, + user, + monthlyBonusAmount + ); + + const embed = new EmbedBuilder() + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setAuthor({ + name: "🌟 Monthly Treasure Claimed", + }) + .setThumbnail(user.displayAvatarURL()) + .setDescription( + `You've just claimed your monthly treasure of **${monthlyBonusAmount} credits**! 🎉\nEmbark on an epic adventure and spend your riches wisely.\n\n💰 **Your balance**: ${userEconomy.balance} credits` + ) + .setFooter({ + text: `Claimed by ${user.username}`, + iconURL: user.displayAvatarURL() || "", + }) + .setTimestamp(); + + await sendResponse(interaction, { embeds: [embed] }); + + const cooldownDuration = 24 * 60 * 60; // 24 hours in seconds + const cooldownName = await generateCooldownName(interaction); + await cooldownManager.setCooldown( + cooldownName, + guild, + user, + cooldownDuration + ); +}; diff --git a/src/commands/credits/groups/bonus/subcommands/weekly/index.ts b/src/commands/credits/groups/bonus/subcommands/weekly/index.ts new file mode 100644 index 0000000..15c7dd2 --- /dev/null +++ b/src/commands/credits/groups/bonus/subcommands/weekly/index.ts @@ -0,0 +1,73 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import CooldownManager from "../../../../../../handlers/CooldownManager"; +import CreditsManager from "../../../../../../handlers/CreditsManager"; +import prisma from "../../../../../../handlers/prisma"; +import generateCooldownName from "../../../../../../helpers/generateCooldownName"; +import deferReply from "../../../../../../utils/deferReply"; +import sendResponse from "../../../../../../utils/sendResponse"; + +const cooldownManager = new CooldownManager(); +const creditsManager = new CreditsManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("weekly") + .setDescription("Claim your weekly treasure!"); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + const { guild, user } = interaction; + + await deferReply(interaction, false); + + if (!guild) { + throw new Error( + "Oops! It looks like you're not part of a guild. Join a guild to embark on this adventure!" + ); + } + + if (!user) { + throw new Error( + "Oops! We couldn't find your user information. Please try again or contact support for assistance." + ); + } + + const guildCreditsSettings = await prisma.guildCreditsSettings.upsert({ + where: { id: guild.id }, + update: {}, + create: { id: guild.id }, + }); + + const weeklyBonusAmount = guildCreditsSettings.weeklyBonusAmount; + const userEconomy = await creditsManager.give(guild, user, weeklyBonusAmount); + + const embed = new EmbedBuilder() + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setAuthor({ + name: "🌟 Weekly Treasure Claimed", + }) + .setThumbnail(user.displayAvatarURL()) + .setDescription( + `You've just claimed your weekly treasure of **${weeklyBonusAmount} credits**! 🎉\nEmbark on an epic adventure and spend your riches wisely.\n\n💰 **Your balance**: ${userEconomy.balance} credits` + ) + .setFooter({ + text: `Claimed by ${user.username}`, + iconURL: user.displayAvatarURL() || "", + }) + .setTimestamp(); + + await sendResponse(interaction, { embeds: [embed] }); + + const cooldownDuration = 24 * 60 * 60; // 24 hours in seconds + const cooldownName = await generateCooldownName(interaction); + await cooldownManager.setCooldown( + cooldownName, + guild, + user, + cooldownDuration + ); +}; diff --git a/src/commands/credits/index.ts b/src/commands/credits/index.ts index 1a103ba..f79d6be 100644 --- a/src/commands/credits/index.ts +++ b/src/commands/credits/index.ts @@ -1,42 +1,45 @@ import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; - -// Modules import { - builder as BalanceBuilder, - execute as BalanceExecute, -} from "./modules/balance"; -import { builder as GiftBuilder, execute as GiftExecute } from "./modules/gift"; -import { builder as TopBuilder, execute as TopExecute } from "./modules/top"; -import { builder as WorkBuilder, execute as WorkExecute } from "./modules/work"; + SubcommandGroupHandlers, + SubcommandHandlers, + executeSubcommand, +} from "../../handlers/executeSubcommand"; +import * as balance from "./subcommands/balance"; +import * as gift from "./subcommands/gift"; +import * as top from "./subcommands/top"; +import * as work from "./subcommands/work"; + +import * as bonus from "./groups/bonus"; + +const subcommandHandlers: SubcommandHandlers = { + balance: balance.execute, + gift: gift.execute, + top: top.execute, + work: work.execute, +}; + +const subcommandGroupHandlers: SubcommandGroupHandlers = { + bonus: { + daily: bonus.subcommands.daily.execute, + weekly: bonus.subcommands.weekly.execute, + monthly: bonus.subcommands.monthly.execute, + }, +}; -// 1. Export a builder function. export const builder = new SlashCommandBuilder() .setName("credits") .setDescription("Manage your credits.") .setDMPermission(false) + .addSubcommandGroup(bonus.builder) + .addSubcommand(balance.builder) + .addSubcommand(gift.builder) + .addSubcommand(top.builder) + .addSubcommand(work.builder); - // Modules - .addSubcommand(BalanceBuilder) - .addSubcommand(GiftBuilder) - .addSubcommand(TopBuilder) - .addSubcommand(WorkBuilder); - -// 2. Export an execute function. export const execute = async (interaction: ChatInputCommandInteraction) => { - switch (interaction.options.getSubcommand()) { - case "balance": - await BalanceExecute(interaction); - break; - case "gift": - await GiftExecute(interaction); - break; - case "top": - await TopExecute(interaction); - break; - case "work": - await WorkExecute(interaction); - break; - default: - throw new Error("Subcommand not found"); - } + await executeSubcommand( + interaction, + subcommandHandlers, + subcommandGroupHandlers + ); }; diff --git a/src/commands/credits/modules/balance/index.ts b/src/commands/credits/modules/balance/index.ts deleted file mode 100644 index 60c17c6..0000000 --- a/src/commands/credits/modules/balance/index.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { CommandInteraction, SlashCommandSubcommandBuilder } from "discord.js"; - -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import { success as BaseEmbedSuccess } from "../../../../helpers/baseEmbeds"; -import logger from "../../../../middlewares/logger"; - -// 1. Export a builder function. -export const builder = (command: SlashCommandSubcommandBuilder) => { - return command - .setName("balance") - .setDescription(`Check balance`) - .addUserOption((option) => - option.setName("target").setDescription(`Account you want to check`) - ); -}; - -// 2. Export an execute function. -export const execute = async (interaction: CommandInteraction) => { - // 1. Defer reply as ephemeral. - await deferReply(interaction, true); - - // 2. Destructure interaction object. - const { options, user, guild } = interaction; - if (!guild) throw new Error("Server unavailable"); - if (!user) throw new Error("User unavailable"); - if (!options) throw new Error("Options unavailable"); - - // 3. Get options from interaction. - const target = options.getUser("target"); - - // 4. Create base embeds. - const EmbedSuccess = await BaseEmbedSuccess(guild, ":credit_card:︱Balance"); - - // 5. Upsert the user in the database. - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: (target || user).id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: (target || user).id, - }, - where: { - id: (target || user).id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger.silly(createGuildMember); - - // 6. Send embed. - await interaction.editReply({ - embeds: [ - EmbedSuccess.setDescription( - target - ? `${target} has ${createGuildMember.creditsEarned} coins in his account.` - : `You have ${createGuildMember.creditsEarned} coins in your account.` - ), - ], - }); -}; diff --git a/src/commands/credits/modules/gift/index.ts b/src/commands/credits/modules/gift/index.ts deleted file mode 100644 index e21d9c9..0000000 --- a/src/commands/credits/modules/gift/index.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { - ChatInputCommandInteraction, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import prisma from "../../../../handlers/database"; - -import deferReply from "../../../../handlers/deferReply"; -import { success as BaseEmbedSuccess } from "../../../../helpers/baseEmbeds"; -import creditsTransfer from "../../../../helpers/credits/transfer"; -import logger from "../../../../middlewares/logger"; - -// 1. Export a builder function. -export const builder = (command: SlashCommandSubcommandBuilder) => { - return command - .setName("gift") - .setDescription(`Gift credits to an account`) - .addUserOption((option) => - option - .setName("account") - .setDescription("The account you gift to") - .setRequired(true) - ) - .addIntegerOption((option) => - option - .setName("credits") - .setDescription("How much you gift") - .setRequired(true) - .setMinValue(1) - .setMaxValue(100000000) - ) - .addStringOption((option) => - option - .setName("message") - .setDescription("Your personalized message to the account") - ); -}; - -// 2. Export an execute function. -export const execute = async (interaction: ChatInputCommandInteraction) => { - // 1. Defer reply as ephemeral. - await deferReply(interaction, true); - - // 2. Destructure interaction object. - const { options, user, guild } = interaction; - if (!guild) throw new Error("Server unavailable"); - if (!user) throw new Error("User unavailable"); - - // 3. Get options from interaction. - const account = options.getUser("account"); - const credits = options.getInteger("credits"); - const message = options.getString("message"); - if (!account) throw new Error("Account unavailable"); - if (typeof credits !== "number") - throw new Error("You need to enter a valid number of credits to gift"); - - // 4. Create base embeds. - const receiverEmbed = await BaseEmbedSuccess( - guild, - `:credit_card:︱You received a gift from ${user.username}` - ); - - // 5. Start an transaction of the credits. - await creditsTransfer(guild, user, account, credits); - - const receiverGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: account.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: account.id, - }, - where: { - id: account.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger.silly(receiverGuildMember); - - if (message) receiverEmbed.setFields({ name: "Message", value: message }); - - // 6. Tell the target that they have been gifted credits. - await account.send({ - embeds: [ - receiverEmbed.setDescription( - `You received a gift containing ${credits} coins from ${user}! You now have ${receiverGuildMember.creditsEarned} coins in balance!` - ), - ], - }); - - const senderGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - logger.silly(senderGuildMember); - - const senderEmbed = await BaseEmbedSuccess( - guild, - ":credit_card:︱Send a gift" - ); - - if (message) senderEmbed.setFields({ name: "Message", value: message }); - - // 7. Tell the sender that they have gifted the credits. - await interaction.editReply({ - embeds: [ - senderEmbed.setDescription( - `Your gift has been sent to ${account}. You now have ${senderGuildMember.creditsEarned} coins in balance!` - ), - ], - }); -}; diff --git a/src/commands/credits/modules/top/index.ts b/src/commands/credits/modules/top/index.ts deleted file mode 100644 index 52444e2..0000000 --- a/src/commands/credits/modules/top/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { GuildMember } from "@prisma/client"; -import { - CommandInteraction, - SlashCommandSubcommandBuilder, - userMention, -} from "discord.js"; - -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import { success as BaseEmbedSuccess } from "../../../../helpers/baseEmbeds"; -import logger from "../../../../middlewares/logger"; - -// 1. Export a builder function. -export const builder = (command: SlashCommandSubcommandBuilder) => { - return command.setName("top").setDescription(`View the top users`); -}; - -// 2. Export an execute function. -export const execute = async (interaction: CommandInteraction) => { - // 1. Defer reply as permanent. - await deferReply(interaction, false); - - // 2. Destructure interaction object. - const { guild, client } = interaction; - if (!guild) throw new Error("Guild not found"); - if (!client) throw new Error("Client not found"); - - // 3. Create base embeds. - const EmbedSuccess = await BaseEmbedSuccess(guild, "[:dollar:] Top"); - - // 4. Get the top 10 users. - const topTen = await prisma.guildMember.findMany({ - where: { - guildId: guild.id, - }, - orderBy: { - creditsEarned: "desc", - }, - take: 10, - }); - logger.silly(topTen); - - // 5. Create the top 10 list. - const entry = (guildMember: GuildMember, index: number) => - `${index + 1}. ${userMention(guildMember.userId)} | :coin: ${ - guildMember.creditsEarned - }`; - - // 6. Send embed - return interaction.editReply({ - embeds: [ - EmbedSuccess.setDescription( - `The top 10 users in this server are:\n\n${topTen - .map(entry) - .join("\n")}` - ), - ], - }); -}; diff --git a/src/commands/credits/modules/work/index.ts b/src/commands/credits/modules/work/index.ts deleted file mode 100644 index 980e207..0000000 --- a/src/commands/credits/modules/work/index.ts +++ /dev/null @@ -1,64 +0,0 @@ -import Chance from "chance"; -import { CommandInteraction, SlashCommandSubcommandBuilder } from "discord.js"; - -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import { success as BaseEmbedSuccess } from "../../../../helpers/baseEmbeds"; -import creditsGive from "../../../../helpers/credits/give"; -import cooldown from "../../../../middlewares/cooldown"; -import logger from "../../../../middlewares/logger"; - -// 1. Export a builder function. -export const builder = (command: SlashCommandSubcommandBuilder) => { - return command.setName("work").setDescription(`Work to earn credits`); -}; - -// 2. Export an execute function. -export const execute = async (interaction: CommandInteraction) => { - // 1. Defer reply as ephemeral. - await deferReply(interaction, true); - - // 2. Destructure interaction object. - const { guild, user, commandId } = interaction; - if (!guild) throw new Error("Guild not found"); - if (!user) throw new Error("User not found"); - - // 3. Create base embeds. - const EmbedSuccess = await BaseEmbedSuccess(guild, "[:dollar:] Work"); - - // 4. Create new Chance instance. - const chance = new Chance(); - - // 5. Upsert the guild in the database. - const createGuild = await prisma.guild.upsert({ - where: { - id: guild.id, - }, - update: {}, - create: { - id: guild.id, - }, - }); - logger.silly(createGuild); - if (!createGuild) throw new Error("Guild not found"); - - // 6. Create a cooldown for the user. - await cooldown(guild, user, commandId, createGuild.creditsWorkTimeout); - - // 6. Generate a random number between 0 and creditsWorkRate. - const creditsEarned = chance.integer({ - min: 0, - max: createGuild.creditsWorkRate, - }); - - const upsertGuildMember = await creditsGive(guild, user, creditsEarned); - - // 8. Send embed. - await interaction.editReply({ - embeds: [ - EmbedSuccess.setDescription( - `You worked and earned **${creditsEarned}** credits! You now have **${upsertGuildMember.creditsEarned}** credits. :tada:` - ), - ], - }); -}; diff --git a/src/commands/credits/subcommands/balance/index.ts b/src/commands/credits/subcommands/balance/index.ts new file mode 100644 index 0000000..2f73384 --- /dev/null +++ b/src/commands/credits/subcommands/balance/index.ts @@ -0,0 +1,105 @@ +import { GuildMemberCredit } from "@prisma/client"; +import { + ChatInputCommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, + User, +} from "discord.js"; +import CreditsManager from "../../../../handlers/CreditsManager"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; + +const creditsManager = new CreditsManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("balance") + .setDescription(`View account balance`) + .addUserOption((option) => + option + .setName("account") + .setDescription( + "Enter the username of another user to check their balance" + ) + ); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + const { options, user, guild } = interaction; + await deferReply(interaction, false); + + if (!guild) { + throw new Error("This command can only be used in guild environments. ❌"); + } + + const checkAccount = options.getUser("account") || user; + const creditAccount = await creditsManager.balance(guild, checkAccount); + + const isUserCheckAccount = checkAccount.id === user.id; + const pronoun = isUserCheckAccount ? "You" : "They"; + const possessivePronoun = isUserCheckAccount ? "Your" : "Their"; + + const description = getAccountBalanceDescription( + creditAccount, + checkAccount, + isUserCheckAccount, + pronoun, + possessivePronoun + ); + + await sendAccountBalanceEmbed( + interaction, + description, + checkAccount, + pronoun, + possessivePronoun + ); +}; + +const getAccountBalanceDescription = ( + creditAccount: GuildMemberCredit, + checkAccount: User, + isUserCheckAccount: boolean, + pronoun: string, + possessivePronoun: string +) => { + let description = `${ + isUserCheckAccount ? "You" : checkAccount + } currently have ${creditAccount.balance} credits. 💰\n\n`; + + if (creditAccount.balance === 0) { + description += `${possessivePronoun} wallet is empty. Encourage ${ + isUserCheckAccount ? "yourself" : "them" + } to start earning credits by participating in community events and challenges!`; + } else if (creditAccount.balance < 100) { + description += `${pronoun}'re making progress! Keep earning credits and unlock exciting rewards.`; + } else if (creditAccount.balance < 500) { + description += `Great job! ${possessivePronoun} account balance is growing. ${pronoun}'re on ${possessivePronoun.toLowerCase()} way to becoming a credit millionaire!`; + } else { + description += `Wow! ${pronoun}'re a credit master with a substantial account balance. Enjoy the perks and exclusive benefits!`; + } + + return description; +}; + +const sendAccountBalanceEmbed = async ( + interaction: ChatInputCommandInteraction, + description: string, + checkAccount: User, + pronoun: string, + possessivePronoun: string +) => { + await sendResponse(interaction, { + embeds: [ + new EmbedBuilder() + .setColor("#FDD835") + .setAuthor({ name: "💳 Account Balance" }) + .setDescription(description) + .setThumbnail(checkAccount.displayAvatarURL()) + .setFooter({ + text: `${possessivePronoun} credit balance reflects ${possessivePronoun.toLowerCase()} community engagement!`, + }) + .setTimestamp(), + ], + }); +}; diff --git a/src/commands/credits/subcommands/gift/index.ts b/src/commands/credits/subcommands/gift/index.ts new file mode 100644 index 0000000..348c98d --- /dev/null +++ b/src/commands/credits/subcommands/gift/index.ts @@ -0,0 +1,139 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + Guild, + SlashCommandSubcommandBuilder, + User, + codeBlock, +} from "discord.js"; +import CreditsManager from "../../../../handlers/CreditsManager"; +import upsertGuildMember from "../../../../helpers/upsertGuildMember"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; + +const creditsManager = new CreditsManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("gift") + .setDescription("🎁 Gift credits to an account") + .addUserOption((option) => + option + .setName("account") + .setDescription("👤 The account you want to gift to") + .setRequired(true) + ) + .addIntegerOption((option) => + option + .setName("amount") + .setDescription("💰 The amount you want to gift") + .setRequired(true) + .setMinValue(1) + .setMaxValue(2147483647) + ) + .addStringOption((option) => + option + .setName("message") + .setDescription("💬 Your personalized message to the account") + ); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + await deferReply(interaction, true); + + const { options, user, guild } = interaction; + const recipient = options.getUser("account"); + const amount = options.getInteger("amount"); + const message = options.getString("message"); + + if (!guild || !user || !recipient) { + throw new Error("Invalid interaction data"); + } + + if (typeof amount !== "number" || amount < 1) { + throw new Error("Please enter a valid number of credits to gift"); + } + + await upsertGuildMember(guild, user); + + await creditsManager.transfer(guild, user, recipient, amount); + + const recipientEmbed = await createRecipientEmbed( + user, + guild, + recipient, + amount, + message + ); + const senderEmbed = await createSenderEmbed( + guild, + user, + recipient, + amount, + message + ); + + await recipient.send({ embeds: [recipientEmbed] }); + + await sendResponse(interaction, { embeds: [senderEmbed] }); +}; + +const createRecipientEmbed = async ( + sender: User, + guild: Guild, + recipient: User, + amount: number, + message: string | null +) => { + const recipientEmbed = new EmbedBuilder() + .setTimestamp() + .setAuthor({ + name: `🎁 ${sender.username} sent you a gift!`, + }) + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setDescription(`You've received ${amount} credits as a gift!`) + .setThumbnail(sender.displayAvatarURL()) + .setFooter({ + text: `You received this gift in guild ${guild.name}`, + iconURL: guild.iconURL() || "", + }); + + if (message) { + recipientEmbed.addFields({ + name: "Message", + value: codeBlock(message), + }); + } + + return recipientEmbed; +}; + +const createSenderEmbed = async ( + guild: Guild, + sender: User, + recipient: User, + amount: number, + message: string | null +) => { + const senderEmbed = new EmbedBuilder() + .setTimestamp() + .setAuthor({ + name: `🎁 You sent a gift to ${recipient.username}!`, + }) + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setDescription(`You've sent ${amount} credits as a gift!`) + .setThumbnail(recipient.displayAvatarURL()) + .setFooter({ + text: `The recipient received this gift in guild ${guild.name}`, + iconURL: guild.iconURL() || "", + }); + + if (message) { + senderEmbed.addFields({ + name: "Message", + value: codeBlock(message), + }); + } + + return senderEmbed; +}; diff --git a/src/commands/credits/subcommands/top/index.ts b/src/commands/credits/subcommands/top/index.ts new file mode 100644 index 0000000..3d6c701 --- /dev/null +++ b/src/commands/credits/subcommands/top/index.ts @@ -0,0 +1,67 @@ +import { + CommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, + User, +} from "discord.js"; +import CreditsManager from "../../../../handlers/CreditsManager"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; + +const creditsManager = new CreditsManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("top") + .setDescription("View the top users in the server."); +}; + +export const execute = async (interaction: CommandInteraction) => { + const { guild, client, user } = interaction; + + await deferReply(interaction, false); + + if (!guild) { + throw new Error("Unable to find the guild."); + } + + const topTen = await creditsManager.topUsers(guild, 10); + + const embed = new EmbedBuilder() + .setTimestamp() + .setAuthor({ name: "🏅 Top Users" }) + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setFooter({ + text: `Requested by ${user.username}`, + iconURL: user.displayAvatarURL(), + }); + + const medalEmojis = ["🥇", "🥈", "🥉"]; + const genericMedalEmoji = "🏅"; + + const filteredTopTen = topTen.filter((topAccount) => topAccount.balance > 0); + + const fetchUser = async (userId: string): Promise => { + const fetchedUser = await client.users.fetch(userId); + return fetchedUser; + }; + + const topUsersDescription = await Promise.all( + filteredTopTen.map(async (topAccount, index) => { + const position = index + 1; + const fetchedUser = await fetchUser(topAccount.userId); + const userDisplayName = fetchedUser?.username || "Unknown User"; + const fieldContent = `${userDisplayName} with ${topAccount.balance} credits`; + const medalEmoji = + position <= 3 ? medalEmojis[position - 1] : genericMedalEmoji; + return `\`${medalEmoji} ${fieldContent}\``; + }) + ); + + const description = `Here are the top users in this server:\n\n${topUsersDescription.join( + "\n" + )}`; + embed.setDescription(description); + + await sendResponse(interaction, { embeds: [embed] }); +}; diff --git a/src/commands/credits/subcommands/work/index.ts b/src/commands/credits/subcommands/work/index.ts new file mode 100644 index 0000000..e26d3fc --- /dev/null +++ b/src/commands/credits/subcommands/work/index.ts @@ -0,0 +1,137 @@ +import Chance from "chance"; +import { + ChatInputCommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import CooldownManager from "../../../../handlers/CooldownManager"; +import CreditsManager from "../../../../handlers/CreditsManager"; +import prisma from "../../../../handlers/prisma"; +import generateCooldownName from "../../../../helpers/generateCooldownName"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; +import jobs from "./jobs"; + +const cooldownManager = new CooldownManager(); +const creditsManager = new CreditsManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("work") + .setDescription("Put in the hustle and earn some credits!"); +}; + +const fallbackEmoji = "💼"; // Fallback work emoji + +export const execute = async (interaction: ChatInputCommandInteraction) => { + const { guild, user } = interaction; + + await deferReply(interaction, false); + + if (!guild) { + throw new Error( + "Oops! It seems like you're not part of a guild. Join a guild to use this command!" + ); + } + + if (!user) { + throw new Error( + "Oops! It looks like we couldn't find your user information. Please try again or contact support for assistance." + ); + } + + const chance = new Chance(); + + const getRandomWork = () => { + return chance.pickone(jobs); + }; + + // Retrieve settings from the GuildSettings model + const guildCreditsSettings = await prisma.guildCreditsSettings.findUnique({ + where: { id: guild.id }, + }); + + const baseCreditsRate = getRandomWork().creditsRate; // Get the base rate of credits earned per work action + const bonusChance = guildCreditsSettings?.workBonusChance || 30; // Retrieve bonus chance from guild settings or use default value + const penaltyChance = guildCreditsSettings?.workPenaltyChance || 10; // Retrieve penalty chance from guild settings or use default value + const baseCreditsEarned = chance.integer({ min: 1, max: baseCreditsRate }); // Generate a random base number of credits earned + + let bonusCredits = 0; // Initialize bonus credits + let penaltyCredits = 0; // Initialize penalty credits + let creditsEarned = baseCreditsEarned; // Set the initial earned credits to the base amount + let work; + + if (chance.bool({ likelihood: bonusChance })) { + // Earn bonus credits + const bonusMultiplier = chance.floating({ min: 1.1, max: 1.5 }); // Get a random multiplier for the bonus credits + bonusCredits = Math.ceil(baseCreditsEarned * bonusMultiplier); // Calculate the bonus credits + creditsEarned = baseCreditsEarned + bonusCredits; // Update the total earned credits + work = getRandomWork(); // Get a random work type + } else if (chance.bool({ likelihood: penaltyChance })) { + // Receive a penalty + const penaltyMultiplier = chance.floating({ min: 0.5, max: 0.8 }); // Get a random multiplier for the penalty credits + penaltyCredits = Math.ceil(baseCreditsEarned * penaltyMultiplier); // Calculate the penalty credits + creditsEarned = baseCreditsEarned - penaltyCredits; // Update the total earned credits + work = getRandomWork(); // Get a random work type + } else { + // Earn base credits + work = getRandomWork(); // Get a random work type + } + + // Descriptions + const descriptions = []; + + // Work Description + descriptions.push( + `Mission complete! You've earned **${baseCreditsEarned} credits**! 🎉` + ); + + // Bonus Description + if (bonusCredits > 0) { + descriptions.push(`💰 Bonus: **${bonusCredits} credits**!`); + } + + // Penalty Description + if (penaltyCredits !== 0) { + descriptions.push(`😱 Penalty: **${penaltyCredits} credits** deducted.`); + } + + // Total Credits Description + descriptions.push( + `Total earnings: **${creditsEarned} credits**. Keep up the hustle!` + ); + + if (creditsEarned > 0) { + await creditsManager.give(guild, user, creditsEarned); // Give the user the earned credits + } + + // User Balance + const userBalance = await creditsManager.balance(guild, user); + + const embedSuccess = new EmbedBuilder() + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setAuthor({ + name: `${user.username}'s Work Result`, + iconURL: user.displayAvatarURL(), + }) + .setTimestamp() + .setDescription(descriptions.join("\n")) + .setFooter({ + text: `${user.username} just worked as a ${work.name}! ${ + work?.emoji || fallbackEmoji + }`, + }) + .addFields({ + name: "New Balance", + value: `${userBalance.balance} credits`, + }); + + await sendResponse(interaction, { embeds: [embedSuccess] }); + + await cooldownManager.setCooldown( + await generateCooldownName(interaction), + guild, + user, + 86400 + ); +}; diff --git a/src/commands/credits/subcommands/work/jobs.ts b/src/commands/credits/subcommands/work/jobs.ts new file mode 100644 index 0000000..5adfffa --- /dev/null +++ b/src/commands/credits/subcommands/work/jobs.ts @@ -0,0 +1,74 @@ +const jobs = [ + { name: "Software Developer", creditsRate: 37.5, emoji: "💻" }, + { name: "Graphic Designer", creditsRate: 30, emoji: "🎨" }, + { name: "Content Writer", creditsRate: 22.5, emoji: "📝" }, + { name: "Social Media Manager", creditsRate: 26.25, emoji: "📱" }, + { name: "Data Analyst", creditsRate: 33.75, emoji: "📊" }, + { name: "Video Editor", creditsRate: 28.125, emoji: "🎥" }, + { name: "Photographer", creditsRate: 26.25, emoji: "📸" }, + { name: "Marketing Specialist", creditsRate: 31.875, emoji: "📣" }, + { name: "Customer Support Representative", creditsRate: 18.75, emoji: "📞" }, + { name: "Translator", creditsRate: 24.375, emoji: "🌍" }, + { name: "Sales Representative", creditsRate: 30, emoji: "💼" }, + { name: "Event Planner", creditsRate: 28.125, emoji: "🎉" }, + { name: "Fitness Instructor", creditsRate: 22.5, emoji: "💪" }, + { name: "Chef", creditsRate: 33.75, emoji: "👨‍🍳" }, + { name: "Baker", creditsRate: 26.25, emoji: "🥐" }, + { name: "Barista", creditsRate: 20.625, emoji: "☕" }, + { name: "Personal Trainer", creditsRate: 30, emoji: "🏋️‍♂️" }, + { name: "Hair Stylist", creditsRate: 24.375, emoji: "💇" }, + { name: "Pet Groomer", creditsRate: 22.5, emoji: "🐶" }, + { name: "Gardener", creditsRate: 20.625, emoji: "🌿" }, + { name: "Game Developer", creditsRate: 35.625, emoji: "🎮" }, + { name: "Game Tester", creditsRate: 26.25, emoji: "🕹️" }, + { name: "Game Designer", creditsRate: 31.875, emoji: "🎲" }, + { name: "Linux System Administrator", creditsRate: 33.75, emoji: "🐧" }, + { name: "Network Engineer", creditsRate: 30, emoji: "🌐" }, + { name: "DevOps Engineer", creditsRate: 31.875, emoji: "🔧" }, + { name: "Database Administrator", creditsRate: 28.125, emoji: "🗄️" }, + { name: "Server Administrator", creditsRate: 30, emoji: "🖥️" }, + { name: "IT Security Specialist", creditsRate: 33.75, emoji: "🔒" }, + { name: "Cloud Architect", creditsRate: 31.875, emoji: "☁️" }, + { name: "Linux System Administrator", creditsRate: 33.75, emoji: "🐧" }, + { name: "Network Engineer", creditsRate: 30, emoji: "🌐" }, + { name: "DevOps Engineer", creditsRate: 31.875, emoji: "🔧" }, + { name: "Database Administrator", creditsRate: 28.125, emoji: "🗄️" }, + { name: "Server Administrator", creditsRate: 30, emoji: "🖥️" }, + { name: "IT Security Specialist", creditsRate: 33.75, emoji: "🔒" }, + { name: "Cloud Architect", creditsRate: 31.875, emoji: "☁️" }, + { name: "Linux Kernel Developer", creditsRate: 35.625, emoji: "🐧💻" }, + { name: "Linux Distribution Maintainer", creditsRate: 31.875, emoji: "📦🐧" }, + { name: "Linux System Engineer", creditsRate: 31.875, emoji: "🔩🐧" }, + { name: "Linux Network Administrator", creditsRate: 30, emoji: "🌐🐧" }, + { name: "Linux Security Analyst", creditsRate: 33.75, emoji: "🔒🐧" }, + { + name: "Linux Virtualization Specialist", + creditsRate: 31.875, + emoji: "💻🐧", + }, + { name: "Linux Storage Administrator", creditsRate: 30, emoji: "💾🐧" }, + { name: "Linux Web Server Administrator", creditsRate: 30, emoji: "🌐🐧" }, + { name: "Linux Automation Engineer", creditsRate: 31.875, emoji: "⚙️🐧" }, + { + name: "Linux Desktop Support Specialist", + creditsRate: 28.125, + emoji: "🖥️🐧", + }, + { name: "Linux Consultant", creditsRate: 33.75, emoji: "👩‍💼🐧" }, + { name: "Network Engineer", creditsRate: 30, emoji: "🌐" }, + { name: "Network Administrator", creditsRate: 28.125, emoji: "🔌🔧" }, + { name: "Network Security Engineer", creditsRate: 33.75, emoji: "🔒🔧" }, + { name: "Network Architect", creditsRate: 31.875, emoji: "🏛️🌐" }, + { name: "Wireless Network Engineer", creditsRate: 30, emoji: "📶🌐" }, + { + name: "Network Operations Center (NOC) Technician", + creditsRate: 26.25, + emoji: "📡🔧", + }, + { name: "Network Support Specialist", creditsRate: 26.25, emoji: "🔧📞" }, + { name: "Network Consultant", creditsRate: 33.75, emoji: "👩‍💼🌐" }, + { name: "Network Project Manager", creditsRate: 31.875, emoji: "👩‍💼📂🌐" }, + { name: "VoIP Engineer", creditsRate: 30, emoji: "☎️🌐" }, +]; + +export default jobs; diff --git a/src/commands/dns/index.ts b/src/commands/dns/index.ts index b252bfe..3677233 100644 --- a/src/commands/dns/index.ts +++ b/src/commands/dns/index.ts @@ -1,24 +1,20 @@ import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; +import { + SubcommandHandlers, + executeSubcommand, +} from "../../handlers/executeSubcommand"; -// Modules -import moduleLookup from "./modules/lookup"; +import * as lookup from "./subcommands/lookup"; + +const subcommandHandlers: SubcommandHandlers = { + lookup: lookup.execute, +}; export const builder = new SlashCommandBuilder() .setName("dns") .setDescription("DNS commands.") + .addSubcommand(lookup.builder); - // Modules - .addSubcommand(moduleLookup.builder); - -// Execute the command export const execute = async (interaction: ChatInputCommandInteraction) => { - switch (interaction.options.getSubcommand()) { - case "lookup": - await moduleLookup.execute(interaction); - break; - default: - throw new Error( - `Unknown subcommand: ${interaction.options.getSubcommand()}` - ); - } + await executeSubcommand(interaction, subcommandHandlers); }; diff --git a/src/commands/dns/modules/lookup/index.ts b/src/commands/dns/modules/lookup/index.ts deleted file mode 100644 index b4fe4bd..0000000 --- a/src/commands/dns/modules/lookup/index.ts +++ /dev/null @@ -1,133 +0,0 @@ -import axios from "axios"; -import { - ChatInputCommandInteraction, - EmbedBuilder, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import deferReply from "../../../../handlers/deferReply"; -import getEmbedConfig from "../../../../helpers/getEmbedData"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("lookup") - .setDescription( - "Lookup a domain or ip. (Request sent over HTTP, proceed with caution!)" - ) - .addStringOption((option) => - option - .setName("query") - .setDescription("The query you want to look up.") - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, false); - - const { errorColor, successColor, footerText, footerIcon } = - await getEmbedConfig(interaction.guild); - const embedTitle = "[:hammer:] Utility (Lookup)"; - - const { options } = interaction; - const query = options.getString("query"); - - await axios - .get(`http://ip-api.com/json/${query}`) - .then(async (response) => { - if (response.data.status !== "success") { - await interaction.editReply({ - embeds: [ - new EmbedBuilder() - .setTitle(embedTitle) - .setFooter({ - text: footerText, - iconURL: footerIcon, - }) - .setTimestamp(new Date()) - .setColor(errorColor) - .setFooter({ text: footerText, iconURL: footerIcon }) - .setDescription( - `${response?.data?.message}: ${response?.data?.query}` - ), - ], - }); - return; - } - - await interaction.editReply({ - embeds: [ - new EmbedBuilder() - .setTitle(embedTitle) - .setFooter({ - text: footerText, - iconURL: footerIcon, - }) - .setTimestamp(new Date()) - .setColor(successColor) - .setFields([ - { - name: ":classical_building: AS", - value: `${response.data.as || "Unknown"}`, - inline: true, - }, - { - name: ":classical_building: ISP", - value: `${response.data.isp || "Unknown"}`, - inline: true, - }, - { - name: ":classical_building: Organization", - value: `${response.data.org || "Unknown"}`, - inline: true, - }, - { - name: ":compass: Latitude", - value: `${response.data.lat || "Unknown"}`, - inline: true, - }, - { - name: ":compass: Longitude", - value: `${response.data.lon || "Unknown"}`, - inline: true, - }, - { - name: ":clock4: Timezone", - value: `${response.data.timezone || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: Country", - value: `${response.data.country || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: Region", - value: `${response.data.regionName || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: City", - value: `${response.data.city || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: Country Code", - value: `${response.data.countryCode || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: Region Code", - value: `${response.data.region || "Unknown"}`, - inline: true, - }, - { - name: ":globe_with_meridians: ZIP", - value: `${response.data.zip || "Unknown"}`, - inline: true, - }, - ]), - ], - }); - }); - }, -}; diff --git a/src/commands/dns/subcommands/lookup/index.ts b/src/commands/dns/subcommands/lookup/index.ts new file mode 100644 index 0000000..d6d930b --- /dev/null +++ b/src/commands/dns/subcommands/lookup/index.ts @@ -0,0 +1,91 @@ +import axios from "axios"; +import { + ChatInputCommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import dns from "node:dns"; +import { promisify } from "util"; +import { default as CooldownManager } from "../../../../handlers/CooldownManager"; +import generateCooldownName from "../../../../helpers/generateCooldownName"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; + +const cooldownManager = new CooldownManager(); + +const dnsLookup = promisify(dns.lookup); + +export const builder = ( + command: SlashCommandSubcommandBuilder +): SlashCommandSubcommandBuilder => { + return command + .setName("lookup") + .setDescription("Lookup a domain or IP.") + .addStringOption((option) => + option + .setName("query") + .setDescription("The query you want to look up.") + .setRequired(true) + ); +}; + +export const execute = async ( + interaction: ChatInputCommandInteraction +): Promise => { + await deferReply(interaction, false); + + const { user, guild, options } = interaction; + const query = options.getString("query", true); + + try { + const { address } = await dnsLookup(query); + + const { data } = await axios.get(`https://ipinfo.io/${address}`); + + await sendResponse(interaction, { + embeds: [ + new EmbedBuilder() + .setAuthor({ + name: `Powered using IPinfo.io`, + url: "https://ipinfo.io", + iconURL: "https://ipinfo.io/static/favicon-96x96.png?v3", + }) + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setFooter({ + text: `Requested by ${user.username}`, + iconURL: user.displayAvatarURL(), + }) + .setTimestamp().setDescription(` + **IP**: ${data.ip} + **Hostname**: ${data.hostname} + **Organization**: ${data.org} + **Anycast**: ${data.anycast ? "Yes" : "No"} + **City**: ${data.city} + **Region**: ${data.region} + **Country**: ${data.country} + **Location**: ${data.loc} + **Postal**: ${data.postal} + **Timezone**: ${data.timezone} + `), + ], + }); + + const cooldownName = await generateCooldownName(interaction); + const cooldownDuration = 5; + + await cooldownManager.setCooldown( + cooldownName, + guild || null, + user, + cooldownDuration + ); + } catch (error: unknown) { + if ((error as NodeJS.ErrnoException).code === "ENOTFOUND") { + throw new Error( + `Sorry, we couldn't find the address for the requested query: ${query}.` + ); + } else { + throw error; + } + } +}; diff --git a/src/commands/fun/index.ts b/src/commands/fun/index.ts index f2ab5b8..8096f37 100644 --- a/src/commands/fun/index.ts +++ b/src/commands/fun/index.ts @@ -1,22 +1,23 @@ import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; -import logger from "../../middlewares/logger"; -// Modules -import moduleMeme from "./modules/meme"; +// Subcommands +import { + SubcommandHandlers, + executeSubcommand, +} from "../../handlers/executeSubcommand"; +import * as meme from "./subcommands/meme"; + +const subcommandHandlers: SubcommandHandlers = { + meme: meme.execute, +}; export const builder = new SlashCommandBuilder() .setName("fun") .setDescription("Fun commands.") - .addSubcommand(moduleMeme.builder); + .addSubcommand(meme.builder); // Execute function export const execute = async (interaction: ChatInputCommandInteraction) => { - const { options } = interaction; - - if (options.getSubcommand() === "meme") { - await moduleMeme.execute(interaction); - } else { - logger.silly(`Unknown subcommand ${options.getSubcommand()}`); - } + await executeSubcommand(interaction, subcommandHandlers); }; diff --git a/src/commands/fun/modules/meme/index.ts b/src/commands/fun/modules/meme/index.ts deleted file mode 100644 index 01089a5..0000000 --- a/src/commands/fun/modules/meme/index.ts +++ /dev/null @@ -1,61 +0,0 @@ -import axios from "axios"; -import { - ActionRowBuilder, - ButtonBuilder, - ButtonStyle, - CommandInteraction, - EmbedBuilder, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import deferReply from "../../../../handlers/deferReply"; -import getEmbedConfig from "../../../../helpers/getEmbedData"; -import cooldown from "../../../../middlewares/cooldown"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command.setName("meme").setDescription("Random memes from r/memes"); - }, - - execute: async (interaction: CommandInteraction) => { - await deferReply(interaction, false); - - const { guild, user, commandId } = interaction; - if (!guild) throw new Error("Server unavailable"); - if (!user) throw new Error("User unavailable"); - - await cooldown(guild, user, commandId, 15); - - const embedConfig = await getEmbedConfig(guild); - - await axios - .get("https://www.reddit.com/r/memes/random/.json") - .then(async (res) => { - const response = res.data[0].data.children; - const content = response[0].data; - - const buttons = new ActionRowBuilder().addComponents( - new ButtonBuilder() - .setLabel("View post") - .setStyle(ButtonStyle.Link) - .setEmoji("🔗") - .setURL(`https://reddit.com${content.permalink}`) - ); - - const embed = new EmbedBuilder() - .setTitle(`😆︱Meme`) - .setDescription(`**${content.title}**`) - .setTimestamp(new Date()) - .setImage(content.url) - .setFooter({ - text: `👍 ${content.ups}︱👎 ${content.downs}`, - }) - .setColor(embedConfig.successColor); - - await interaction.editReply({ embeds: [embed], components: [buttons] }); - return; - }) - .catch((error) => { - throw new Error(error.message); - }); - }, -}; diff --git a/src/commands/fun/subcommands/meme/index.ts b/src/commands/fun/subcommands/meme/index.ts new file mode 100644 index 0000000..bd6d36f --- /dev/null +++ b/src/commands/fun/subcommands/meme/index.ts @@ -0,0 +1,112 @@ +import axios from "axios"; +import { + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + ChatInputCommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, + TextChannel, +} from "discord.js"; +import CooldownManager from "../../../../handlers/CooldownManager"; +import generateCooldownName from "../../../../helpers/generateCooldownName"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; + +const cooldownManager = new CooldownManager(); + +interface MemeContent { + title: string; + url: string; + author: string; + ups: number; + over_18: boolean; + permalink: string; +} + +interface AuthorData { + icon_img: string; + // Add other properties as needed +} + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command.setName("meme").setDescription("Random memes from r/memes"); +}; + +export const execute = async ( + interaction: ChatInputCommandInteraction +): Promise => { + await deferReply(interaction, false); + + const { channel, guild, user } = interaction; + const cooldownItem = await generateCooldownName(interaction); + const cooldownDuration = 15; // 10 seconds + + try { + const content: MemeContent = await fetchRandomMeme(); + const authorData: AuthorData = await fetchAuthorData(content.author); + + if (channel instanceof TextChannel && channel.nsfw && content.over_18) { + // NSFW handling logic (e.g., skip or show a warning message) + return; + } + + const buttons = createButtons(content.permalink); + const embed = createEmbed(content, authorData); + + await sendResponse(interaction, { + embeds: [embed], + components: [buttons], + }); + } catch (error) { + throw new Error( + "Sorry, we couldn't fetch a meme at the moment. Please try again later." + ); + } + + await cooldownManager.setCooldown( + cooldownItem, + guild || null, + user, + cooldownDuration + ); +}; + +async function fetchRandomMeme(): Promise { + const { data } = await axios.get( + "https://www.reddit.com/r/memes/random/.json" + ); + const { children } = data[0].data; + const content: MemeContent = children[0].data; + return content; +} + +async function fetchAuthorData(author: string): Promise { + const { data } = await axios.get( + `https://www.reddit.com/user/${author}/about.json` + ); + const authorData: AuthorData = data.data; + return authorData; +} + +function createButtons(permalink: string) { + return new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setLabel("View post") + .setStyle(ButtonStyle.Link) + .setEmoji("🔗") + .setURL(`https://reddit.com${permalink}`) + ); +} + +function createEmbed(content: MemeContent, authorData: AuthorData) { + return new EmbedBuilder() + .setAuthor({ name: content.title }) + .setTimestamp() + .setImage(content.url) + .setFooter({ + text: `Meme by ${content.author} | 👍 ${content.ups}`, + iconURL: authorData.icon_img.split("?").shift(), + }) + .setColor(process.env.EMBED_COLOR_SUCCESS); +} diff --git a/src/commands/manage/groups/credits/index.ts b/src/commands/manage/groups/credits/index.ts new file mode 100644 index 0000000..cb393b5 --- /dev/null +++ b/src/commands/manage/groups/credits/index.ts @@ -0,0 +1,25 @@ +import { SlashCommandSubcommandGroupBuilder } from "discord.js"; +import * as give from "./subcommands/give"; +import * as giveaway from "./subcommands/giveaway"; +import * as set from "./subcommands/set"; +import * as take from "./subcommands/take"; +import * as transfer from "./subcommands/transfer"; + +export const builder = (group: SlashCommandSubcommandGroupBuilder) => { + return group + .setName("credits") + .setDescription("Manage the credits of a user.") + .addSubcommand(give.builder) + .addSubcommand(set.builder) + .addSubcommand(take.builder) + .addSubcommand(transfer.builder) + .addSubcommand(giveaway.builder); +}; + +export const subcommands = { + give, + set, + take, + transfer, + giveaway, +}; diff --git a/src/commands/manage/groups/credits/subcommands/give/index.ts b/src/commands/manage/groups/credits/subcommands/give/index.ts new file mode 100644 index 0000000..472e792 --- /dev/null +++ b/src/commands/manage/groups/credits/subcommands/give/index.ts @@ -0,0 +1,71 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + PermissionsBitField, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import CreditsManager from "../../../../../../handlers/CreditsManager"; +import checkPermission from "../../../../../../utils/checkPermission"; +import deferReply from "../../../../../../utils/deferReply"; +import sendResponse from "../../../../../../utils/sendResponse"; + +const creditsManager = new CreditsManager(); + +export const builder = ( + command: SlashCommandSubcommandBuilder +): SlashCommandSubcommandBuilder => { + return command + .setName("give") + .setDescription("Give credits to a user.") + .addUserOption((option) => + option + .setName("user") + .setDescription("The user to give credits to.") + .setRequired(true) + ) + .addIntegerOption((option) => + option + .setName("amount") + .setDescription("The amount of credits to give.") + .setRequired(true) + .setMinValue(1) + .setMaxValue(2147483647) + ); +}; + +export const execute = async ( + interaction: ChatInputCommandInteraction +): Promise => { + const { guild, options, user } = interaction; + + await deferReply(interaction, false); + checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + + if (!guild) { + throw new Error("We could not get the current guild from Discord."); + } + + const discordReceiver = options.getUser("user", true); + const creditsAmount = options.getInteger("amount", true); + + if (!discordReceiver || typeof creditsAmount !== "number") { + await sendResponse(interaction, "Invalid user or credit amount provided."); + return; + } + + const embedSuccess = new EmbedBuilder() + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setAuthor({ name: "💳 Credits Manager" }) + .setDescription( + ` Successfully gave ${creditsAmount} credits to the user.` + ) + .setFooter({ + text: `Action by ${user.username}`, + iconURL: user.displayAvatarURL(), + }) + .setTimestamp(); + + await creditsManager.give(guild, discordReceiver, creditsAmount); + + await sendResponse(interaction, { embeds: [embedSuccess] }); +}; diff --git a/src/commands/manage/groups/credits/subcommands/giveaway/index.ts b/src/commands/manage/groups/credits/subcommands/giveaway/index.ts new file mode 100644 index 0000000..70629e0 --- /dev/null +++ b/src/commands/manage/groups/credits/subcommands/giveaway/index.ts @@ -0,0 +1,107 @@ +// Dependencies +import { + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + ChannelType, + ChatInputCommandInteraction, + EmbedBuilder, + PermissionsBitField, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import { v4 as uuidv4 } from "uuid"; +// Configurations +import CtrlPanelAPI from "../../../../../../services/CtrlPanelAPI"; +import checkPermission from "../../../../../../utils/checkPermission"; +import deferReply from "../../../../../../utils/deferReply"; +import sendResponse from "../../../../../../utils/sendResponse"; + +// Function +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("giveaway") + .setDescription("Giveaway some credits for specified amount of users.") + .addIntegerOption((option) => + option + .setName("uses") + .setDescription("How many users should be able to use this.") + .setRequired(true) + ) + .addIntegerOption((option) => + option + .setName("credit") + .setDescription(`How much credits provided per use.`) + .setRequired(true) + ) + .addChannelOption((option) => + option + .setName("channel") + .setDescription("The channel to send the message to.") + .setRequired(true) + .addChannelTypes(ChannelType.GuildText) + ); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + const { guild, options } = interaction; + + await deferReply(interaction, true); + checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + + if (!guild) throw new Error("This command can only be used in guilds"); + const ctrlPanelAPI = new CtrlPanelAPI(guild); + + const uses = options?.getInteger("uses"); + const creditAmount = options?.getInteger("credit"); + const channel = options?.getChannel("channel"); + + if (!uses) throw new Error("Amount of uses is required."); + if (!creditAmount) throw new Error("Amount of credits is required."); + if (!channel) throw new Error("Channel is required."); + if (!guild) throw new Error("Guild is required."); + + const embedSuccess = new EmbedBuilder() + .setTitle(":toolbox:︱Giveaway") + .setColor("#FFFFFF") + .setTimestamp(new Date()); + + const code = uuidv4(); + const { redeemUrl } = await ctrlPanelAPI.generateVoucher( + code, + creditAmount, + uses + ); + + await sendResponse(interaction, { + embeds: [embedSuccess.setDescription(`Successfully created code: ${code}`)], + }); + + const buttons = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setLabel("Redeem it here") + .setStyle(ButtonStyle.Link) + .setEmoji("🏦") + .setURL(`${redeemUrl}`) + ); + + const discordChannel = await guild.channels.fetch(channel.id); + if (!discordChannel) return; + if (discordChannel.type !== ChannelType.GuildText) return; + + discordChannel.send({ + embeds: [ + embedSuccess + .addFields([ + { + name: "💶 Credits", + value: `${creditAmount}`, + inline: true, + }, + ]) + .setDescription( + `${interaction.user} dropped a voucher for a maximum **${uses}** members!` + ), + ], + components: [buttons], + }); +}; diff --git a/src/commands/manage/groups/credits/subcommands/set/index.ts b/src/commands/manage/groups/credits/subcommands/set/index.ts new file mode 100644 index 0000000..9cf342a --- /dev/null +++ b/src/commands/manage/groups/credits/subcommands/set/index.ts @@ -0,0 +1,69 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + PermissionsBitField, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import CreditsManager from "../../../../../../handlers/CreditsManager"; +import checkPermission from "../../../../../../utils/checkPermission"; +import deferReply from "../../../../../../utils/deferReply"; +import sendResponse from "../../../../../../utils/sendResponse"; + +const creditsManager = new CreditsManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("set") + .setDescription("Set credits to a user.") + .addUserOption((option) => + option + .setName("user") + .setDescription("The user to set credits to.") + .setRequired(true) + ) + .addIntegerOption((option) => + option + .setName("amount") + .setDescription(`The amount of credits to set.`) + .setRequired(true) + .setMinValue(1) + .setMaxValue(2147483647) + ); +}; + +export const execute = async ( + interaction: ChatInputCommandInteraction +): Promise => { + const { guild, options, user } = interaction; + + await deferReply(interaction, false); + checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + + if (!guild) { + throw new Error("We could not get the current guild from Discord."); + } + + const discordReceiver = options.getUser("user"); + const creditsAmount = options.getInteger("amount"); + + if (!discordReceiver || typeof creditsAmount !== "number") { + await sendResponse(interaction, "Invalid user or credit amount provided."); + return; + } + + const embedSuccess = new EmbedBuilder() + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setAuthor({ name: "💳 Credits Manager" }) + .setDescription( + ` Successfully set ${creditsAmount} credits to the user.` + ) + .setFooter({ + text: `Action by ${user.username}`, + iconURL: user.displayAvatarURL(), + }) + .setTimestamp(); + + await creditsManager.set(guild, discordReceiver, creditsAmount); + + await sendResponse(interaction, { embeds: [embedSuccess] }); +}; diff --git a/src/commands/manage/groups/credits/subcommands/take/index.ts b/src/commands/manage/groups/credits/subcommands/take/index.ts new file mode 100644 index 0000000..eb815d9 --- /dev/null +++ b/src/commands/manage/groups/credits/subcommands/take/index.ts @@ -0,0 +1,69 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + PermissionsBitField, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import CreditsManager from "../../../../../../handlers/CreditsManager"; +import checkPermission from "../../../../../../utils/checkPermission"; +import deferReply from "../../../../../../utils/deferReply"; +import sendResponse from "../../../../../../utils/sendResponse"; + +const creditsManager = new CreditsManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("take") + .setDescription("Take credits from a user.") + .addUserOption((option) => + option + .setName("user") + .setDescription("The user to take credits from.") + .setRequired(true) + ) + .addIntegerOption((option) => + option + .setName("amount") + .setDescription(`The amount of credits to take.`) + .setRequired(true) + .setMinValue(1) + .setMaxValue(2147483647) + ); +}; + +export const execute = async ( + interaction: ChatInputCommandInteraction +): Promise => { + const { guild, options, user } = interaction; + + await deferReply(interaction, false); + checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + + if (!guild) { + throw new Error("We could not get the current guild from Discord."); + } + + const discordReceiver = options.getUser("user"); + const creditsAmount = options.getInteger("amount"); + + if (!discordReceiver || typeof creditsAmount !== "number") { + await sendResponse(interaction, "Invalid user or credit amount provided."); + return; + } + + const embedSuccess = new EmbedBuilder() + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setAuthor({ name: "💳 Credits Manager" }) + .setDescription( + ` Successfully took ${creditsAmount} credits to the user.` + ) + .setFooter({ + text: `Action by ${user.username}`, + iconURL: user.displayAvatarURL(), + }) + .setTimestamp(); + + await creditsManager.take(guild, discordReceiver, creditsAmount); + + await sendResponse(interaction, { embeds: [embedSuccess] }); +}; diff --git a/src/commands/manage/groups/credits/subcommands/transfer/index.ts b/src/commands/manage/groups/credits/subcommands/transfer/index.ts new file mode 100644 index 0000000..9a0a00e --- /dev/null +++ b/src/commands/manage/groups/credits/subcommands/transfer/index.ts @@ -0,0 +1,111 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + PermissionsBitField, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import CreditsManager from "../../../../../../handlers/CreditsManager"; +import checkPermission from "../../../../../../utils/checkPermission"; +import deferReply from "../../../../../../utils/deferReply"; +import sendResponse from "../../../../../../utils/sendResponse"; + +const creditsManager = new CreditsManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("transfer") + .setDescription("Transfer credits from a user to another.") + .addUserOption((option) => + option + .setName("from-user") + .setDescription("The user to take credits from.") + .setRequired(true) + ) + .addUserOption((option) => + option + .setName("to-user") + .setDescription("The user to give credits to.") + .setRequired(true) + ) + .addIntegerOption((option) => + option + .setName("amount") + .setDescription(`The amount of credits to set.`) + .setRequired(true) + .setMinValue(1) + .setMaxValue(2147483647) + ); +}; + +export const execute = async ( + interaction: ChatInputCommandInteraction +): Promise => { + const { guild, options, user } = interaction; + + await deferReply(interaction, false); + checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + + if (!guild) { + throw new Error("We could not get the current guild from Discord."); + } + + const fromUser = options.getUser("from-user"); + const toUser = options.getUser("to-user"); + const creditsAmount = options.getInteger("amount"); + + if (!fromUser || !toUser || typeof creditsAmount !== "number") { + throw new Error("Invalid user(s) or credit amount provided."); + } + + const transactionResult = await creditsManager.transfer( + guild, + fromUser, + toUser, + creditsAmount + ); + + // Constructing the transfer embed + const transferEmbed = new EmbedBuilder() + .setColor(process.env.EMBED_COLOR_SUCCESS) + .addFields( + { name: "📤 Sender", value: fromUser.username, inline: true }, + { name: "📥 Recipient", value: toUser.username, inline: true }, + { + name: "💰 Transferred Amount", + value: `${transactionResult.transferredAmount}`, + inline: true, + }, + { + name: "🪙 Sender Balance", + value: `${transactionResult.fromTransaction.balance}`, + inline: true, + }, + { + name: "🪙 Recipient Balance", + value: `${transactionResult.toTransaction.balance}`, + inline: true, + } + ) + .setAuthor({ name: "This is an administrative action." }) + //.setThumbnail(user.displayAvatarURL()) + .setFooter({ + text: `Action by ${user.username}`, + iconURL: user.displayAvatarURL(), + }) + .setTimestamp(); + + // Adding explanation if not all credits were transferred + if (creditsAmount !== transactionResult.transferredAmount) { + transferEmbed.setAuthor({ + name: `⚠️ Some credits could not be transferred.`, + }); + const explanation = `*This is because the transfer amount exceeded the maximum allowed limit.*`; + transferEmbed.setDescription(explanation); + } else { + transferEmbed.setAuthor({ + name: "✅ All credits have been successfully transferred.", + }); + } + + await sendResponse(interaction, { embeds: [transferEmbed] }); +}; diff --git a/src/commands/manage/index.ts b/src/commands/manage/index.ts index d532b0a..b643a0d 100644 --- a/src/commands/manage/index.ts +++ b/src/commands/manage/index.ts @@ -1,35 +1,26 @@ -//Dependencies import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; +import { + SubcommandGroupHandlers, + executeSubcommand, +} from "../../handlers/executeSubcommand"; +import * as credits from "./groups/credits"; -// Modules -import moduleCounters from "./modules/counters"; -import moduleCredits from "./modules/credits"; +const subcommandGroupHandlers: SubcommandGroupHandlers = { + credits: { + give: credits.subcommands.give.execute, + giveaway: credits.subcommands.giveaway.execute, + set: credits.subcommands.set.execute, + take: credits.subcommands.take.execute, + transfer: credits.subcommands.transfer.execute, + }, +}; -// Function export const builder = new SlashCommandBuilder() .setName("manage") .setDescription("Manage the bot.") .setDMPermission(false) - - // Modules - .addSubcommandGroup(moduleCounters.builder) - .addSubcommandGroup(moduleCredits.builder); + .addSubcommandGroup(credits.builder); export const execute = async (interaction: ChatInputCommandInteraction) => { - // Destructure - const { options } = interaction; - - switch (options.getSubcommandGroup()) { - case "credits": { - await moduleCredits.execute(interaction); - break; - } - case "counters": { - await moduleCounters.execute(interaction); - break; - } - default: { - throw new Error("Could not find an module for the command."); - } - } + await executeSubcommand(interaction, {}, subcommandGroupHandlers); }; diff --git a/src/commands/manage/modules/counters/index.ts b/src/commands/manage/modules/counters/index.ts deleted file mode 100644 index 1074ad5..0000000 --- a/src/commands/manage/modules/counters/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Dependencies -import { - ChatInputCommandInteraction, - SlashCommandSubcommandGroupBuilder, -} from "discord.js"; - -// Modules -import moduleAdd from "./modules/add"; -import moduleRemove from "./modules/remove"; - -export default { - builder: (group: SlashCommandSubcommandGroupBuilder) => { - return group - .setName("counters") - .setDescription("Manage guild counters.") - .addSubcommand(moduleAdd.builder) - .addSubcommand(moduleRemove.builder); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - const { options } = interaction; - - switch (options.getSubcommand()) { - case "add": { - await moduleAdd.execute(interaction); - break; - } - case "remove": { - await moduleRemove.execute(interaction); - break; - } - default: { - throw new Error("Could not found a module for that command."); - } - } - }, -}; diff --git a/src/commands/manage/modules/counters/modules/add/index.ts b/src/commands/manage/modules/counters/modules/add/index.ts deleted file mode 100644 index 30e3d6a..0000000 --- a/src/commands/manage/modules/counters/modules/add/index.ts +++ /dev/null @@ -1,113 +0,0 @@ -// Dependencies -import { - ChannelType, - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import deferReply from "../../../../../../handlers/deferReply"; -import checkPermission from "../../../../../../helpers/checkPermission"; -// Configurations -import prisma from "../../../../../../handlers/database"; -import getEmbedConfig from "../../../../../../helpers/getEmbedData"; -import logger from "../../../../../../middlewares/logger"; - -// Function -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("add") - .setDescription("Add a counter to your guild.") - .addChannelOption((option) => - option - .setName("channel") - .setDescription("The channel to send the counter to.") - .setRequired(true) - .addChannelTypes(ChannelType.GuildText) - ) - .addStringOption((option) => - option - .setName("word") - .setDescription("The word to use for the counter.") - .setRequired(true) - ) - .addNumberOption((option) => - option - .setName("start") - .setDescription("The starting value of the counter.") - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); - const { options, guild } = interaction; - - const discordChannel = options?.getChannel("channel"); - const triggerWord = options?.getString("word"); - const startValue = options?.getNumber("start"); - - if (!guild) throw new Error("We could not find a guild"); - if (!discordChannel) throw new Error("We could not find a channel"); - if (!triggerWord) throw new Error("We could not find a word"); - - const channelCounter = await prisma.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: discordChannel.id, - }, - }, - }); - - if (channelCounter) - throw new Error("A counter already exists for this channel."); - - const createGuildCounter = await prisma.guildCounter.upsert({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: discordChannel.id, - }, - }, - update: {}, - create: { - channelId: discordChannel.id, - triggerWord, - count: startValue || 0, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - }); - - logger.silly(createGuildCounter); - - if (createGuildCounter) { - const embed = new EmbedBuilder() - .setTitle("[:toolbox:] Counters - Add") - .setTimestamp(new Date()) - .setFooter({ text: footerText, iconURL: footerIcon }); - - await interaction?.editReply({ - embeds: [ - embed - .setDescription(":white_check_mark: Counter created successfully.") - .setColor(successColor), - ], - }); - } - }, -}; diff --git a/src/commands/manage/modules/counters/modules/remove/index.ts b/src/commands/manage/modules/counters/modules/remove/index.ts deleted file mode 100644 index 8b542e6..0000000 --- a/src/commands/manage/modules/counters/modules/remove/index.ts +++ /dev/null @@ -1,82 +0,0 @@ -// Dependencies -// Models -import { - ChannelType, - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import deferReply from "../../../../../../handlers/deferReply"; -import checkPermission from "../../../../../../helpers/checkPermission"; -// Configurations -import prisma from "../../../../../../handlers/database"; -import getEmbedConfig from "../../../../../../helpers/getEmbedData"; - -// Function -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("remove") - .setDescription(`Delete a counter from your guild.`) - .addChannelOption((option) => - option - .setName("channel") - .setDescription("The channel to delete the counter from.") - .setRequired(true) - .addChannelTypes(ChannelType.GuildText) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); - const { options, guild } = interaction; - - const discordChannel = options?.getChannel("channel"); - - if (!guild) throw new Error("We could not find a guild"); - if (!discordChannel) throw new Error("We could not find a channel"); - - const embed = new EmbedBuilder() - .setTitle("[:toolbox:] Counters - Remove") - .setTimestamp(new Date()) - .setFooter({ text: footerText, iconURL: footerIcon }); - - const channelCounter = await prisma.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: discordChannel.id, - }, - }, - }); - - if (!channelCounter) - throw new Error( - "There is no counter sin this channel, please add one first." - ); - - const deleteGuildCounter = await prisma.guildCounter.deleteMany({ - where: { - guildId: guild.id, - channelId: discordChannel.id, - }, - }); - - if (!deleteGuildCounter) - throw new Error("We could not find a counter for this guild"); - - await interaction?.editReply({ - embeds: [ - embed - .setDescription(":white_check_mark: Counter deleted successfully.") - .setColor(successColor), - ], - }); - }, -}; diff --git a/src/commands/manage/modules/credits/index.ts b/src/commands/manage/modules/credits/index.ts deleted file mode 100644 index 4089408..0000000 --- a/src/commands/manage/modules/credits/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { - ChatInputCommandInteraction, - SlashCommandSubcommandGroupBuilder, -} from "discord.js"; - -// Modules -import moduleGive from "./modules/give"; -import moduleGiveaway from "./modules/giveaway"; -import moduleSet from "./modules/set"; -import moduleTake from "./modules/take"; -import moduleTransfer from "./modules/transfer"; - -export default { - builder: (group: SlashCommandSubcommandGroupBuilder) => { - return group - .setName("credits") - .setDescription("Manage the credits of a user.") - .addSubcommand(moduleGive.builder) - .addSubcommand(moduleSet.builder) - .addSubcommand(moduleTake.builder) - .addSubcommand(moduleTransfer.builder) - .addSubcommand(moduleGiveaway.builder); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - switch (interaction.options.getSubcommand()) { - case "give": - await moduleGive.execute(interaction); - break; - case "set": - await moduleSet.execute(interaction); - break; - case "take": - await moduleTake.execute(interaction); - break; - case "transfer": - await moduleTransfer.execute(interaction); - break; - case "giveaway": - await moduleGiveaway.execute(interaction); - break; - default: - throw new Error("No module found for that specific command"); - } - }, -}; diff --git a/src/commands/manage/modules/credits/modules/give/index.ts b/src/commands/manage/modules/credits/modules/give/index.ts deleted file mode 100644 index 61ad2ef..0000000 --- a/src/commands/manage/modules/credits/modules/give/index.ts +++ /dev/null @@ -1,72 +0,0 @@ -// Dependencies -import { - ChatInputCommandInteraction, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -// Configurations -// Helpers../../../../../../../helpers/userData -import pluralize from "../../../../../../helpers/pluralize"; -// Models -// Handlers -import deferReply from "../../../../../../handlers/deferReply"; -import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds"; -import checkPermission from "../../../../../../helpers/checkPermission"; -import creditsGive from "../../../../../../helpers/credits/give"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("give") - .setDescription("Give credits to a user.") - .addUserOption((option) => - option - .setName("user") - .setDescription("The user to give credits to.") - .setRequired(true) - ) - .addIntegerOption((option) => - option - .setName("amount") - .setDescription(`The amount of credits to give.`) - .setRequired(true) - ); - }, - - execute: async (interaction: ChatInputCommandInteraction) => { - // 1. Defer reply as ephemeral. - await deferReply(interaction, true); - - // 2. Check if the user has the MANAGE_GUILD permission. - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - // 3. Destructure interaction object. - const { guild, options } = interaction; - if (!guild) - throw new Error("We could not get the current guild from discord."); - if (!options) throw new Error("We could not get the options from discord."); - - // 4. Get the user and amount from the options. - const discordReceiver = options.getUser("user"); - const creditsAmount = options.getInteger("amount"); - if (typeof creditsAmount !== "number") - throw new Error("You need to provide a credit amount."); - if (!discordReceiver) - throw new Error("We could not get the receiving user from Discord"); - - // 5. Create base embeds. - const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Give"); - - // 6. Give the credits. - await creditsGive(guild, discordReceiver, creditsAmount); - - // 7. Send embed. - return await interaction.editReply({ - embeds: [ - embedSuccess.setDescription( - `Successfully gave ${pluralize(creditsAmount, "credit")}` - ), - ], - }); - }, -}; diff --git a/src/commands/manage/modules/credits/modules/giveaway/index.ts b/src/commands/manage/modules/credits/modules/giveaway/index.ts deleted file mode 100644 index 15a5c83..0000000 --- a/src/commands/manage/modules/credits/modules/giveaway/index.ts +++ /dev/null @@ -1,189 +0,0 @@ -// Dependencies -import axios from "axios"; -import { - ActionRowBuilder, - ButtonBuilder, - ButtonStyle, - ChannelType, - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import { v4 as uuidv4 } from "uuid"; -import encryption from "../../../../../../helpers/encryption"; -// Configurations -import prisma from "../../../../../../handlers/database"; -import deferReply from "../../../../../../handlers/deferReply"; -import checkPermission from "../../../../../../helpers/checkPermission"; -import getEmbedConfig from "../../../../../../helpers/getEmbedData"; -import logger from "../../../../../../middlewares/logger"; - -// Function -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("giveaway") - .setDescription("Giveaway some credits for specified amount of users.") - .addIntegerOption((option) => - option - .setName("uses") - .setDescription("How many users should be able to use this.") - .setRequired(true) - ) - .addIntegerOption((option) => - option - .setName("credit") - .setDescription(`How much credits provided per use.`) - .setRequired(true) - ) - .addChannelOption((option) => - option - .setName("channel") - .setDescription("The channel to send the message to.") - .setRequired(true) - .addChannelTypes(ChannelType.GuildText) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); // Destructure - const { guild, user, options } = interaction; - - const uses = options?.getInteger("uses"); - const creditAmount = options?.getInteger("credit"); - const channel = options?.getChannel("channel"); - - if (!uses) throw new Error("Amount of uses is required."); - if (!creditAmount) throw new Error("Amount of credits is required."); - if (!channel) throw new Error("Channel is required."); - if (!guild) throw new Error("Guild is required."); - - const embed = new EmbedBuilder() - .setTitle("[:toolbox:] Giveaway") - .setFooter({ text: footerText, iconURL: footerIcon }); - - const code = uuidv4(); - - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - - logger.silly(createGuildMember); - - if ( - !createGuildMember.guild.apiCpggUrlIv || - !createGuildMember.guild.apiCpggUrlContent - ) - throw new Error("No API url available"); - - if ( - !createGuildMember.guild.apiCpggTokenIv || - !createGuildMember.guild.apiCpggTokenContent - ) - throw new Error("No API token available"); - - const url = encryption.decrypt({ - iv: createGuildMember.guild.apiCpggUrlIv, - content: createGuildMember.guild.apiCpggUrlContent, - }); - const api = axios?.create({ - baseURL: `${url}/api/`, - headers: { - Authorization: `Bearer ${encryption.decrypt({ - iv: createGuildMember.guild.apiCpggTokenIv, - content: createGuildMember.guild.apiCpggTokenContent, - })}`, - }, - }); - - const shopUrl = `${url}/store`; - - await api - .post("vouchers", { - uses, - code, - credits: creditAmount, - memo: `[GIVEAWAY] ${interaction?.createdTimestamp} - ${interaction?.user?.id}`, - }) - .then(async () => { - await interaction.editReply({ - embeds: [ - embed - .setColor(successColor) - .setDescription(`Successfully created code: ${code}`), - ], - }); - - const buttons = new ActionRowBuilder().addComponents( - new ButtonBuilder() - .setLabel("Redeem it here") - .setStyle(ButtonStyle.Link) - .setEmoji("🏦") - .setURL(`${shopUrl}?voucher=${code}`) - ); - - const discordChannel = guild?.channels.cache.get(channel.id); - - if (!discordChannel) return; - - if (discordChannel.type !== ChannelType.GuildText) return; - - discordChannel.send({ - embeds: [ - new EmbedBuilder() - .setTitle("[:parachute:] Credits!") - .addFields([ - { - name: "💶 Credits", - value: `${creditAmount}`, - inline: true, - }, - ]) - .setDescription( - `${interaction.user} dropped a voucher for a maximum **${uses}** members!` - ) - .setColor(successColor), - ], - components: [buttons], - }); - }); - }, -}; diff --git a/src/commands/manage/modules/credits/modules/set/index.ts b/src/commands/manage/modules/credits/modules/set/index.ts deleted file mode 100644 index a69509b..0000000 --- a/src/commands/manage/modules/credits/modules/set/index.ts +++ /dev/null @@ -1,66 +0,0 @@ -// Dependencies -// Helpers -// Models -import { - ChatInputCommandInteraction, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; - -import deferReply from "../../../../../../handlers/deferReply"; -import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds"; -import checkPermission from "../../../../../../helpers/checkPermission"; -import creditsSet from "../../../../../../helpers/credits/set"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("set") - .setDescription("Set the amount of credits a user has.") - .addUserOption((option) => - option - .setName("user") - .setDescription("The user to set the amount of credits for.") - .setRequired(true) - ) - .addIntegerOption((option) => - option - .setName("amount") - .setDescription(`The amount of credits to set.`) - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - // 1. Defer reply as ephemeral. - await deferReply(interaction, true); - - // 2. Check if the user has the permission to manage the guild. - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - // 3. Destructure interaction object. - const { options, guild } = interaction; - if (!guild) throw new Error(`We could not find this guild.`); - if (!options) throw new Error(`We could not find the options.`); - - // 4. Get the user and amount from the options. - const discordUser = options.getUser("user"); - const creditAmount = options.getInteger("amount"); - if (typeof creditAmount !== "number") throw new Error("Amount is not set."); - if (!discordUser) throw new Error("User is not specified"); - - // 5. Set the credits. - await creditsSet(guild, discordUser, creditAmount); - - // 6. Create base embeds. - const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Set"); - - // 7. Send embed. - return await interaction.editReply({ - embeds: [ - embedSuccess.setDescription( - `Set **${discordUser}**'s credits to **${creditAmount}**.` - ), - ], - }); - }, -}; diff --git a/src/commands/manage/modules/credits/modules/take/index.ts b/src/commands/manage/modules/credits/modules/take/index.ts deleted file mode 100644 index 9ea9eba..0000000 --- a/src/commands/manage/modules/credits/modules/take/index.ts +++ /dev/null @@ -1,66 +0,0 @@ -// Dependencies -// Models -import { - ChatInputCommandInteraction, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; - -import deferReply from "../../../../../../handlers/deferReply"; -import { success as baseEmbedSuccess } from "../../../../../../helpers/baseEmbeds"; -import checkPermission from "../../../../../../helpers/checkPermission"; -import creditsTake from "../../../../../../helpers/credits/take"; -import pluralize from "../../../../../../helpers/pluralize"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("take") - .setDescription("Take credits from a user.") - .addUserOption((option) => - option - .setName("user") - .setDescription("The user to take credits from.") - .setRequired(true) - ) - .addIntegerOption((option) => - option - .setName("amount") - .setDescription(`The amount of credits to take.`) - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - // 1. Defer reply as ephemeral. - await deferReply(interaction, true); - - // 2. Check if the user has the MANAGE_GUILD permission. - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - // 3. Destructure interaction object. - const { guild, options } = interaction; - if (!guild) throw new Error("Invalid guild."); - if (!options) throw new Error("Invalid options."); - - // 4. Get the user and amount from the options. - const discordReceiver = options.getUser("user"); - const optionAmount = options.getInteger("amount"); - if (typeof optionAmount !== "number") throw new Error("Invalid amount."); - if (!discordReceiver) throw new Error("Invalid user."); - - // 5. Create base embeds. - const embedSuccess = await baseEmbedSuccess(guild, "[:toolbox:] Take"); - - // 6. Take the credits. - await creditsTake(guild, discordReceiver, optionAmount); - - // 7. Send embed. - return await interaction.editReply({ - embeds: [ - embedSuccess.setDescription( - `Took ${pluralize(optionAmount, "credit")} from ${discordReceiver}.` - ), - ], - }); - }, -}; diff --git a/src/commands/manage/modules/credits/modules/transfer/index.ts b/src/commands/manage/modules/credits/modules/transfer/index.ts deleted file mode 100644 index c140f52..0000000 --- a/src/commands/manage/modules/credits/modules/transfer/index.ts +++ /dev/null @@ -1,81 +0,0 @@ -// Dependencies -// Models -import { - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import creditsTransfer from "../../../../../../helpers/credits/transfer"; -// Configurations -import deferReply from "../../../../../../handlers/deferReply"; -import checkPermission from "../../../../../../helpers/checkPermission"; -import getEmbedConfig from "../../../../../../helpers/getEmbedData"; - -// Function -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("transfer") - .setDescription("Transfer credits from one user to another.") - .addUserOption((option) => - option - .setName("from") - .setDescription("The user to transfer credits from.") - .setRequired(true) - ) - .addUserOption((option) => - option - .setName("to") - .setDescription("The user to transfer credits to.") - .setRequired(true) - ) - .addIntegerOption((option) => - option - .setName("amount") - .setDescription(`The amount of credits to transfer.`) - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); // Destructure member - const { guild, options } = interaction; - - // Get options - const optionFromUser = options?.getUser("from"); - const optionToUser = options?.getUser("to"); - const optionAmount = options?.getInteger("amount"); - - if (optionAmount === null) throw new Error("Amount is not specified"); - - if (optionAmount <= 0) - throw new Error("You need to set amount above zero to transfer."); - - if (!guild) throw new Error(`We could not find this guild.`); - - if (!optionFromUser) - throw new Error("You must provide a user to transfer from."); - - if (!optionToUser) - throw new Error("You must provide a user to transfer to."); - - await creditsTransfer(guild, optionFromUser, optionToUser, optionAmount); - - return interaction?.editReply({ - embeds: [ - new EmbedBuilder() - .setTitle("[:toolbox:] Manage - Credits (Transfer)") - .setDescription(`Transferred ${optionAmount} credits.`) - .setTimestamp(new Date()) - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }), - ], - }); - }, -}; diff --git a/src/commands/moderation/index.ts b/src/commands/moderation/index.ts index 263f900..72bc10e 100644 --- a/src/commands/moderation/index.ts +++ b/src/commands/moderation/index.ts @@ -1,26 +1,21 @@ import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; +import { + SubcommandHandlers, + executeSubcommand, +} from "../../handlers/executeSubcommand"; -// Modules -import modulePrune from "./modules/prune"; +import * as prune from "./subcommands/prune"; + +const subcommandHandlers: SubcommandHandlers = { + prune: prune.execute, +}; export const builder = new SlashCommandBuilder() .setName("moderation") .setDescription("Moderation.") .setDMPermission(false) + .addSubcommand(prune.builder); - .addSubcommand(modulePrune.builder); - -// Execute the command export const execute = async (interaction: ChatInputCommandInteraction) => { - switch (interaction.options.getSubcommand()) { - case "prune": { - await modulePrune.execute(interaction); - break; - } - default: { - throw new Error( - `Unknown subcommand: ${interaction.options.getSubcommand()}` - ); - } - } + await executeSubcommand(interaction, subcommandHandlers); }; diff --git a/src/commands/moderation/modules/prune/index.ts b/src/commands/moderation/modules/prune/index.ts deleted file mode 100644 index e244a22..0000000 --- a/src/commands/moderation/modules/prune/index.ts +++ /dev/null @@ -1,85 +0,0 @@ -// Dependencies -import { - ChannelType, - ChatInputCommandInteraction, - EmbedBuilder, - PermissionsBitField, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import deferReply from "../../../../handlers/deferReply"; -import checkPermission from "../../../../helpers/checkPermission"; -// Configurations -import getEmbedConfig from "../../../../helpers/getEmbedData"; - -// Function -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("prune") - .setDescription("Prune messages!") - .addIntegerOption((option) => - option - .setName("count") - .setDescription("How many messages you want to prune.") - .setRequired(true) - ) - .addBooleanOption((option) => - option.setName("bots").setDescription("Include bots.") - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, false); - - checkPermission(interaction, PermissionsBitField.Flags.ManageMessages); - - const { errorColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); - - const count = interaction.options.getInteger("count"); - if (count === null) return; - const bots = interaction.options.getBoolean("bots"); - - if (count < 1 || count > 100) { - const interactionEmbed = new EmbedBuilder() - .setTitle("[:police_car:] Prune") - .setDescription(`You can only prune between 1 and 100 messages.`) - .setTimestamp() - .setColor(errorColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - - await interaction.editReply({ - embeds: [interactionEmbed], - }); - return; - } - - if (interaction?.channel?.type !== ChannelType.GuildText) return; - await interaction.channel.messages.fetch().then(async (messages) => { - const messagesToDelete = ( - bots - ? messages.filter((m) => m?.interaction?.id !== interaction.id) - : messages.filter( - (m) => - m?.interaction?.id !== interaction.id && m?.author?.bot !== true - ) - ).first(count); - - if (interaction?.channel?.type !== ChannelType.GuildText) return; - await interaction.channel - .bulkDelete(messagesToDelete, true) - .then(async () => { - const interactionEmbed = new EmbedBuilder() - .setTitle("[:police_car:] Prune") - .setDescription(`Successfully pruned \`${count}\` messages.`) - .setTimestamp() - .setColor(errorColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - - await interaction.editReply({ - embeds: [interactionEmbed], - }); - }); - }); - }, -}; diff --git a/src/commands/moderation/subcommands/prune/index.ts b/src/commands/moderation/subcommands/prune/index.ts new file mode 100644 index 0000000..db112d7 --- /dev/null +++ b/src/commands/moderation/subcommands/prune/index.ts @@ -0,0 +1,86 @@ +// Dependencies +import { + ChannelType, + ChatInputCommandInteraction, + EmbedBuilder, + PermissionsBitField, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import checkPermission from "../../../../utils/checkPermission"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; + +// Function +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("prune") + .setDescription("Prune messages!") + .addIntegerOption((option) => + option + .setName("count") + .setDescription("How many messages you wish to prune") + .setRequired(true) + .setMinValue(1) + .setMaxValue(99) + ) + .addBooleanOption((option) => + option + .setName("bots") + .setDescription("Should bot messages be pruned too?") + ); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + const { user, options, channel } = interaction; + if (!channel) { + throw new Error("The bot failed to find the channel to prune messages in."); + } + + await deferReply(interaction, false); + checkPermission(interaction, PermissionsBitField.Flags.ManageMessages); + + const count = options.getInteger("count"); + const bots = options.getBoolean("bots"); + if (!count || count < 1 || count > 99) { + throw new Error( + "Please provide a number between 1 and 99 for the prune command." + ); + } + + if (channel.type !== ChannelType.GuildText) return; + + const messagesToDelete = await channel.messages + .fetch({ limit: count + 1 }) // Fetch count + 1 messages to exclude the interaction message itself + .then((messages) => { + let filteredMessages = messages; + if (!bots) { + filteredMessages = filteredMessages.filter( + (message) => !message.author.bot + ); + } + return filteredMessages; + }); + + const firstMessage = messagesToDelete.first(); + if (firstMessage) messagesToDelete.delete(firstMessage.id); + + const messagesToDeleteArray = [...messagesToDelete.values()]; // Convert Collection to an array + + await channel.bulkDelete(messagesToDeleteArray, true).then(async () => { + const interactionEmbed = new EmbedBuilder() + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setAuthor({ name: "🤖 Moderation" }) + .setDescription( + `Successfully deleted ${messagesToDeleteArray.length} messages.` + ) + .setFooter({ + text: `Action by ${user.username}`, + iconURL: user.displayAvatarURL(), + }) + .setTimestamp(); + + await sendResponse(interaction, { + embeds: [interactionEmbed], + }); + }); +}; diff --git a/src/commands/reputation/index.ts b/src/commands/reputation/index.ts index 25291e1..8c02645 100644 --- a/src/commands/reputation/index.ts +++ b/src/commands/reputation/index.ts @@ -1,28 +1,26 @@ -// Dependencies import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; +import { + SubcommandHandlers, + executeSubcommand, +} from "../../handlers/executeSubcommand"; -// Modules -import moduleCheck from "./modules/check"; -import moduleRepute from "./modules/repute"; +import * as check from "./subcommands/check"; +import * as repute from "./subcommands/repute"; + +const subcommandHandlers: SubcommandHandlers = { + repute: repute.execute, + check: check.execute, +}; -// Function export const builder = new SlashCommandBuilder() .setName("reputation") - .setDescription("See and repute users to show other how trustworthy they are") + .setDescription( + "See and give reputation to users to show others how trustworthy they are" + ) .setDMPermission(false) + .addSubcommand(repute.builder) + .addSubcommand(check.builder); - // Modules - .addSubcommand(moduleRepute.builder) - .addSubcommand(moduleCheck.builder); - -// Execute function export const execute = async (interaction: ChatInputCommandInteraction) => { - if (interaction.options.getSubcommand() === "repute") { - await moduleRepute.execute(interaction); - return; - } - if (interaction.options.getSubcommand() === "check") { - await moduleCheck.execute(interaction); - return; - } + await executeSubcommand(interaction, subcommandHandlers); }; diff --git a/src/commands/reputation/modules/check/index.ts b/src/commands/reputation/modules/check/index.ts deleted file mode 100644 index 1e6008f..0000000 --- a/src/commands/reputation/modules/check/index.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { - ChatInputCommandInteraction, - EmbedBuilder, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import getEmbedConfig from "../../../../helpers/getEmbedData"; -import logger from "../../../../middlewares/logger"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("check") - .setDescription("Check reputation") - .addUserOption((option) => - option - .setName("account") - .setDescription("The account you checking") - .setRequired(false) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - const { options, guild, user } = interaction; - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - guild - ); - - const optionAccount = options?.getUser("account"); - - if (!guild) throw new Error("Server unavailable"); - if (!user) throw new Error("User unavailable"); - - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: (optionAccount || user).id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: (optionAccount || user).id, - }, - where: { - id: (optionAccount || user).id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - - logger.silly(createGuildMember); - - const reputationType = (reputation: number) => { - if (reputation < 0) return `negative reputation of ${reputation}`; - if (reputation > 0) return `positive reputation of ${reputation}`; - return "neutral reputation"; - }; - - const interactionEmbed = new EmbedBuilder() - .setTitle( - optionAccount - ? `:loudspeaker:︱Showing ${optionAccount.username}'s reputation` - : ":loudspeaker:︱Showing your reputation" - ) - .setDescription( - optionAccount - ? `${optionAccount} have a ${reputationType( - createGuildMember.user.reputationsEarned - )}` - : `You have a ${reputationType( - createGuildMember.user.reputationsEarned - )}` - ) - .setTimestamp() - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - - await interaction.editReply({ - embeds: [interactionEmbed], - }); - }, -}; diff --git a/src/commands/reputation/modules/repute/components/noSelfReputation.ts b/src/commands/reputation/modules/repute/components/noSelfReputation.ts deleted file mode 100644 index 9592215..0000000 --- a/src/commands/reputation/modules/repute/components/noSelfReputation.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { User } from "discord.js"; - -export default (to: User | null, from: User | null) => { - if (from?.id === to?.id) { - throw new Error("You can only repute other users"); - } -}; diff --git a/src/commands/reputation/modules/repute/index.ts b/src/commands/reputation/modules/repute/index.ts deleted file mode 100644 index 42dd7d9..0000000 --- a/src/commands/reputation/modules/repute/index.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { - ChatInputCommandInteraction, - EmbedBuilder, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import getEmbedConfig from "../../../../helpers/getEmbedData"; -import logger from "../../../../middlewares/logger"; -import noSelfReputation from "./components/noSelfReputation"; - -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import cooldown from "../../../../middlewares/cooldown"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("repute") - .setDescription("Repute an account") - .addUserOption((option) => - option - .setName("account") - .setDescription("The account you repute") - .setRequired(true) - ) - .addStringOption((option) => - option - .setName("type") - .setDescription("Type of reputation") - .setRequired(true) - .addChoices( - { name: "Positive", value: "positive" }, - { - name: "Negative", - value: "negative", - } - ) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - const { options, user, guild, commandId } = interaction; - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - guild - ); - - const optionAccount = options?.getUser("account"); - const optionType = options?.getString("type"); - - if (!guild) throw new Error("Server unavailable"); - if (!optionAccount) throw new Error("User unavailable"); - - // Pre-checks - noSelfReputation(optionAccount, user); - - // Check if user is on cooldown otherwise create one - await cooldown( - guild, - user, - commandId, - parseInt(process.env.REPUTATION_TIMEOUT) - ); - - switch (optionType) { - case "positive": { - const createUser = await prisma.user.upsert({ - where: { - id: optionAccount.id, - }, - update: { - reputationsEarned: { - increment: 1, - }, - }, - create: { - id: optionAccount.id, - reputationsEarned: 1, - }, - }); - - logger.silly(createUser); - break; - } - case "negative": { - const createUser = await prisma.user.upsert({ - where: { - id: optionAccount.id, - }, - update: { - reputationsEarned: { - decrement: 1, - }, - }, - create: { - id: optionAccount.id, - reputationsEarned: -1, - }, - }); - - logger.silly(createUser); - break; - } - default: { - throw new Error("Invalid reputation type"); - } - } - - const interactionEmbed = new EmbedBuilder() - .setTitle(`:loudspeaker:︱Reputing ${optionAccount.username}`) - .setDescription( - `You have given a ${optionType} repute to ${optionAccount}!` - ) - .setTimestamp() - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - - await interaction.editReply({ - embeds: [interactionEmbed], - }); - }, -}; diff --git a/src/commands/reputation/subcommands/check/index.ts b/src/commands/reputation/subcommands/check/index.ts new file mode 100644 index 0000000..6259da8 --- /dev/null +++ b/src/commands/reputation/subcommands/check/index.ts @@ -0,0 +1,57 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import ReputationManager from "../../../../handlers/ReputationManager"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; + +const reputationManager = new ReputationManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("check") + .setDescription("Check reputation") + .addUserOption((option) => + option + .setName("user") + .setDescription("The user you are checking") + .setRequired(false) + ); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + await deferReply(interaction, false); + + const { options, user } = interaction; + + const checkUser = options.getUser("user") || user; + + if (!user) throw new Error("User unavailable"); + + const userReputation = await reputationManager.check(checkUser); + + const interactionEmbed = new EmbedBuilder() + .setAuthor({ + name: `Showing ${checkUser.username}'s reputation`, + }) + .setDescription( + `**User:** ${checkUser}\n\n` + + `**Reputation:**\n` + + `- Negative: ${userReputation.negative}\n` + + `- Positive: ${userReputation.positive}\n` + + `- Total: ${userReputation.total}` + ) + .setFooter({ + text: `Requested by ${user.username}`, + iconURL: user.displayAvatarURL(), + }) + .setThumbnail(checkUser.displayAvatarURL()) + .setTimestamp() + .setColor(process.env.EMBED_COLOR_SUCCESS); + + await sendResponse(interaction, { + embeds: [interactionEmbed], + }); +}; diff --git a/src/commands/reputation/subcommands/repute/index.ts b/src/commands/reputation/subcommands/repute/index.ts new file mode 100644 index 0000000..180c6c3 --- /dev/null +++ b/src/commands/reputation/subcommands/repute/index.ts @@ -0,0 +1,87 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import CooldownManager from "../../../../handlers/CooldownManager"; +import ReputationManager from "../../../../handlers/ReputationManager"; +import generateCooldownName from "../../../../helpers/generateCooldownName"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; + +const cooldownManager = new CooldownManager(); +const reputationManager = new ReputationManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("repute") + .setDescription("Repute a user") + .addUserOption((option) => + option + .setName("user") + .setDescription("The user you repute") + .setRequired(true) + ) + .addStringOption((option) => + option + .setName("type") + .setDescription("Type of reputation") + .setRequired(true) + .addChoices( + { name: "Positive", value: "positive" }, + { name: "Negative", value: "negative" } + ) + ); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + const { options, user, guild } = interaction; + await deferReply(interaction, true); + + if (!guild) { + throw new Error("This command can only be used in guilds"); + } + + const targetUser = options.getUser("user", true); + const reputationType = options.getString("type", true); + + if (!targetUser) { + throw new Error( + "Sorry, we were unable to find the user you are trying to give reputation to." + ); + } + + if (reputationType !== "positive" && reputationType !== "negative") { + throw new Error("Invalid reputation type"); + } + + if (user.id === targetUser.id) { + throw new Error("It is not possible to give yourself reputation."); + } + + await reputationManager.repute(targetUser, reputationType); + + const emoji = reputationType === "positive" ? "😊" : "😔"; + + const interactionMessage = `You have successfully given ${emoji} ${reputationType} reputation to ${targetUser}!`; + + const interactionEmbed = new EmbedBuilder() + .setAuthor({ + name: `Reputing ${targetUser.username}`, + iconURL: targetUser.displayAvatarURL(), + }) + .setDescription(interactionMessage) + .setTimestamp() + .setColor(process.env.EMBED_COLOR_SUCCESS); + + await sendResponse(interaction, { + embeds: [interactionEmbed], + }); + + await cooldownManager.setCooldown( + await generateCooldownName(interaction), + guild, + user, + 24 * 60 * 60 + ); +}; diff --git a/src/commands/settings/index.ts b/src/commands/settings/index.ts new file mode 100644 index 0000000..6b8f461 --- /dev/null +++ b/src/commands/settings/index.ts @@ -0,0 +1,24 @@ +import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; + +import { + SubcommandHandlers, + executeSubcommand, +} from "../../handlers/executeSubcommand"; +import * as credits from "./subcommands/credits"; +import * as ctrlpanel from "./subcommands/ctrlpanel"; + +const subcommandHandlers: SubcommandHandlers = { + ctrlpanel: ctrlpanel.execute, + credits: credits.execute, +}; + +export const builder = new SlashCommandBuilder() + .setName("settings") + .setDescription("Manage guild configurations.") + .setDMPermission(false) + .addSubcommand(ctrlpanel.builder) + .addSubcommand(credits.builder); + +export const execute = async (interaction: ChatInputCommandInteraction) => { + await executeSubcommand(interaction, subcommandHandlers); +}; diff --git a/src/commands/settings/subcommands/credits/index.ts b/src/commands/settings/subcommands/credits/index.ts new file mode 100644 index 0000000..aeda841 --- /dev/null +++ b/src/commands/settings/subcommands/credits/index.ts @@ -0,0 +1,110 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + PermissionsBitField, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import prisma from "../../../../handlers/prisma"; +import checkPermission from "../../../../utils/checkPermission"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("credits") + .setDescription(`Configure credits module`) + .addNumberOption((option) => + option + .setName("work-bonus-chance") + .setDescription("work-bonus-chance") + .setRequired(true) + .setMinValue(0) + .setMaxValue(100) + ) + .addNumberOption((option) => + option + .setName("work-penalty-chance") + .setDescription("work-penalty-chance") + .setRequired(true) + .setMinValue(0) + .setMaxValue(100) + ); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + await deferReply(interaction, true); + + checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + + const { guild, options, user } = interaction; + + const workBonusChance = options.getNumber("work-bonus-chance"); + const workPenaltyChance = options.getNumber("work-penalty-chance"); + + if (!guild) { + throw new Error("Guild not found."); + } + + if (typeof workBonusChance !== "number") { + throw new Error("Work Bonus Chance must be a number."); + } + + if (typeof workPenaltyChance !== "number") { + throw new Error("Work Penalty Chance must be a number."); + } + + const upsertGuildCreditsSettings = await prisma.guildCreditsSettings.upsert({ + where: { + id: guild.id, + }, + update: { + workBonusChance, + workPenaltyChance, + }, + create: { + id: guild.id, + workBonusChance, + workPenaltyChance, + guildSettings: { + connectOrCreate: { + where: { + id: guild.id, + }, + create: { + id: guild.id, + }, + }, + }, + }, + }); + + const embedSuccess = new EmbedBuilder() + .setAuthor({ + name: "Configuration of Credits", + }) + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setFooter({ + text: `Successfully configured by ${user.username}`, + iconURL: user.displayAvatarURL(), + }) + .setTimestamp(); + + await sendResponse(interaction, { + embeds: [ + embedSuccess + .setDescription("Configuration updated successfully!") + .addFields( + { + name: "Work Bonus Chance", + value: `${upsertGuildCreditsSettings.workBonusChance}`, + inline: true, + }, + { + name: "Work Penalty Chance", + value: `${upsertGuildCreditsSettings.workPenaltyChance}`, + inline: true, + } + ), + ], + }); +}; diff --git a/src/commands/settings/subcommands/ctrlpanel/index.ts b/src/commands/settings/subcommands/ctrlpanel/index.ts new file mode 100644 index 0000000..130b8b8 --- /dev/null +++ b/src/commands/settings/subcommands/ctrlpanel/index.ts @@ -0,0 +1,76 @@ +import { + ChatInputCommandInteraction, + EmbedBuilder, + PermissionsBitField, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import CtrlPanelAPI, { + CtrlPanelAPIError, +} from "../../../../services/CtrlPanelAPI"; +import checkPermission from "../../../../utils/checkPermission"; +import deferReply from "../../../../utils/deferReply"; +import logger from "../../../../utils/logger"; +import sendResponse from "../../../../utils/sendResponse"; + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("ctrlpanel") + .setDescription("Ctrlpanel.gg API") + .addStringOption((option) => + option + .setName("scheme") + .setDescription("API protocol") + .setRequired(true) + .addChoices( + { name: "HTTPS (secure)", value: "https" }, + { name: "HTTP (insecure)", value: "http" } + ) + ) + .addStringOption((option) => + option.setName("domain").setDescription("API domain").setRequired(true) + ) + .addStringOption((option) => + option.setName("token").setDescription("API Token").setRequired(true) + ); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + await deferReply(interaction, true); + + checkPermission(interaction, PermissionsBitField.Flags.ManageGuild); + + const { guild, options, user } = interaction; + if (!guild) throw new Error("Guild unavailable"); + + const scheme = options.getString("scheme", true); + const domain = options.getString("domain", true); + const tokenData = options.getString("token", true); + if (!scheme || !domain || !tokenData) + throw new Error("Scheme, domain, and token must be set"); + + const ctrlPanelAPI = new CtrlPanelAPI(guild); + + try { + await ctrlPanelAPI.updateApiCredentials(scheme, domain, tokenData); + + const embedSuccess = new EmbedBuilder() + .setAuthor({ + name: "Configuration of Ctrlpanel.gg", + iconURL: "https://ctrlpanel.gg/img/controlpanel.png", + }) + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setFooter({ + text: `Successfully configured by ${user.username}`, + iconURL: user.displayAvatarURL(), + }) + .setTimestamp() + .setDescription(`API Address: \`${scheme}://${domain}\``); + + await sendResponse(interaction, { embeds: [embedSuccess] }); + } catch (error: unknown) { + if (error instanceof CtrlPanelAPIError) { + logger.error("CtrlPanelAPI error:", error.message); + throw error; + } + } +}; diff --git a/src/commands/shop/index.ts b/src/commands/shop/index.ts index 0df13dd..6b84d99 100644 --- a/src/commands/shop/index.ts +++ b/src/commands/shop/index.ts @@ -1,41 +1,21 @@ -// Dependencies import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; +import * as ctrlpanel from "./subcommands/ctrlpanel"; -// Modules -import moduleCpgg from "./modules/cpgg"; -import moduleRoles from "./modules/roles"; +import { + SubcommandHandlers, + executeSubcommand, +} from "../../handlers/executeSubcommand"; + +const subcommandHandlers: SubcommandHandlers = { + ctrlpanel: ctrlpanel.execute, +}; -// Function export const builder = new SlashCommandBuilder() .setName("shop") - .setDescription("Shop for credits and custom roles.") + .setDescription("Guild shop") .setDMPermission(false) + .addSubcommand(ctrlpanel.builder); - // Modules - .addSubcommand(moduleCpgg.builder) - .addSubcommandGroup(moduleRoles.builder); - -// Execute the command export const execute = async (interaction: ChatInputCommandInteraction) => { - const { options } = interaction; - - switch (options.getSubcommand()) { - case "cpgg": { - await moduleCpgg.execute(interaction); - break; - } - default: { - throw new Error("Could not find module for that command."); - } - } - - switch (options.getSubcommandGroup()) { - case "roles": { - await moduleRoles.execute(interaction); - break; - } - default: { - throw new Error("Could not find module for that command."); - } - } + await executeSubcommand(interaction, subcommandHandlers); }; diff --git a/src/commands/shop/modules/cpgg/index.ts b/src/commands/shop/modules/cpgg/index.ts deleted file mode 100644 index 29600d3..0000000 --- a/src/commands/shop/modules/cpgg/index.ts +++ /dev/null @@ -1,195 +0,0 @@ -import axios from "axios"; -import { - ActionRowBuilder, - ButtonBuilder, - ButtonStyle, - ChatInputCommandInteraction, - EmbedBuilder, - Message, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import { v4 as uuidv4 } from "uuid"; -import prisma from "../../../../handlers/database"; -import deferReply from "../../../../handlers/deferReply"; -import encryption from "../../../../helpers/encryption"; -import getEmbedData from "../../../../helpers/getEmbedData"; -import logger from "../../../../middlewares/logger"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("cpgg") - .setDescription("Buy cpgg power.") - .addIntegerOption((option) => - option - .setName("amount") - .setDescription("How much credits you want to withdraw.") - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - const { errorColor, successColor, footerText, footerIcon } = - await getEmbedData(interaction.guild); - const { options, guild, user, client } = interaction; - const optionAmount = options?.getInteger("amount"); - if (optionAmount === null) { - logger?.silly(`Amount is null.`); - const interactionEmbed = new EmbedBuilder() - .setTitle("[:dollar:] Gift") - .setDescription("We could not read your requested amount.") - .setTimestamp() - .setColor(errorColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - return interaction?.editReply({ - embeds: [interactionEmbed], - }); - } - if (!guild) throw new Error("Guild not found"); - - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - - logger.silly(createGuildMember); - - const dmUser = client?.users?.cache?.get(user?.id); - - if ((optionAmount || createGuildMember.creditsEarned) < 100) - throw new Error("You can't withdraw to CPGG below 100 credits."); - - if ((optionAmount || createGuildMember.creditsEarned) > 1000000) - throw new Error("Amount or user credits is above 1.000.000."); - - if (createGuildMember.creditsEarned < optionAmount) - throw new Error("You can't withdraw more than you have on your account."); - - if ( - !createGuildMember.guild.apiCpggUrlIv || - !createGuildMember.guild.apiCpggUrlContent - ) - throw new Error("No API url available"); - - if ( - !createGuildMember.guild.apiCpggTokenIv || - !createGuildMember.guild.apiCpggTokenContent - ) - throw new Error("No API token available"); - - const code = uuidv4(); - const url = encryption.decrypt({ - iv: createGuildMember.guild.apiCpggUrlIv, - content: createGuildMember.guild.apiCpggUrlContent, - }); - const api = axios?.create({ - baseURL: `${url}/api/`, - headers: { - Authorization: `Bearer ${encryption.decrypt({ - iv: createGuildMember.guild.apiCpggTokenIv, - content: createGuildMember.guild.apiCpggTokenContent, - })}`, - }, - }); - const shopUrl = `${url}/store`; - const buttons = new ActionRowBuilder().addComponents( - new ButtonBuilder() - .setLabel("Redeem it here") - .setStyle(ButtonStyle.Link) - .setEmoji("🏦") - .setURL(`${shopUrl}?voucher=${code}`) - ); - await api - ?.post("vouchers", { - uses: 1, - code, - credits: optionAmount || createGuildMember.creditsEarned, - memo: `${interaction?.createdTimestamp} - ${interaction?.user?.id}`, - }) - ?.then(async () => { - logger?.silly(`Successfully created voucher.`); - createGuildMember.creditsEarned -= - optionAmount || createGuildMember.creditsEarned; - - const updateGuildMember = await prisma.guildMember.update({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - data: { - creditsEarned: { - decrement: optionAmount || createGuildMember.creditsEarned, - }, - }, - }); - - logger.silly(updateGuildMember); - - if (!interaction.guild) throw new Error("Guild is undefined"); - const dmEmbed = new EmbedBuilder() - .setTitle("[:shopping_cart:] CPGG") - .setDescription( - `This voucher comes from **${interaction.guild.name}**.` - ) - .setTimestamp() - .addFields({ - name: "💶 Credits", - value: `${optionAmount || createGuildMember.creditsEarned}`, - inline: true, - }) - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - await dmUser - ?.send({ - embeds: [dmEmbed], - components: [buttons], - }) - .then(async (msg: Message) => { - const interactionEmbed = new EmbedBuilder() - .setTitle("[:shopping_cart:] CPGG") - .setDescription(`I have sent you the code in [DM](${msg.url})!`) - .setTimestamp() - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - await interaction?.editReply({ - embeds: [interactionEmbed], - }); - }); - }); - return true; - }, -}; diff --git a/src/commands/shop/modules/roles/index.ts b/src/commands/shop/modules/roles/index.ts deleted file mode 100644 index 329c08f..0000000 --- a/src/commands/shop/modules/roles/index.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Dependencies -import { - ChatInputCommandInteraction, - SlashCommandSubcommandGroupBuilder, -} from "discord.js"; - -// Handlers - -// Modules -import moduleBuy from "./modules/buy"; -import moduleCancel from "./modules/cancel"; - -import prisma from "../../../../handlers/database"; - -export default { - builder: (group: SlashCommandSubcommandGroupBuilder) => { - return ( - group - .setName("roles") - .setDescription("Shop for custom roles.") - - // Modules - .addSubcommand(moduleBuy.builder) - .addSubcommand(moduleCancel.builder) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - if (!interaction.guild) return; - const { options, guild } = interaction; - - const getGuild = await prisma.guild.findUnique({ - where: { id: guild.id }, - }); - if (!getGuild) throw new Error("Guild not found"); - - if (!getGuild.shopRolesEnabled) - throw new Error("This server has disabled shop roles."); - - if (options?.getSubcommand() === "buy") { - await moduleBuy.execute(interaction); - } - - if (options?.getSubcommand() === "cancel") { - await moduleCancel.execute(interaction); - } - }, -}; diff --git a/src/commands/shop/modules/roles/modules/buy/index.ts b/src/commands/shop/modules/roles/modules/buy/index.ts deleted file mode 100644 index 5844ed4..0000000 --- a/src/commands/shop/modules/roles/modules/buy/index.ts +++ /dev/null @@ -1,178 +0,0 @@ -// Dependencies -// Helpers -import { - ChatInputCommandInteraction, - ColorResolvable, - EmbedBuilder, - GuildMemberRoleManager, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import deferReply from "../../../../../../handlers/deferReply"; -import getEmbedData from "../../../../../../helpers/getEmbedData"; -import logger from "../../../../../../middlewares/logger"; -// Configurations -// import fetchUser from "../../../../../../helpers/userData"; -// Models - -import prisma from "../../../../../../handlers/database"; -import pluralize from "../../../../../../helpers/pluralize"; - -// Function -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("buy") - .setDescription("Buy a custom role.") - .addStringOption((option) => - option - .setName("name") - .setDescription("Name of the role you wish to buy.") - .setRequired(true) - ) - .addStringOption((option) => - option - .setName("color") - .setDescription("Color of the role you wish to buy.") - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - const { successColor, footerText, footerIcon } = await getEmbedData( - interaction.guild - ); - const { options, guild, user, member } = interaction; - const optionName = options?.getString("name"); - const optionColor = options?.getString("color"); - // If amount is null - if (optionName === null) - throw new Error("We could not read your requested name"); - await guild?.roles - .create({ - name: optionName, - color: optionColor as ColorResolvable, - reason: `${user?.id} bought from shop`, - }) - .then(async (role) => { - const userId = "SNOWFLKAE"; - const guildId = "SNOWFLAKE"; - - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId, - guildId, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: userId, - }, - where: { - id: userId, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guildId, - }, - where: { - id: guildId, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - - logger.silly(createGuildMember); - - // Get guild object - const pricePerHour = createGuildMember.guild.shopRolesPricePerHour; - - const updateGuildMember = await prisma.guildMember.update({ - where: { - userId_guildId: { - userId, - guildId, - }, - }, - data: { - creditsEarned: { decrement: pricePerHour }, - }, - }); - - logger.silly(updateGuildMember); - - const createShopRole = await prisma.guildShopRoles.upsert({ - where: { - guildId_userId_roleId: { - guildId: guild.id, - userId: user.id, - roleId: role.id, - }, - }, - update: {}, - create: { - roleId: role.id, - lastPayed: new Date(), - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - - logger.silly(createShopRole); - - await (member?.roles as GuildMemberRoleManager)?.add(role?.id); - logger?.silly(`Role ${role?.name} was bought by ${user?.tag}`); - const interactionEmbed = new EmbedBuilder() - .setTitle("[:shopping_cart:] Buy") - .setDescription( - `You bought **${optionName}** for **${pluralize( - pricePerHour, - "credit" - )}**.` - ) - .setTimestamp() - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); - return interaction?.editReply({ - embeds: [interactionEmbed], - }); - }) - .catch(() => { - throw new Error("Failed creating role."); - }); - }, -}; diff --git a/src/commands/shop/modules/roles/modules/cancel/index.ts b/src/commands/shop/modules/roles/modules/cancel/index.ts deleted file mode 100644 index e4b96b5..0000000 --- a/src/commands/shop/modules/roles/modules/cancel/index.ts +++ /dev/null @@ -1,127 +0,0 @@ -// Dependencies -// Helpers -import { - ChatInputCommandInteraction, - EmbedBuilder, - GuildMemberRoleManager, - SlashCommandSubcommandBuilder, -} from "discord.js"; -// Configurations -// Models -import deferReply from "../../../../../../handlers/deferReply"; -import logger from "../../../../../../middlewares/logger"; -// Configurations -// Models - -import prisma from "../../../../../../handlers/database"; -import getEmbedData from "../../../../../../helpers/getEmbedData"; -import pluralize from "../../../../../../helpers/pluralize"; - -// Function -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("cancel") - .setDescription("Cancel a purchase.") - .addRoleOption((option) => - option - .setName("role") - .setDescription("Role you wish to cancel.") - .setRequired(true) - ); - }, - execute: async (interaction: ChatInputCommandInteraction) => { - await deferReply(interaction, true); - - const { successColor, footerText, footerIcon } = await getEmbedData( - interaction.guild - ); - const { options, guild, user, member } = interaction; - const optionRole = options.getRole("role"); - if (optionRole === null) - throw new Error("We could not read your requested role."); - if (!guild) throw new Error("No guild specified"); - if (!user) throw new Error("No user specified"); - - const roleExist = await prisma.guildShopRoles.findUnique({ - where: { - guildId_userId_roleId: { - guildId: guild.id, - userId: user.id, - roleId: optionRole.id, - }, - }, - }); - if (roleExist === null) return; - await (member?.roles as GuildMemberRoleManager)?.remove(optionRole?.id); - await guild?.roles - .delete(optionRole?.id, `${user?.id} canceled from shop`) - .then(async () => { - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - - logger.silly(createGuildMember); - - if (!createGuildMember) throw new Error("Guild member not created"); - - const deleteShopRole = await prisma.guildShopRoles.delete({ - where: { - guildId_userId_roleId: { - guildId: guild?.id, - userId: user?.id, - roleId: optionRole?.id, - }, - }, - }); - - logger.silly(deleteShopRole); - - const interactionEmbed = new EmbedBuilder() - .setTitle("[:shopping_cart:] Cancel") - .setDescription(`You have canceled ${optionRole.name}.`) - .setTimestamp() - .setColor(successColor) - .addFields({ - name: "Your balance", - value: `${pluralize(createGuildMember.creditsEarned, "credit")}`, - }) - .setFooter({ text: footerText, iconURL: footerIcon }); - return interaction?.editReply({ - embeds: [interactionEmbed], - }); - }); - }, -}; diff --git a/src/commands/shop/subcommands/ctrlpanel.ts b/src/commands/shop/subcommands/ctrlpanel.ts new file mode 100644 index 0000000..e454483 --- /dev/null +++ b/src/commands/shop/subcommands/ctrlpanel.ts @@ -0,0 +1,85 @@ +import { + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + ChatInputCommandInteraction, + EmbedBuilder, + Message, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import { v4 as uuidv4 } from "uuid"; +import CreditsManager from "../../../handlers/CreditsManager"; +import CtrlPanelAPI from "../../../services/CtrlPanelAPI"; +import deferReply from "../../../utils/deferReply"; +import sendResponse from "../../../utils/sendResponse"; + +const creditsManager = new CreditsManager(); + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("ctrlpanel") + .setDescription("Buy cpgg power.") + .addIntegerOption((option) => + option + .setName("withdraw") + .setDescription("How much credits you want to withdraw.") + .setRequired(true) + .setMinValue(100) + .setMaxValue(999999) + ); +}; + +export const execute = async (interaction: ChatInputCommandInteraction) => { + await deferReply(interaction, true); + + const { options, guild, user, client } = interaction; + if (!guild) throw new Error("This command can only be executed in a guild"); + + const ctrlPanelAPI = new CtrlPanelAPI(guild); + + const withdrawalAmount = options.getInteger("withdraw", true); + + await creditsManager.take(guild, user, withdrawalAmount); + + const voucherCode = uuidv4(); + const { redeemUrl } = await ctrlPanelAPI.generateVoucher( + voucherCode, + withdrawalAmount, + 1 + ); + + const userDM = await client.users.fetch(user.id); + const dmEmbed = new EmbedBuilder() + .setTitle(":shopping_cart:︱CPGG") + .setDescription(`This voucher was generated in guild: **${guild.name}**.`) + .setTimestamp() + .addFields({ + name: "💶 Credits", + value: `${withdrawalAmount}`, + inline: true, + }) + .setColor(process.env.EMBED_COLOR_SUCCESS); + + const redemptionButton = new ButtonBuilder() + .setLabel("Redeem it here") + .setStyle(ButtonStyle.Link) + .setEmoji("🏦") + .setURL(redeemUrl); + + const actionRow = new ActionRowBuilder().addComponents( + redemptionButton + ); + + const dmMessage: Message = await userDM.send({ + embeds: [dmEmbed], + components: [actionRow], + }); + + const interactionEmbed = new EmbedBuilder() + .setTitle(":shopping_cart:︱CPGG") + .setDescription(`I have sent you the code in [DM](${dmMessage.url})!`) + .setTimestamp() + .setColor(process.env.EMBED_COLOR_SUCCESS); + + await sendResponse(interaction, { embeds: [interactionEmbed] }); +}; diff --git a/src/commands/utils/index.ts b/src/commands/utils/index.ts index 4bce106..d2f3aa8 100644 --- a/src/commands/utils/index.ts +++ b/src/commands/utils/index.ts @@ -1,29 +1,22 @@ import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"; +import { + SubcommandHandlers, + executeSubcommand, +} from "../../handlers/executeSubcommand"; +import * as about from "./subcommands/about"; +import * as avatar from "./subcommands/avatar"; -// Modules -import moduleAbout from "./modules/about"; -import moduleAvatar from "./modules/avatar"; +const subcommandHandlers: SubcommandHandlers = { + about: about.execute, + avatar: avatar.execute, +}; export const builder = new SlashCommandBuilder() .setName("utils") .setDescription("Common utility.") + .addSubcommand(about.builder) + .addSubcommand(avatar.builder); - // Modules - .addSubcommand(moduleAbout.builder) - .addSubcommand(moduleAvatar.builder); - -// Execute the command export const execute = async (interaction: ChatInputCommandInteraction) => { - switch (interaction.options.getSubcommand()) { - case "about": - await moduleAbout.execute(interaction); - break; - case "avatar": - await moduleAvatar.execute(interaction); - break; - default: - throw new Error( - `Unknown subcommand: ${interaction.options.getSubcommand()}` - ); - } + await executeSubcommand(interaction, subcommandHandlers); }; diff --git a/src/commands/utils/modules/about/index.ts b/src/commands/utils/modules/about/index.ts deleted file mode 100644 index 3003511..0000000 --- a/src/commands/utils/modules/about/index.ts +++ /dev/null @@ -1,120 +0,0 @@ -/* eslint-disable no-loops/no-loops */ -// Dependencies -import { formatDuration, intervalToDuration, subMilliseconds } from "date-fns"; -import { - ActionRowBuilder, - ButtonBuilder, - ButtonStyle, - CommandInteraction, - EmbedBuilder, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import deferReply from "../../../../handlers/deferReply"; -// Configurations -import getEmbedConfig from "../../../../helpers/getEmbedData"; - -// Function -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("about") - .setDescription("Check information about this instance"); - }, - execute: async (interaction: CommandInteraction) => { - await deferReply(interaction, false); - - if (!interaction.guild) throw new Error("You need to be in a guild"); - - const { client } = interaction; - - // await cooldown( - // interaction.guild, - // interaction.user, - // interaction.commandId, - // 3600 - // ); - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); - - // // Initialize a storage for the user ids - // const userIds = new Set(); - // // Iterate over all guilds (always cached) - // for await (const guild of client.guilds.cache.values()) { - // // Fetch all guild members and iterate over them - // for await (const member of (await guild.members.fetch()).values()) { - // // Fetch the user, if user already cached, returns value from cache - // // Will probably always return from cache - // const user = await client.users.fetch(member.id); - // // Check if user id is not already in set and user is not a bot - // if (!userIds.has(user.id) && !user.bot) { - // // Add unique user id to our set - // userIds.add(user.id); - // } - // } - // } - - const buttons = new ActionRowBuilder().addComponents( - new ButtonBuilder() - .setLabel("Support") - .setStyle(ButtonStyle.Link) - .setEmoji("💬") - .setURL("https://discord.zyner.org"), - new ButtonBuilder() - .setLabel("Documentation") - .setStyle(ButtonStyle.Link) - .setEmoji("📚") - .setURL("https://xyter.zyner.org") - ); - - const interactionEmbed = new EmbedBuilder() - .setColor(successColor) - .setTitle(":toolbox:︱About this instance") - .setDescription( - `This bot instance is hosted by [${process.env.BOT_HOSTER_NAME}](${process.env.BOT_HOSTER_URL}) who might have modified the [source code](https://github.com/ZynerOrg/xyter).` - ) - .setFields( - { - name: "Latency", - value: `${Math.round(client.ws.ping)} ms`, - inline: true, - }, - { - name: "Servers (cached)", - value: `${client.guilds.cache.size}`, - inline: true, - }, - { - name: "Users (cached)", - value: `${client.guilds.cache.reduce( - (a, g) => a + g.memberCount, - 0 - )}`, - inline: true, - }, - { - name: "Version", - value: `[${process.env.npm_package_version}](https://github.com/ZynerOrg/xyter/releases/tag/${process.env.npm_package_version})`, - inline: true, - }, - { - name: "Since last restart", - value: `${formatDuration( - intervalToDuration({ - start: subMilliseconds(new Date(), client.uptime), - end: new Date(), - }) - )}`, - inline: true, - } - ) - .setTimestamp() - .setFooter({ text: footerText, iconURL: footerIcon }); - - await interaction.editReply({ - embeds: [interactionEmbed], - components: [buttons], - }); - }, -}; diff --git a/src/commands/utils/modules/avatar/index.ts b/src/commands/utils/modules/avatar/index.ts deleted file mode 100644 index aa7bafb..0000000 --- a/src/commands/utils/modules/avatar/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { - CommandInteraction, - EmbedBuilder, - SlashCommandSubcommandBuilder, -} from "discord.js"; -import deferReply from "../../../../handlers/deferReply"; -import getEmbedConfig from "../../../../helpers/getEmbedData"; - -export default { - builder: (command: SlashCommandSubcommandBuilder) => { - return command - .setName("avatar") - .setDescription("Check someones avatar!)") - .addUserOption((option) => - option - .setName("user") - .setDescription("The user whose avatar you want to check") - ); - }, - execute: async (interaction: CommandInteraction) => { - await deferReply(interaction, false); - - const { successColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); - const userOption = interaction.options.getUser("user"); - - const targetUser = userOption || interaction.user; - - const embed = new EmbedBuilder() - .setTitle(":toolbox:︱Avatar") - .setTimestamp(new Date()) - .setFooter({ text: footerText, iconURL: footerIcon }); - - const avatarUrl = targetUser.displayAvatarURL(); - - return interaction.editReply({ - embeds: [ - embed - .setDescription( - userOption - ? `You can also [download it here](${avatarUrl})!` - : `Your avatar is available to [download here](${avatarUrl}).` - ) - .setThumbnail(avatarUrl) - .setColor(successColor), - ], - }); - }, -}; diff --git a/src/commands/utils/subcommands/about/index.ts b/src/commands/utils/subcommands/about/index.ts new file mode 100644 index 0000000..eb11307 --- /dev/null +++ b/src/commands/utils/subcommands/about/index.ts @@ -0,0 +1,70 @@ +import { formatDuration, intervalToDuration, subMilliseconds } from "date-fns"; +import { + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + CommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("about") + .setDescription("Get information about the bot and its hosting"); +}; + +export const execute = async (interaction: CommandInteraction) => { + await deferReply(interaction, false); + + const { user, guild, client } = interaction; + + if (!guild) { + throw new Error("This command is only available in guilds"); + } + + const guildCount = client.guilds.cache.size; + const memberCount = client.guilds.cache.reduce( + (a, g) => a + g.memberCount, + 0 + ); + const version = process.env.npm_package_version; + + const buttons = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setLabel("Documentation") + .setStyle(ButtonStyle.Link) + .setEmoji("📚") + .setURL("https://xyter.zyner.org"), + new ButtonBuilder() + .setLabel("Discord Server") + .setStyle(ButtonStyle.Link) + .setEmoji("💬") + .setURL("https://discord.zyner.org") + ); + + const uptimeDuration = intervalToDuration({ + start: subMilliseconds(new Date(), client.uptime), + end: new Date(), + }); + const uptimeString = formatDuration(uptimeDuration); + + const botDescription = `This bot, developed by [**Zyner**](https://zyner.org), serves **${guildCount}** servers and has a vast user base of **${memberCount}**. The current version is **${version}**, accessible on [**GitHub**](https://github.com/ZynerOrg/xyter). It has been active since the last restart, with an uptime of **${uptimeString}**.`; + + const interactionEmbed = new EmbedBuilder() + .setDescription(botDescription) + .setTimestamp() + .setAuthor({ name: "About Xyter" }) + .setColor(process.env.EMBED_COLOR_SUCCESS) + .setFooter({ + text: `Requested by ${user.username}`, + iconURL: user.displayAvatarURL(), + }); + + await sendResponse(interaction, { + embeds: [interactionEmbed], + components: [buttons], + }); +}; diff --git a/src/commands/utils/subcommands/avatar/index.ts b/src/commands/utils/subcommands/avatar/index.ts new file mode 100644 index 0000000..975167e --- /dev/null +++ b/src/commands/utils/subcommands/avatar/index.ts @@ -0,0 +1,54 @@ +import { + CommandInteraction, + EmbedBuilder, + SlashCommandSubcommandBuilder, +} from "discord.js"; +import deferReply from "../../../../utils/deferReply"; +import sendResponse from "../../../../utils/sendResponse"; + +export const builder = (command: SlashCommandSubcommandBuilder) => { + return command + .setName("avatar") + .setDescription("Display someones avatar") + .addUserOption((option) => + option + .setName("user") + .setDescription("The user whose avatar you want to check") + ); +}; + +export const execute = async (interaction: CommandInteraction) => { + await deferReply(interaction, false); + + const { options, user } = interaction; + + const userOption = options.getUser("user"); + + const targetUser = userOption || user; + + const embed = new EmbedBuilder() + .setAuthor({ + name: `${targetUser.username}'s Profile Picture`, + iconURL: targetUser.displayAvatarURL(), + }) + .setTimestamp(new Date()) + .setFooter({ + text: `Requested by ${user.username}`, + iconURL: user.displayAvatarURL(), + }); + + const avatarUrl = targetUser.displayAvatarURL(); + + await sendResponse(interaction, { + embeds: [ + embed + .setDescription( + userOption + ? `You can also [download it here](${avatarUrl})!` + : `Your avatar is available to [download here](${avatarUrl}).` + ) + .setThumbnail(avatarUrl) + .setColor(process.env.EMBED_COLOR_SUCCESS), + ], + }); +}; diff --git a/src/events/guildCreate/index.ts b/src/events/guildCreate/index.ts index 42653b0..390e4a3 100644 --- a/src/events/guildCreate/index.ts +++ b/src/events/guildCreate/index.ts @@ -1,51 +1,18 @@ import { Guild } from "discord.js"; -import prisma from "../../handlers/database"; -import updatePresence from "../../handlers/updatePresence"; +import upsertGuildMember from "../../helpers/upsertGuildMember"; import { IEventOptions } from "../../interfaces/EventOptions"; -import logger from "../../middlewares/logger"; +import logger from "../../utils/logger"; export const options: IEventOptions = { type: "on", }; -// Execute the function export const execute = async (guild: Guild) => { - const { client } = guild; - - updatePresence(client); - - // Create guildMember object - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: guild.ownerId, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: guild.ownerId, - }, - where: { - id: guild.ownerId, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - }); - - logger.silly(createGuildMember); + try { + const { user } = await guild.fetchOwner(); + await upsertGuildMember(guild, user); + } catch (error) { + logger.error(`Error executing guild member fetch: ${error}`); + // Handle the error appropriately (e.g., sending an error message, etc.) + } }; diff --git a/src/events/guildDelete/index.ts b/src/events/guildDelete/index.ts index 3bac8bd..d592be0 100644 --- a/src/events/guildDelete/index.ts +++ b/src/events/guildDelete/index.ts @@ -1,37 +1,57 @@ -// 3rd party dependencies import { Guild } from "discord.js"; -import prisma from "../../handlers/database"; -import updatePresence from "../../handlers/updatePresence"; +import prisma from "../../handlers/prisma"; import { IEventOptions } from "../../interfaces/EventOptions"; -import logger from "../../middlewares/logger"; +import logger from "../../utils/logger"; export const options: IEventOptions = { type: "on", }; -// Execute the function export const execute = async (guild: Guild) => { - const { client } = guild; + const guildId = guild.id; // Assuming guild.id is the unique ID of the guild - updatePresence(client); + try { + // Delete related models based on guildId + await prisma.guildMember.deleteMany({ + where: { + guildId, + }, + }); - // Delete guildMember objects - const deleteGuildMembers = prisma.guildMember.deleteMany({ - where: { - guildId: guild.id, - }, - }); + await prisma.apiCredentials.deleteMany({ + where: { + guildId, + }, + }); - // Delete guild object - const deleteGuild = prisma.guild.deleteMany({ - where: { - id: guild.id, - }, - }); + await prisma.guildCreditsSettings.deleteMany({ + where: { + id: guildId, + }, + }); - // The transaction runs synchronously so deleteUsers must run last. - await prisma.$transaction([deleteGuildMembers, deleteGuild]); + await prisma.guildMemberCredit.deleteMany({ + where: { + guildId, + }, + }); - logger.silly(deleteGuildMembers); - logger.silly(deleteGuild); + await prisma.guildSettings.deleteMany({ + where: { + id: guildId, + }, + }); + + // Delete the Guild model + await prisma.guild.deleteMany({ + where: { + id: guildId, + }, + }); + + logger.info(`Deleted guild and related records with ID: ${guildId}`); + } catch (error) { + logger.error(`Error executing guild deletion: ${error}`); + // Handle the error appropriately (e.g., logging, sending an error message, etc.) + } }; diff --git a/src/events/guildMemberAdd/audits.ts b/src/events/guildMemberAdd/audits.ts deleted file mode 100644 index 0d61fa1..0000000 --- a/src/events/guildMemberAdd/audits.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { ChannelType, EmbedBuilder, GuildMember } from "discord.js"; -import prisma from "../../handlers/database"; -import getEmbedConfig from "../../helpers/getEmbedData"; -import logger from "../../middlewares/logger"; - -export default { - execute: async (member: GuildMember) => { - const { client, guild } = member; - - const getGuild = await prisma.guild.findUnique({ - where: { id: member.guild.id }, - }); - if (!getGuild) throw new Error("Guild not found"); - - if (getGuild.auditsEnabled !== true) return; - if (!getGuild.auditsChannelId) { - throw new Error("Channel not found"); - } - - const embedConfig = await getEmbedConfig(guild); - - const channel = client.channels.cache.get(getGuild.auditsChannelId); - - if (!channel) throw new Error("Channel not found"); - if (channel.type !== ChannelType.GuildText) { - throw new Error("Channel must be a text channel"); - } - - const embed = new EmbedBuilder() - .setTimestamp(new Date()) - .setAuthor({ - name: "Member Joined", - iconURL: client.user?.displayAvatarURL(), - }) - .setFooter({ - text: embedConfig.footerText, - iconURL: embedConfig.footerIcon, - }); - - await channel - .send({ - embeds: [ - embed - .setColor(embedConfig.successColor) - .setDescription(`${member.user} - (${member.user.tag})`) - .addFields([ - { - name: "Account Age", - value: `${member.user.createdAt}`, - }, - ]), - ], - }) - .then(() => { - logger.debug(`Audit log sent for event guildMemberAdd`); - }) - .catch(() => { - throw new Error("Audit log failed to send"); - }); - }, -}; diff --git a/src/events/guildMemberAdd/index.ts b/src/events/guildMemberAdd/index.ts index fc71e62..13cf99b 100644 --- a/src/events/guildMemberAdd/index.ts +++ b/src/events/guildMemberAdd/index.ts @@ -1,60 +1,20 @@ -// 3rd party dependencies import { GuildMember } from "discord.js"; -import prisma from "../../handlers/database"; -import updatePresence from "../../handlers/updatePresence"; +import handleGuildMemberJoin from "../../handlers/handleGuildMemberJoin"; import { IEventOptions } from "../../interfaces/EventOptions"; -import logger from "../../middlewares/logger"; -import audits from "./audits"; -import joinMessage from "./joinMessage"; +import logger from "../../utils/logger"; export const options: IEventOptions = { type: "on", }; -// Execute the function export const execute = async (member: GuildMember) => { - const { client, user, guild } = member; + const { user, guild } = member; - logger.silly( - `New member: ${user.tag} (${user.id}) added to guild: ${guild.name} (${guild.id})` - ); - - await audits.execute(member); - await joinMessage.execute(member); - updatePresence(client); - - // Create guildMember object - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, + logger.info({ + message: `User: ${user.tag} (${user.id}) joined guild: ${guild.name} (${guild.id})`, + guild, + user, }); - logger.silly(createGuildMember); + await handleGuildMemberJoin(guild, user); }; diff --git a/src/events/guildMemberAdd/joinMessage.ts b/src/events/guildMemberAdd/joinMessage.ts deleted file mode 100644 index 57703fb..0000000 --- a/src/events/guildMemberAdd/joinMessage.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { ChannelType, EmbedBuilder, GuildMember } from "discord.js"; -import prisma from "../../handlers/database"; -import getEmbedConfig from "../../helpers/getEmbedData"; - -export default { - execute: async (member: GuildMember) => { - const { footerText, footerIcon, successColor } = await getEmbedConfig( - member.guild - ); - - const getGuild = await prisma.guild.findUnique({ - where: { id: member.guild.id }, - }); - - if (!getGuild) throw new Error("Guild not found"); - - const { client } = member; - - if (getGuild.welcomeEnabled !== true) return; - if (!getGuild.welcomeJoinChannelId) return; - - const channel = client.channels.cache.get( - `${getGuild.welcomeJoinChannelId}` - ); - - if (!channel) throw new Error("Channel not found"); - if (channel.type !== ChannelType.GuildText) - throw new Error("Channel is not a text channel"); - - channel.send({ - embeds: [ - new EmbedBuilder() - .setColor(successColor) - .setTitle(`${member.user.username} has joined the server!`) - .setThumbnail(member.user.displayAvatarURL()) - .setDescription( - getGuild.welcomeJoinChannelMessage || - "Configure a join message in the `/settings guild welcome`." - ) - .setTimestamp() - .setFooter({ - text: footerText, - iconURL: footerIcon, - }), - ], - }); - }, -}; diff --git a/src/events/guildMemberRemove/audits.ts b/src/events/guildMemberRemove/audits.ts deleted file mode 100644 index ff4bb59..0000000 --- a/src/events/guildMemberRemove/audits.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { ChannelType, EmbedBuilder, GuildMember } from "discord.js"; -import prisma from "../../handlers/database"; -import getEmbedConfig from "../../helpers/getEmbedData"; -import logger from "../../middlewares/logger"; - -export default { - execute: async (member: GuildMember) => { - const { client, guild } = member; - - const getGuild = await prisma.guild.findUnique({ - where: { id: member.guild.id }, - }); - if (!getGuild) throw new Error("Guild not found"); - - if (getGuild.auditsEnabled !== true) return; - if (!getGuild.auditsChannelId) { - throw new Error("Channel not found"); - } - - const embedConfig = await getEmbedConfig(guild); - - const channel = client.channels.cache.get(getGuild.auditsChannelId); - if (channel?.type !== ChannelType.GuildText) { - throw new Error("Channel must be a text channel"); - } - - const embed = new EmbedBuilder() - .setTimestamp(new Date()) - .setAuthor({ - name: "Member Left", - iconURL: client.user?.displayAvatarURL(), - }) - .setFooter({ - text: embedConfig.footerText, - iconURL: embedConfig.footerIcon, - }); - - channel - .send({ - embeds: [ - embed - .setColor(embedConfig.errorColor) - .setDescription(`${member.user} - (${member.user.tag})`) - .addFields([ - { - name: "Account Age", - value: `${member.user.createdAt}`, - }, - ]), - ], - }) - .then(() => { - logger.debug(`Audit log sent for event guildMemberRemove.`); - }) - .catch(() => { - throw new Error("Audit log failed to send"); - }); - }, -}; diff --git a/src/events/guildMemberRemove/index.ts b/src/events/guildMemberRemove/index.ts index bbe61ad..bfeb70d 100644 --- a/src/events/guildMemberRemove/index.ts +++ b/src/events/guildMemberRemove/index.ts @@ -1,35 +1,26 @@ -// 3rd party dependencies import { GuildMember } from "discord.js"; -import prisma from "../../handlers/database"; -import updatePresence from "../../handlers/updatePresence"; +import prisma from "../../handlers/prisma"; import { IEventOptions } from "../../interfaces/EventOptions"; -import logger from "../../middlewares/logger"; -import audits from "./audits"; -import leaveMessage from "./leaveMessage"; +import logger from "../../utils/logger"; export const options: IEventOptions = { type: "on", }; -// Execute the function export const execute = async (member: GuildMember) => { - const { client, user, guild } = member; + const { user, guild } = member; - logger?.silly( - `Removed member: ${user.tag} (${user.id}) from guild: ${guild.name} (${guild.id})` - ); - - await audits.execute(member); - await leaveMessage.execute(member); - updatePresence(client); - - // Delete guildMember object - const deleteGuildMember = await prisma.guildMember.deleteMany({ - where: { - userId: user.id, - guildId: guild.id, - }, - }); - - logger.silly(deleteGuildMember); + try { + await prisma.guildMember.delete({ + where: { + guildId_userId: { + guildId: guild.id, + userId: user.id, + }, + }, + }); + } catch (error) { + logger.error(`Error deleting guild member: ${error}`); + // Handle the error appropriately (e.g., sending an error message, etc.) + } }; diff --git a/src/events/guildMemberRemove/leaveMessage.ts b/src/events/guildMemberRemove/leaveMessage.ts deleted file mode 100644 index 9ac7c85..0000000 --- a/src/events/guildMemberRemove/leaveMessage.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { ChannelType, EmbedBuilder, GuildMember } from "discord.js"; -import prisma from "../../handlers/database"; -import getEmbedConfig from "../../helpers/getEmbedData"; - -export default { - execute: async (member: GuildMember) => { - const { footerText, footerIcon, errorColor } = await getEmbedConfig( - member.guild - ); - - const getGuild = await prisma.guild.findUnique({ - where: { id: member.guild.id }, - }); - - if (!getGuild) throw new Error("Guild not found"); - - const { client } = member; - - if (getGuild.welcomeEnabled !== true) return; - if (!getGuild.welcomeLeaveChannelId) return; - - const channel = client.channels.cache.get( - `${getGuild.welcomeLeaveChannelId}` - ); - - if (!channel) throw new Error("Channel not found"); - if (channel.type !== ChannelType.GuildText) - throw new Error("Channel is not a text channel"); - - channel.send({ - embeds: [ - new EmbedBuilder() - .setColor(errorColor) - .setTitle(`${member.user.username} has left the server!`) - .setThumbnail(member.user.displayAvatarURL()) - .setDescription( - getGuild.welcomeLeaveChannelMessage || - "Configure a leave message in the `/settings guild welcome`." - ) - .setTimestamp() - .setFooter({ - text: footerText, - iconURL: footerIcon, - }), - ], - }); - }, -}; diff --git a/src/events/interactionCreate/audits.ts b/src/events/interactionCreate/audits.ts deleted file mode 100644 index 90a55e4..0000000 --- a/src/events/interactionCreate/audits.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { BaseInteraction, ChannelType, EmbedBuilder } from "discord.js"; -import prisma from "../../handlers/database"; -import getEmbedConfig from "../../helpers/getEmbedData"; -import logger from "../../middlewares/logger"; - -export default { - execute: async (interaction: BaseInteraction) => { - if (interaction === null) return; - - if (interaction.guild === null) return; - - const getGuild = await prisma.guild.findUnique({ - where: { id: interaction.guild.id }, - }); - if (!getGuild) throw new Error("Guild not found"); - - const { footerText, footerIcon, successColor } = await getEmbedConfig( - interaction.guild - ); - - const { client } = interaction; - - if (getGuild.auditsEnabled !== true) return; - if (!getGuild.auditsChannelId) return; - - const channel = client.channels.cache.get(`${getGuild.auditsChannelId}`); - - if (!channel) return; - if (channel.type !== ChannelType.GuildText) return; - - channel - .send({ - embeds: [ - new EmbedBuilder() - .setColor(successColor) - .setDescription( - ` - **Interaction created by** ${interaction.user.username} **in** ${interaction.channel} - ㅤ**Interaction ID**: ${interaction.id} - ㅤ**Type**: ${interaction.type} - ㅤ**User ID**: ${interaction.user.id} - ` - ) - .setThumbnail(interaction.user.displayAvatarURL()) - .setTimestamp() - .setFooter({ - text: footerText, - iconURL: footerIcon, - }), - ], - }) - .then(() => { - logger.debug( - `Audit log sent for event interactionCreate in guild ${interaction?.guild?.name} (${interaction?.guild?.id})` - ); - }) - .catch(() => { - logger.silly("Failed to send audit log for event interactionCreate"); - }); - }, -}; diff --git a/src/events/interactionCreate/handlers/button/index.ts b/src/events/interactionCreate/handlers/button/index.ts deleted file mode 100644 index e3e8281..0000000 --- a/src/events/interactionCreate/handlers/button/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Dependencies -import { BaseInteraction } from "discord.js"; - -export default async (interaction: BaseInteraction) => { - if (!interaction.isButton()) return; - - const { customId } = interaction; - - const currentButton = await import(`../../../buttons/${customId}`); - - if (!currentButton) throw new Error(`Unknown button ${customId}`); - - await currentButton.execute(interaction); -}; diff --git a/src/events/interactionCreate/handlers/command/index.ts b/src/events/interactionCreate/handlers/command/index.ts deleted file mode 100644 index c49f7d2..0000000 --- a/src/events/interactionCreate/handlers/command/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Dependencies -import { ChatInputCommandInteraction } from "discord.js"; - -export default async (interaction: ChatInputCommandInteraction) => { - if (!interaction.isCommand()) return; - const { client, commandName } = interaction; - - const currentCommand = client.commands.get(commandName); - if (!currentCommand) throw new Error(`Unknown command ${commandName}`); - - await currentCommand.execute(interaction); -}; diff --git a/src/events/interactionCreate/handlers/index.ts b/src/events/interactionCreate/handlers/index.ts deleted file mode 100644 index 8e9d8c3..0000000 --- a/src/events/interactionCreate/handlers/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { - ActionRowBuilder, - BaseInteraction, - ButtonBuilder, - ButtonInteraction, - ButtonStyle, - ChatInputCommandInteraction, - CommandInteraction, - EmbedBuilder, -} from "discord.js"; -import getEmbedConfig from "../../../helpers/getEmbedData"; -import button from "./button"; -import command from "./command"; - -// Send interactions to all available handlers -export const execute = async (interaction: BaseInteraction) => { - await button(interaction); - await command(interaction); -}; - -// Handle interactions from commands -export const handleCommandInteraction = async ( - interaction: CommandInteraction -) => { - const { errorColor, footerText, footerIcon } = await getEmbedConfig( - interaction.guild - ); - - await command(interaction).catch((err) => { - const buttons = new ActionRowBuilder().addComponents( - new ButtonBuilder() - .setLabel("Report Problem") - .setStyle(ButtonStyle.Link) - .setEmoji("📝") - .setURL("https://discord.zyner.org") - ); - - return interaction.editReply({ - embeds: [ - new EmbedBuilder() - .setTitle(`:no_entry_sign:︱Your request failed`) - .setDescription(`${err.message}`) - .setColor(errorColor) - .setTimestamp(new Date()) - .setFooter({ text: footerText, iconURL: footerIcon }), - ], - components: [buttons], - }); - }); -}; diff --git a/src/events/interactionCreate/index.ts b/src/events/interactionCreate/index.ts index c7e9c63..f48c5af 100644 --- a/src/events/interactionCreate/index.ts +++ b/src/events/interactionCreate/index.ts @@ -1,35 +1,48 @@ -// 3rd party dependencies -import { - BaseInteraction, - CommandInteraction, - InteractionType, -} from "discord.js"; +import { BaseInteraction } from "discord.js"; +import upsertGuildMember from "../../helpers/upsertGuildMember"; import { IEventOptions } from "../../interfaces/EventOptions"; -import logger from "../../middlewares/logger"; -// Dependencies -import audits from "./audits"; -import { handleCommandInteraction as HandlersHandleCommandInteraction } from "./handlers"; +import logger from "../../utils/logger"; +import button from "./interactionTypes/button"; +import handleCommandInteraction from "./interactionTypes/handleCommandInteraction"; export const options: IEventOptions = { type: "on", }; -// Execute the event -export const execute = async (interaction: BaseInteraction) => { - const { guild, id } = interaction; +export async function execute(interaction: BaseInteraction) { + const { guild, user } = interaction; - logger?.silly( - `New interaction: ${id} in guild: ${guild?.name} (${guild?.id})` - ); + logInteraction(); - switch (interaction.type) { - case InteractionType.ApplicationCommand: - await HandlersHandleCommandInteraction(interaction); - break; - - default: - logger?.error(`Unknown interaction type: ${interaction.type}`); + if (guild) { + await upsertGuildMember(guild, user); } - await audits.execute(interaction); -}; + if (interaction.isCommand()) { + await handleCommandInteraction(interaction); + } else if (interaction.isButton()) { + await button(interaction); + } else { + logError("Unknown interaction type"); + } + + function logInteraction() { + logger.verbose({ + message: `New interaction created: ${interaction.id} by: ${user.tag} (${user.id})`, + interactionId: interaction.id, + userId: user.id, + guildId: guild?.id, + }); + } + + function logError(errorMessage: string) { + logger.error({ + message: errorMessage, + error: new Error(errorMessage), + interactionId: interaction.id, + userId: user.id, + guildId: guild?.id, + }); + throw new Error(errorMessage); + } +} diff --git a/src/events/interactionCreate/interactionTypes/button/index.ts b/src/events/interactionCreate/interactionTypes/button/index.ts new file mode 100644 index 0000000..a69ceef --- /dev/null +++ b/src/events/interactionCreate/interactionTypes/button/index.ts @@ -0,0 +1,20 @@ +import { ButtonInteraction } from "discord.js"; +import interactionErrorHandler from "../../../../handlers/interactionErrorHandler"; + +export default async function handleButtonInteraction( + interaction: ButtonInteraction +) { + const { customId } = interaction; + + const currentButton = await import(`../../../buttons/${customId}`); + + if (!currentButton) { + throw new Error(`Unknown button ${customId}`); + } + + try { + await currentButton.execute(interaction); + } catch (error) { + await interactionErrorHandler(interaction, error); + } +} diff --git a/src/events/interactionCreate/interactionTypes/handleCommandInteraction/handlers/handleCooldown.ts b/src/events/interactionCreate/interactionTypes/handleCommandInteraction/handlers/handleCooldown.ts new file mode 100644 index 0000000..78e5076 --- /dev/null +++ b/src/events/interactionCreate/interactionTypes/handleCommandInteraction/handlers/handleCooldown.ts @@ -0,0 +1,59 @@ +import { Cooldown } from "@prisma/client"; +import { formatDistanceToNow } from "date-fns"; +import { + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + CommandInteraction, + EmbedBuilder, +} from "discord.js"; +import sendResponse from "../../../../../utils/sendResponse"; + +export default async function handleCooldown( + interaction: CommandInteraction, + guildCooldown: Cooldown | null, + userCooldown: Cooldown | null, + guildMemberCooldown: Cooldown | null +) { + const cooldown = guildCooldown || userCooldown || guildMemberCooldown; + + if (!cooldown || !cooldown.expiresAt) { + return; + } + + const timeLeft = formatDistanceToNow(cooldown.expiresAt, { + includeSeconds: true, + }); + + const buttons = createButtons(); + + const cooldownEmbed = createCooldownEmbed(timeLeft, cooldown.id); + + const response = { + embeds: [cooldownEmbed], + components: [buttons], + }; + + await sendResponse(interaction, response); +} + +function createButtons() { + return new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setLabel("Report Problem") + .setStyle(ButtonStyle.Link) + .setEmoji("✏️") + .setURL("https://discord.zyner.org") + ); +} + +function createCooldownEmbed(timeLeft: string, cooldownId: number) { + return new EmbedBuilder() + .setAuthor({ name: "⚠️ | Request Failed" }) + .setDescription( + `Sorry, but you're currently on cooldown. Please try again later.\n\nRemaining cooldown time: ${timeLeft}` + ) + .setColor("#FF6699") + .setTimestamp() + .setFooter({ text: `Cooldown ID: ${cooldownId}` }); +} diff --git a/src/events/interactionCreate/interactionTypes/handleCommandInteraction/handlers/handleUnavailableCommand.ts b/src/events/interactionCreate/interactionTypes/handleCommandInteraction/handlers/handleUnavailableCommand.ts new file mode 100644 index 0000000..e9ec2dc --- /dev/null +++ b/src/events/interactionCreate/interactionTypes/handleCommandInteraction/handlers/handleUnavailableCommand.ts @@ -0,0 +1,38 @@ +import { + ActionRowBuilder, + ButtonBuilder, + ButtonStyle, + CommandInteraction, + EmbedBuilder, +} from "discord.js"; +import logger from "../../../../../utils/logger"; +import sendResponse from "../../../../../utils/sendResponse"; + +export default async function handleUnavailableCommand( + interaction: CommandInteraction, + commandName: string +) { + const commandErrorMessage = `Command '${commandName}' is unavailable`; + logger.error(commandErrorMessage); + + const errorEmbed = new EmbedBuilder() + .setAuthor({ name: "⚠️ | Request Failed" }) + .setDescription("Sorry, the command is currently unavailable.") + .setColor("#FFCC66") + .setTimestamp(); + + const buttons = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setLabel("Report Problem") + .setStyle(ButtonStyle.Link) + .setEmoji("✏️") + .setURL("https://discord.zyner.org") + ); + + const response = { + embeds: [errorEmbed], + components: [buttons], + }; + + await sendResponse(interaction, response); +} diff --git a/src/events/interactionCreate/interactionTypes/handleCommandInteraction/index.ts b/src/events/interactionCreate/interactionTypes/handleCommandInteraction/index.ts new file mode 100644 index 0000000..3701b67 --- /dev/null +++ b/src/events/interactionCreate/interactionTypes/handleCommandInteraction/index.ts @@ -0,0 +1,43 @@ +import { CommandInteraction } from "discord.js"; +import { default as CooldownManager } from "../../../../handlers/CooldownManager"; +import interactionErrorHandler from "../../../../handlers/interactionErrorHandler"; +import generateCooldownName from "../../../../helpers/generateCooldownName"; +import handleCooldown from "./handlers/handleCooldown"; +import handleUnavailableCommand from "./handlers/handleUnavailableCommand"; + +const cooldownManager = new CooldownManager(); + +export default async function handleCommandInteraction( + interaction: CommandInteraction +) { + if (!interaction.isCommand()) { + return; + } + + const { client, commandName, user, guild } = interaction; + const currentCommand = client.commands.get(commandName); + + if (!currentCommand) { + await handleUnavailableCommand(interaction, commandName); + return; + } + + try { + const cooldownItem = await generateCooldownName(interaction); + const { guildCooldown, userCooldown, guildMemberCooldown } = + await cooldownManager.checkCooldowns(cooldownItem, guild, user); + + if (guildCooldown || userCooldown || guildMemberCooldown) { + await handleCooldown( + interaction, + guildCooldown, + userCooldown, + guildMemberCooldown + ); + } else { + await currentCommand.execute(interaction); + } + } catch (error) { + await interactionErrorHandler(interaction, error); + } +} diff --git a/src/events/messageCreate/components/earnCredits.ts b/src/events/messageCreate/components/earnCredits.ts new file mode 100644 index 0000000..4c00157 --- /dev/null +++ b/src/events/messageCreate/components/earnCredits.ts @@ -0,0 +1,64 @@ +import { Channel, ChannelType, Guild, Message, User } from "discord.js"; +import CooldownManager from "../../../handlers/CooldownManager"; +import CreditsManager from "../../../handlers/CreditsManager"; +import logger from "../../../utils/logger"; + +const cooldownManager = new CooldownManager(); +const creditsManager = new CreditsManager(); + +const MINIMUM_LENGTH = 5; + +const cooldownName = "earnCredits"; + +export default async (message: Message) => { + const { guild, author, channel, content } = message; + + if (!guild || !isMessageValid(guild, author, channel, content)) { + return; + } + + if (await isUserOnCooldown(guild, author)) { + logger.verbose( + `User "${author.username}" is on cooldown for "${cooldownName}" in guild "${guild.name}"` + ); + return; + } + + try { + await creditsManager.give(guild, author, 1); + } catch (error: unknown) { + logger.error( + `Failed to give credits to user ${author.username} in guild ${ + guild.name + } when sending a message: ${String(error)}` + ); + } + + await setCooldown(guild, author); +}; + +function isMessageValid( + guild: Guild, + author: User, + channel: Channel, + content: string +): boolean { + return ( + !author.bot && + channel.type === ChannelType.GuildText && + content.length >= MINIMUM_LENGTH + ); +} + +async function isUserOnCooldown(guild: Guild, author: User): Promise { + const cooldownActive = await cooldownManager.checkCooldown( + cooldownName, + guild, + author + ); + return cooldownActive !== null; +} + +async function setCooldown(guild: Guild, user: User) { + await cooldownManager.setCooldown(cooldownName, guild, user, 5); +} diff --git a/src/events/messageCreate/index.ts b/src/events/messageCreate/index.ts index 6a745cc..edfde2c 100644 --- a/src/events/messageCreate/index.ts +++ b/src/events/messageCreate/index.ts @@ -1,14 +1,11 @@ import { Message } from "discord.js"; import { IEventOptions } from "../../interfaces/EventOptions"; -import modules from "./modules"; +import earnCredits from "./components/earnCredits"; export const options: IEventOptions = { type: "on", }; -// Execute the function export const execute = async (message: Message) => { - await modules.credits.execute(message); - await modules.points.execute(message); - await modules.counters.execute(message); + await earnCredits(message); }; diff --git a/src/events/messageCreate/modules/counters/index.ts b/src/events/messageCreate/modules/counters/index.ts deleted file mode 100644 index 70dd0e7..0000000 --- a/src/events/messageCreate/modules/counters/index.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { ChannelType, Message } from "discord.js"; -import prisma from "../../../../handlers/database"; -import logger from "../../../../middlewares/logger"; - -export default { - execute: async (message: Message) => { - const { guild, author, content, channel } = message; - - if (!guild) return; - if (author.bot) return; - if (channel?.type !== ChannelType.GuildText) return; - - const messages = await message.channel.messages.fetch({ limit: 2 }); - const lastMessage = messages.last(); - - const channelCounter = await prisma.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: channel.id, - }, - }, - }); - - if (!channelCounter) { - logger.debug("No counters found in channel."); - return; - } - - if ( - lastMessage?.author.id === author.id && - channel.id === channelCounter.channelId - ) { - logger.silly( - `${author.username} sent the last message therefor not allowing again.` - ); - await message.delete(); - return false; - } - - if (content !== channelCounter.triggerWord) { - logger.silly( - `Counter word ${channelCounter.triggerWord} does not match message ${content}` - ); - - await message.delete(); - return false; - } - - const updateGuildCounter = await prisma.guildCounter.update({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: channel.id, - }, - }, - data: { - count: { - increment: 1, - }, - }, - }); - - logger.silly(updateGuildCounter); - - if (!updateGuildCounter) - logger.error(`Failed to update counter - ${updateGuildCounter}`); - }, -}; diff --git a/src/events/messageCreate/modules/credits/index.ts b/src/events/messageCreate/modules/credits/index.ts deleted file mode 100644 index b38ad47..0000000 --- a/src/events/messageCreate/modules/credits/index.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { ChannelType, Message } from "discord.js"; -import prisma from "../../../../handlers/database"; -import creditsGive from "../../../../helpers/credits/give"; -import cooldown from "../../../../middlewares/cooldown"; -import logger from "../../../../middlewares/logger"; - -export default { - execute: async (message: Message) => { - const { guild, author, content, channel } = message; - - if (!guild) return; - if (author.bot) return; - if (channel.type !== ChannelType.GuildText) return; - - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: author.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: author.id, - }, - where: { - id: author.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - - logger.silly(createGuildMember); - - if (content.length < createGuildMember.guild.creditsMinimumLength) return; - - await cooldown( - guild, - author, - "event-messageCreate-credits", - createGuildMember.guild.creditsTimeout, - true - ); - - await creditsGive(guild, author, createGuildMember.guild.creditsRate); - }, -}; diff --git a/src/events/messageCreate/modules/index.ts b/src/events/messageCreate/modules/index.ts deleted file mode 100644 index aff2dd3..0000000 --- a/src/events/messageCreate/modules/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import counters from "./counters"; -import credits from "./credits"; -import points from "./points"; - -export default { - counters, - credits, - points, -}; diff --git a/src/events/messageCreate/modules/points/index.ts b/src/events/messageCreate/modules/points/index.ts deleted file mode 100644 index d8f1494..0000000 --- a/src/events/messageCreate/modules/points/index.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { ChannelType, Message } from "discord.js"; -import prisma from "../../../../handlers/database"; -import cooldown from "../../../../middlewares/cooldown"; -import logger from "../../../../middlewares/logger"; - -export default { - execute: async (message: Message) => { - const { guild, author, content, channel } = message; - - if (!guild) return; - if (author.bot) return; - if (channel.type !== ChannelType.GuildText) return; - - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: author.id, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: author.id, - }, - where: { - id: author.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - - logger.silly(createGuildMember); - - if (content.length < createGuildMember.guild.pointsMinimumLength) return; - - await cooldown( - guild, - author, - "event-messageCreate-points", - createGuildMember.guild.pointsTimeout, - true - ); - - const updateGuildMember = await prisma.guildMember.update({ - where: { - userId_guildId: { - userId: author.id, - guildId: guild.id, - }, - }, - data: { - pointsEarned: { - increment: createGuildMember.guild.pointsRate, - }, - }, - }); - - logger.silly(updateGuildMember); - - if (!updateGuildMember) - throw new Error("Failed to update guildMember object"); - }, -}; diff --git a/src/events/messageDelete/audits.ts b/src/events/messageDelete/audits.ts deleted file mode 100644 index 56a8ac1..0000000 --- a/src/events/messageDelete/audits.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { ChannelType, EmbedBuilder, Message } from "discord.js"; -import prisma from "../../handlers/database"; -import getEmbedConfig from "../../helpers/getEmbedData"; -import logger from "../../middlewares/logger"; - -export default { - execute: async (message: Message) => { - if (message === null) return; - - if (message.guild === null) return; - - const { footerText, footerIcon, successColor } = await getEmbedConfig( - message.guild - ); - - const getGuild = await prisma.guild.findUnique({ - where: { id: message.guild.id }, - }); - if (!getGuild) throw new Error("Guild not found"); - - const { client } = message; - - if (!getGuild) throw new Error("Guild not found"); - - if (getGuild.auditsEnabled !== true) return; - if (!getGuild.auditsChannelId) return; - - const channel = client.channels.cache.get(`${getGuild.auditsChannelId}`); - - if (!channel) return; - if (channel.type !== ChannelType.GuildText) return; - - channel - .send({ - embeds: [ - new EmbedBuilder() - .setColor(successColor) - .setAuthor({ - name: message.author.username, - iconURL: message.author.displayAvatarURL(), - }) - .setDescription( - ` - **Message sent by** ${message.author} **deleted in** ${message.channel} - ${message.content} - ` - ) - .setTimestamp() - .setFooter({ - text: footerText, - iconURL: footerIcon, - }), - ], - }) - .then(() => { - logger.info( - `Audit log sent for event messageDelete in guild ${message?.guild?.name} (${message?.guild?.id})` - ); - }) - .catch(() => { - throw new Error( - `Audit log failed to send for event messageDelete in guild ${message?.guild?.name} (${message?.guild?.id})` - ); - }); - }, -}; diff --git a/src/events/messageDelete/index.ts b/src/events/messageDelete/index.ts deleted file mode 100644 index 53ccb2d..0000000 --- a/src/events/messageDelete/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Message } from "discord.js"; -import { IEventOptions } from "../../interfaces/EventOptions"; -import audits from "./audits"; -import counter from "./modules/counter"; - -export const options: IEventOptions = { - type: "on", -}; - -// Execute the function -export const execute = async (message: Message) => { - await audits.execute(message); - await counter(message); -}; diff --git a/src/events/messageDelete/modules/counter.ts b/src/events/messageDelete/modules/counter.ts deleted file mode 100644 index 989db4e..0000000 --- a/src/events/messageDelete/modules/counter.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Dependencies -import { Message } from "discord.js"; -// Models -import prisma from "../../../handlers/database"; -import logger from "../../../middlewares/logger"; - -export default async (message: Message) => { - const { guild, channel, author, content } = message; - - if (!guild) throw new Error("Guild not found"); - if (!channel) throw new Error("Channel not found"); - - const channelCounter = await prisma.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: channel.id, - }, - }, - }); - - if (!channelCounter) throw new Error("No counter found in channel."); - - const messages = await message.channel.messages.fetch({ limit: 1 }); - const lastMessage = messages.last(); - - if (!lastMessage) return; - - if (content !== channelCounter.triggerWord) return; - - if (lastMessage.author.id === message.author.id) return; - - channel?.send(`${author} said **${channelCounter.triggerWord}**.`); - logger?.silly(`${author} said ${channelCounter.triggerWord} in ${channel}`); - logger?.silly( - `User: ${author?.tag} (${author?.id}) in guild: ${guild?.name} (${guild?.id}) said the counter word: ${channelCounter.triggerWord}` - ); -}; diff --git a/src/events/messageUpdate/audits.ts b/src/events/messageUpdate/audits.ts deleted file mode 100644 index a498385..0000000 --- a/src/events/messageUpdate/audits.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* eslint-disable no-loops/no-loops */ -import { ChannelType, EmbedBuilder, Message } from "discord.js"; -import prisma from "../../handlers/database"; -import getEmbedConfig from "../../helpers/getEmbedData"; -import logger from "../../middlewares/logger"; - -export default { - execute: async (oldMessage: Message, newMessage: Message) => { - if (oldMessage === null) return; - if (newMessage === null) return; - - if (oldMessage.guild === null) return; - if (newMessage.guild === null) return; - - const { footerText, footerIcon, successColor } = await getEmbedConfig( - newMessage.guild - ); - - const getGuild = await prisma.guild.findUnique({ - where: { id: oldMessage.guild.id }, - }); - if (!getGuild) throw new Error("Guild not found"); - - const { client } = oldMessage; - - if (getGuild.auditsEnabled !== true) return; - if (!getGuild.auditsChannelId) return; - - const channel = client.channels.cache.get(`${getGuild.auditsChannelId}`); - - if (!channel) return; - if (channel.type !== ChannelType.GuildText) return; - - channel - .send({ - embeds: [ - new EmbedBuilder() - .setColor(successColor) - .setAuthor({ - name: newMessage.author.username, - iconURL: newMessage.author.displayAvatarURL(), - }) - .setDescription( - ` - **Message edited in** ${newMessage.channel} [jump to message](https://discord.com/channels/${newMessage.guild.id}/${newMessage.channel.id}/${newMessage.id}) - ` - ) - .setTimestamp() - .setFooter({ - text: footerText, - iconURL: footerIcon, - }), - ], - }) - .then(() => { - logger.info( - `Audit log sent for event messageUpdate in guild ${newMessage?.guild?.name} (${newMessage?.guild?.id})` - ); - }) - .catch(() => { - throw new Error( - `Audit log failed to send for event messageUpdate in guild ${newMessage?.guild?.name} (${newMessage?.guild?.id})` - ); - }); - }, -}; diff --git a/src/events/messageUpdate/index.ts b/src/events/messageUpdate/index.ts deleted file mode 100644 index fc01d09..0000000 --- a/src/events/messageUpdate/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Dependencies -import { Message } from "discord.js"; -import logger from "../../middlewares/logger"; - -// Modules -import counter from "./modules/counter"; - -import { IEventOptions } from "../../interfaces/EventOptions"; -import audits from "./audits"; - -export const options: IEventOptions = { - type: "on", -}; - -// Execute the function -export const execute = async (oldMessage: Message, newMessage: Message) => { - const { author, guild } = newMessage; - - await audits.execute(oldMessage, newMessage); - - logger?.silly( - `Message update event fired by ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})` - ); - - if (author?.bot) return logger?.silly(`Message update event fired by bot`); - - await counter(newMessage); - - return true; -}; diff --git a/src/events/messageUpdate/modules/counter.ts b/src/events/messageUpdate/modules/counter.ts deleted file mode 100644 index 258e729..0000000 --- a/src/events/messageUpdate/modules/counter.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Dependencies -import { Message } from "discord.js"; -// Models -import prisma from "../../../handlers/database"; -import logger from "../../../middlewares/logger"; - -export default async (message: Message) => { - const { guild, channel, author, content } = message; - - if (!guild) throw new Error("Guild not found"); - - if (!channel) throw new Error("Channel not found"); - - const channelCounter = await prisma.guildCounter.findUnique({ - where: { - guildId_channelId: { - guildId: guild.id, - channelId: channel.id, - }, - }, - }); - - if (!channelCounter) return logger.debug("No counters found in channel."); - - if (content === channelCounter.triggerWord) - return logger?.silly( - `User: ${author?.tag} (${author?.id}) in guild: ${guild?.name} (${guild?.id}) said the counter word: ${channelCounter.triggerWord}` - ); - - await message - .delete() - .then(async () => { - logger?.silly( - `${author} said ${channelCounter.triggerWord} in ${channel}` - ); - await channel?.send(`${author} said **${channelCounter.triggerWord}**.`); - }) - .catch((error) => { - return logger.error(error); - }); - - return true; -}; diff --git a/src/events/rateLimit/index.ts b/src/events/rateLimit/index.ts index 059b855..32dbb16 100644 --- a/src/events/rateLimit/index.ts +++ b/src/events/rateLimit/index.ts @@ -1,14 +1,12 @@ -// Dependencies import { Client } from "discord.js"; -// Helpers import { IEventOptions } from "../../interfaces/EventOptions"; -import logger from "../../middlewares/logger"; +import logger from "../../utils/logger"; export const options: IEventOptions = { type: "on", }; -// Function to execute the event export const execute = (client: Client) => { - logger.warn(`Discord's API client (${client?.user?.tag}) is rate-limited!`); + const clientTag = client?.user?.tag ?? "unknown"; + logger.info(`Discord API client (${clientTag}) is rate-limited.`); }; diff --git a/src/events/ready/importOldData.ts b/src/events/ready/importOldData.ts new file mode 100644 index 0000000..52096e9 --- /dev/null +++ b/src/events/ready/importOldData.ts @@ -0,0 +1,157 @@ +// @ts-nocheck +/* eslint-disable no-loops/no-loops */ +import { ChannelType, Client } from "discord.js"; +import CreditsManager from "../../handlers/CreditsManager"; +import prisma from "../../handlers/prisma"; +import logger from "../../utils/logger"; + +const creditsManager = new CreditsManager(); + +export default async (client: Client) => { + try { + // Fetch all guilds the bot is a member of + const guilds = client.guilds.cache.values(); + + for await (const guild of guilds) { + // if (guild.name === "Zyner Infrastructure") continue; + + // if (guild.memberCount > 200) { + // logger.info(`Skipped guild: ${guild.name}`); + // continue; + // } + + const isDone = await prisma.importOldData.findUnique({ + where: { id: guild.id }, + }); + + if (isDone && isDone.done) continue; + + // Fetch all channels in the guild + const channels = guild.channels.cache.filter( + (channel) => channel.type === ChannelType.GuildText + ); + + // Object to store message counts per user + const messageCounts: unknown = {}; + + for await (const [, channel] of channels) { + if (channel.type !== ChannelType.GuildText) continue; + + let beforeMessageID = null; + let messagesFetched = 0; + + while (true) { + const fetchOptions: never = { limit: 100, before: beforeMessageID }; + + try { + const messages = await channel.messages.fetch(fetchOptions); + + for await (const [, message] of messages) { + const userId = message.author.id; + + logger.debug(message.id); + + if (message.author.bot) continue; + + // Increment message count for the user + if (!messageCounts[userId]) { + messageCounts[userId] = 1; + } else { + messageCounts[userId]++; + logger.silly( + `Guild: ${message.guild.name} User: ${message.author.username} => ${messageCounts[userId]}` + ); + } + } + + messagesFetched += messages.size; + + if (messages.size < 100) { + break; + } + + const importConfig = await prisma.importOldData.upsert({ + where: { id: messages.last().guild.id }, + update: { beforeMessageId: messages.last()?.id }, + create: { + id: messages.last().guild.id, + beforeMessageId: messages.last()?.id, + }, + }); + + logger.error(importConfig.beforeMessageId); + beforeMessageID = importConfig.beforeMessageId; + } catch (error) { + console.error(`Error fetching messages in ${channel.name}:`, error); + // Handle rate limit here if needed + // You can use the error object to determine the type of error and handle it accordingly + // For example, you can check if the error is a rate limit error and implement a delay before retrying + + if (error.code === 429) { + logger.error("RATE LIMIT"); + // Rate limit hit, wait for the specified duration and retry + const retryAfter = error.retryAfter; + logger.warn(`Rate limited. Retrying in ${retryAfter}ms...`); + console.log(retryAfter); + await new Promise((resolve) => setTimeout(resolve, retryAfter)); + continue; // Retry the fetch + } + + if (error.code === 10013) continue; + if (error.code === 50001) break; + if (error.code === 10007) logger.error("Unknown user"); + logger.error(error.code); + } + } + } + + // Log message counts for the guild + logger.info(`Message Counts for Guild: ${guild.name}`); + await prisma.importOldData.upsert({ + where: { id: guild.id }, + update: { done: true }, + create: { + id: guild.id, + done: true, + }, + }); + for (const userId in messageCounts) { + if (messageCounts.hasOwnProperty(userId)) { + try { + const member = await guild.members.fetch(userId); + if (!member) continue; // Skip unknown members + + await creditsManager.set( + member.guild, + member.user, + messageCounts[userId] + ); + + logger.info( + `${member?.user.username}: ${messageCounts[userId]} messages` + ); + } catch (error: unknown) { + if (error.code === 429) { + logger.error("RATE LIMIT"); + // Rate limit hit, wait for the specified duration and retry + const retryAfter = error.retryAfter; + logger.warn(`Rate limited. Retrying in ${retryAfter}ms...`); + console.log(retryAfter); + await new Promise((resolve) => setTimeout(resolve, retryAfter)); + continue; // Retry the fetch + } + + if (error.code === 10013) continue; + if (error.code === 50001) break; + if (error.code === 10007) + logger.error(`Unknown user: ${messageCounts[userId]}`); + logger.error(error.code); + } + 10007; + } + } + } + } catch (error) { + console.error("Error:", error); + } +}; diff --git a/src/events/ready/index.ts b/src/events/ready/index.ts index 72cc060..222ca5c 100644 --- a/src/events/ready/index.ts +++ b/src/events/ready/index.ts @@ -1,19 +1,27 @@ -// Dependencies +/* eslint-disable no-loops/no-loops */ import { Client } from "discord.js"; -// Helpers -import deployCommands from "../../handlers/deployCommands"; +import registerCommands from "../../handlers/registerCommands"; import updatePresence from "../../handlers/updatePresence"; import { IEventOptions } from "../../interfaces/EventOptions"; -import logger from "../../middlewares/logger"; +import logger from "../../utils/logger"; +import importOldData from "./importOldData"; export const options: IEventOptions = { type: "once", }; -// Execute the event export const execute = async (client: Client) => { - logger.info("Discord's API client is ready!"); + if (!client.user) { + logger.error("Client user unavailable"); + throw new Error("Client user unavailable"); + } + + logger.info("Connected to Discord!"); updatePresence(client); - await deployCommands(client); + await registerCommands(client); + + if (process.env.IMPORT_DATA_FROM_V1 === "true") { + await importOldData(client); + } }; diff --git a/src/handlers/CooldownManager.ts b/src/handlers/CooldownManager.ts new file mode 100644 index 0000000..bb66abd --- /dev/null +++ b/src/handlers/CooldownManager.ts @@ -0,0 +1,89 @@ +import { Cooldown } from "@prisma/client"; +import { Guild, User } from "discord.js"; +import logger from "../utils/logger"; +import prisma from "./prisma"; + +class CooldownManager { + async setCooldown( + cooldownItem: string, + guild: Guild | null, + user: User | null, + cooldownSeconds: number + ): Promise { + const expiresAt = new Date(Date.now() + cooldownSeconds * 1000); + const data = { + cooldownItem, + expiresAt, + guild: guild ? { connect: { id: guild.id } } : undefined, + user: user ? { connect: { id: user.id } } : undefined, + }; + + await prisma.cooldown.create({ data }); + + if (guild && user) { + logger.verbose( + `Set guild member cooldown: ${cooldownItem} in guild ${guild.id} for user ${user.id}` + ); + } else if (guild) { + logger.verbose( + `Set guild cooldown: ${cooldownItem} in guild ${guild.id}` + ); + } else if (user) { + logger.verbose(`Set user cooldown: ${cooldownItem} for user ${user.id}`); + } + } + + async checkCooldown( + cooldownItem: string, + guild: Guild | null, + user: User | null + ): Promise { + const start = Date.now(); + const where = { + cooldownItem, + guild: guild ? { id: guild.id } : null, + user: user ? { id: user.id } : null, + expiresAt: { gte: new Date() }, + }; + const cooldown = await prisma.cooldown.findFirst({ where }); + const duration = Date.now() - start; + + if (guild && user) { + logger.verbose( + `Checked guild member cooldown: ${cooldownItem} in guild ${guild.id} for user ${user.id}. Duration: ${duration}ms` + ); + } else if (guild) { + logger.verbose( + `Checked guild cooldown: ${cooldownItem} in guild ${guild.id}. Duration: ${duration}ms` + ); + } else if (user) { + logger.verbose( + `Checked user cooldown: ${cooldownItem} for user ${user.id}. Duration: ${duration}ms` + ); + } + + return cooldown; + } + + async checkCooldowns( + cooldownItem: string, + guild: Guild | null, + user: User + ): Promise<{ + guildCooldown: Cooldown | null; + userCooldown: Cooldown | null; + guildMemberCooldown: Cooldown | null; + }> { + const guildCooldown = guild + ? await this.checkCooldown(cooldownItem, guild, null) + : null; + const userCooldown = await this.checkCooldown(cooldownItem, null, user); + const guildMemberCooldown = guild + ? await this.checkCooldown(cooldownItem, guild, user) + : null; + + return { guildCooldown, userCooldown, guildMemberCooldown }; + } +} + +export default CooldownManager; diff --git a/src/handlers/CreditsManager.ts b/src/handlers/CreditsManager.ts new file mode 100644 index 0000000..1c49d68 --- /dev/null +++ b/src/handlers/CreditsManager.ts @@ -0,0 +1,485 @@ +import { Guild, User } from "discord.js"; +import logger from "../utils/logger"; +import prisma from "./prisma"; + +class CreditsManager { + async validateTransaction(guild: Guild, user: User, amount: number) { + if (!guild) { + throw new Error("Credits are only available for guilds."); + } + + if (amount <= 0) { + throw new Error("You cannot make a transaction below 1 credit."); + } + + if (amount > 2147483647) { + throw new Error("The maximum allowed credits is 2,147,483,647."); + } + + if (user.bot) { + throw new Error("Bots cannot participate in transactions."); + } + } + + async balance(guild: Guild, user: User) { + return await prisma.$transaction(async (tx) => { + const recipient = await tx.guildMemberCredit.upsert({ + update: {}, + create: { + guildMember: { + connectOrCreate: { + create: { + user: { + connectOrCreate: { + create: { id: user.id }, + where: { id: user.id }, + }, + }, + guild: { + connectOrCreate: { + create: { id: guild.id }, + where: { id: guild.id }, + }, + }, + }, + where: { guildId_userId: { guildId: guild.id, userId: user.id } }, + }, + }, + }, + where: { + guildId_userId: { + guildId: guild.id, + userId: user.id, + }, + }, + }); + + if (!recipient) throw new Error("No recipient available"); + + return recipient; + }); + } + + async give(guild: Guild, user: User, amount: number) { + try { + logger.debug( + `Starting give transaction for guild: ${guild.id}, user: ${user.id}` + ); + + const recipient = await prisma.$transaction(async (tx) => { + await this.validateTransaction(guild, user, amount); + + const existingRecipient = await tx.guildMemberCredit.findUnique({ + where: { + guildId_userId: { + userId: user.id, + guildId: guild.id, + }, + }, + }); + + if (existingRecipient && existingRecipient.balance > 2147483647) { + throw new Error( + "Oops! That's more credits than the user can have. The maximum allowed is 2,147,483,647." + ); + } + + await this.upsertGuildMember(guild, user); + + const recipient = await tx.guildMemberCredit.upsert({ + update: { + balance: { + increment: amount, + }, + }, + create: { + guildMember: { + connectOrCreate: { + create: { + user: { + connectOrCreate: { + create: { id: user.id }, + where: { id: user.id }, + }, + }, + guild: { + connectOrCreate: { + create: { id: guild.id }, + where: { id: guild.id }, + }, + }, + }, + where: { + guildId_userId: { + guildId: guild.id, + userId: user.id, + }, + }, + }, + }, + balance: amount, + }, + where: { + guildId_userId: { + guildId: guild.id, + userId: user.id, + }, + }, + }); + + return recipient; + }); + + logger.debug( + `Give transaction completed for guild: ${guild.id}, user: ${user.id}` + ); + + return recipient; + } catch (error) { + logger.error(`Error in give transaction for user: ${user.id}`, error); + throw error; + } + } + + async take(guild: Guild, user: User, amount: number) { + try { + logger.debug( + `Starting take transaction for guild: ${guild.id}, user: ${user.id}` + ); + + const recipient = await prisma.$transaction(async (tx) => { + await this.validateTransaction(guild, user, amount); + + const existingRecipient = await tx.guildMemberCredit.findUnique({ + where: { + guildId_userId: { + userId: user.id, + guildId: guild.id, + }, + }, + }); + + if (!existingRecipient || existingRecipient.balance < amount) { + throw new Error("Insufficient credits for the transaction."); + } + + await this.upsertGuildMember(guild, user); + + const recipient = await tx.guildMemberCredit.upsert({ + update: { + balance: { + decrement: amount, + }, + }, + create: { + guildMember: { + connectOrCreate: { + create: { + user: { + connectOrCreate: { + create: { id: user.id }, + where: { id: user.id }, + }, + }, + guild: { + connectOrCreate: { + create: { id: guild.id }, + where: { id: guild.id }, + }, + }, + }, + where: { + guildId_userId: { + guildId: guild.id, + userId: user.id, + }, + }, + }, + }, + balance: -amount, + }, + where: { + guildId_userId: { + guildId: guild.id, + userId: user.id, + }, + }, + }); + + return recipient; + }); + + logger.debug( + `Take transaction completed for guild: ${guild.id}, user: ${user.id}` + ); + + return recipient; + } catch (error) { + logger.error(`Error in take transaction for user: ${user.id}`, error); + throw error; + } + } + + async set(guild: Guild, user: User, amount: number) { + try { + logger.debug( + `Starting set transaction for guild: ${guild.id}, user: ${user.id}` + ); + + const recipient = await prisma.$transaction(async (tx) => { + await this.validateTransaction(guild, user, amount); + + await this.upsertGuildMember(guild, user); + + const recipient = await tx.guildMemberCredit.upsert({ + update: { + balance: amount, + }, + create: { + guildMember: { + connectOrCreate: { + create: { + user: { + connectOrCreate: { + create: { id: user.id }, + where: { id: user.id }, + }, + }, + guild: { + connectOrCreate: { + create: { id: guild.id }, + where: { id: guild.id }, + }, + }, + }, + where: { + guildId_userId: { + guildId: guild.id, + userId: user.id, + }, + }, + }, + }, + balance: amount, + }, + where: { + guildId_userId: { + guildId: guild.id, + userId: user.id, + }, + }, + }); + + return recipient; + }); + + logger.debug( + `Set transaction completed for guild: ${guild.id}, user: ${user.id}` + ); + + return recipient; + } catch (error) { + logger.error(`Error in set transaction for user: ${user.id}`, error); + throw error; + } + } + + async transfer(guild: Guild, fromUser: User, toUser: User, amount: number) { + if (fromUser.id === toUser.id) { + throw new Error("The sender and receiver cannot be the same user."); + } + + try { + const fromTransaction = await prisma.guildMemberCredit.findFirst({ + where: { + guildId: guild.id, + userId: fromUser.id, + }, + }); + + if (!fromTransaction) { + throw new Error("Failed to fetch the sender's transaction record."); + } + + const toTransaction = await prisma.guildMemberCredit.findUnique({ + where: { + guildId_userId: { + guildId: guild.id, + userId: toUser.id, + }, + }, + }); + + if (!toTransaction) { + console.log({ guildId: guild.id, userId: toUser.id }); + + // Create a new transaction record for the recipient with initial balance of 0 + + await this.upsertGuildMember(guild, toUser); + prisma.guildMemberCredit.create({ + data: { + guildId: guild.id, + userId: toUser.id, + balance: 0, + }, + }); + } + + const remainingBalance = 2147483647 - amount; + + if (fromTransaction.balance < amount) { + throw new Error("The sender does not have enough credits."); + } + + await this.validateTransaction(guild, toUser, amount); + + let adjustedAmount = amount; + let overflowAmount = 0; + + if (toTransaction && toTransaction.balance + amount > 2147483647) { + adjustedAmount = 2147483647 - toTransaction.balance; + overflowAmount = amount - adjustedAmount; + } + + await prisma.$transaction(async (tx) => { + await tx.guildMemberCredit.update({ + where: { + guildId_userId: { + guildId: guild.id, + userId: fromUser.id, + }, + }, + data: { + balance: { + decrement: amount, + }, + }, + }); + + if (adjustedAmount > 0) { + await tx.guildMemberCredit.upsert({ + where: { + guildId_userId: { + guildId: guild.id, + userId: toUser.id, + }, + }, + create: { + guildId: guild.id, + userId: toUser.id, + balance: adjustedAmount, + }, + update: { + balance: { + increment: adjustedAmount, + }, + }, + }); + } + + if (overflowAmount > 0) { + await tx.guildMemberCredit.update({ + where: { + guildId_userId: { + guildId: guild.id, + userId: fromUser.id, + }, + }, + data: { + balance: { + increment: overflowAmount, + }, + }, + }); + } + }); + + const updatedFromTransaction = await prisma.guildMemberCredit.findFirst({ + where: { + guildId: guild.id, + userId: fromUser.id, + }, + }); + + const updatedToTransaction = await prisma.guildMemberCredit.findFirst({ + where: { + guildId: guild.id, + userId: toUser.id, + }, + }); + + if (!updatedFromTransaction) { + throw new Error( + "Failed to fetch the updated sender's transaction record." + ); + } + + if (!updatedToTransaction) { + throw new Error( + "Failed to fetch the updated recipient's transaction record." + ); + } + + const transferredAmount = adjustedAmount; + + return { + transferredAmount, + fromTransaction: updatedFromTransaction, + toTransaction: updatedToTransaction, + }; + } catch (error: any) { + logger.error( + `Error in transaction for guild: ${guild.id}, sender: ${fromUser.id}, recipient: ${toUser.id}: ${error.message}` + ); + throw error; + } + } + + async topUsers(guild: Guild, userAmount: number) { + return await prisma.$transaction(async (tx) => { + const topUsers = await prisma.guildMemberCredit.findMany({ + where: { + guildId: guild.id, + }, + orderBy: { + balance: "desc", + }, + take: userAmount, + }); + + // 2. Verify that there are some top users. + if (!topUsers) throw new Error("No top users found"); + + // 3. Return top users. + return topUsers; + }); + } + + async upsertGuildMember(guild: Guild, user: User) { + await prisma.guildMember.upsert({ + update: {}, + create: { + user: { + connectOrCreate: { + create: { id: user.id }, + where: { id: user.id }, + }, + }, + guild: { + connectOrCreate: { + create: { id: guild.id }, + where: { id: guild.id }, + }, + }, + }, + where: { + guildId_userId: { + guildId: guild.id, + userId: user.id, + }, + }, + }); + } +} + +export default CreditsManager; diff --git a/src/handlers/ReputationManager.ts b/src/handlers/ReputationManager.ts new file mode 100644 index 0000000..93693c3 --- /dev/null +++ b/src/handlers/ReputationManager.ts @@ -0,0 +1,90 @@ +import { User } from "discord.js"; +import prisma from "./prisma"; + +class ReputationManager { + async check(user: User) { + const userData = await prisma.user.upsert({ + where: { id: user.id }, + update: {}, + create: { + id: user.id, + userReputation: { + create: { + positive: 0, + negative: 0, + }, + }, + }, + include: { + userReputation: true, + }, + }); + + const userReputation = userData.userReputation; + + if (!userReputation) { + return { + total: 0, + positive: 0, + negative: 0, + }; + } + + return { + total: userReputation.positive - userReputation.negative, + positive: userReputation.positive, + negative: userReputation.negative, + }; + } + + async repute(user: User, type: "positive" | "negative") { + const userData = await prisma.user.upsert({ + where: { id: user.id }, + update: {}, + create: { + id: user.id, + userReputation: { + create: { + positive: 0, + negative: 0, + }, + }, + }, + include: { + userReputation: true, + }, + }); + + let userReputation: any = {}; + + if (!userData.userReputation) return null; + + if (type === "positive") { + userReputation = await prisma.userReputation.upsert({ + where: { id: userData.userReputation.id }, + update: { positive: { increment: 1 } }, + create: { + positive: 1, + negative: 0, + user: { connect: { id: user.id } }, + }, + }); + } + + if (type === "negative") { + userReputation = await prisma.userReputation.upsert({ + where: { id: userData.userReputation.id }, + update: { negative: { increment: 1 } }, + create: { + positive: 0, + negative: 1, + user: { connect: { id: user.id } }, + }, + }); + } + + return userReputation; + } +} + +export default ReputationManager; diff --git a/src/handlers/command/index.ts b/src/handlers/command/index.ts deleted file mode 100644 index 3d9c083..0000000 --- a/src/handlers/command/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* eslint-disable no-loops/no-loops */ -import { Client } from "discord.js"; -import checkDirectory from "../../helpers/checkDirectory"; -import { ICommand } from "../../interfaces/Command"; -import logger from "../../middlewares/logger"; - -// Register the commands. -export const register = async (client: Client) => { - logger.info("🔧 Started command management"); - - const commandNames = await checkDirectory("commands"); - if (!commandNames) return logger.warn("No available commands found"); - - const totalCommands = commandNames.length; - let loadedCommands = 0; - - logger.info(`🔧 Loading ${totalCommands} commands`); - - // Import an command. - const importCommand = async (name: string) => { - const command: ICommand = await import(`../../commands/${name}`); - - client.commands.set(command.builder.name, command); - return loadedCommands++; - }; - - for await (const commandName of commandNames) { - await importCommand(commandName).then(() => { - return logger.verbose(`🔧 Loaded command "${commandName}"`); - }); - - if (loadedCommands === totalCommands) { - return logger.info("🔧 All commands loaded"); - } - } - return true; -}; diff --git a/src/handlers/database/index.ts b/src/handlers/database/index.ts deleted file mode 100644 index dff0994..0000000 --- a/src/handlers/database/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { PrismaClient } from "@prisma/client"; -import logger from "../../middlewares/logger"; - -const prisma = new PrismaClient(); - -prisma.$use(async (params, next) => { - const before = Date.now(); - - const result = await next(params); - - const after = Date.now(); - - logger.debug( - `Query ${params.model}.${params.action} took ${after - before}ms` - ); - - return result; -}); - -export default prisma; diff --git a/src/handlers/deferReply/index.ts b/src/handlers/deferReply/index.ts deleted file mode 100644 index 1029879..0000000 --- a/src/handlers/deferReply/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { BaseInteraction, EmbedBuilder } from "discord.js"; -import getEmbedConfig from "../../helpers/getEmbedData"; - -export default async (interaction: BaseInteraction, ephemeral: boolean) => { - if (!interaction.isRepliable()) - throw new Error(`Cannot reply to an interaction that is not repliable`); - - await interaction.deferReply({ - ephemeral, - }); - - const embedConfig = await getEmbedConfig(interaction.guild); - - await interaction.editReply({ - embeds: [ - new EmbedBuilder() - .setFooter({ - text: embedConfig.footerText, - iconURL: embedConfig.footerIcon, - }) - .setTimestamp(new Date()) - .setTitle("⏳︱Your request are being processed") - .setColor(embedConfig.waitColor) - .setDescription("This might take a while, please wait..."), - ], - }); -}; diff --git a/src/handlers/deployCommands/index.ts b/src/handlers/deployCommands/index.ts deleted file mode 100644 index 94feecf..0000000 --- a/src/handlers/deployCommands/index.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Client, RESTPostAPIApplicationCommandsJSONBody } from "discord.js"; -import { ICommand } from "../../interfaces/Command"; -import logger from "../../middlewares/logger"; - -export default async (client: Client) => { - // 1. Destructure the client. - const { application } = client; - if (!application) throw new Error("No application found"); - - // 2. Log that we are starting the command management. - logger.info("🔧 Started command deployment"); - - // 3. Get the commands. - const commands: Array = []; - client.commands.forEach((command: ICommand) => { - commands.push(command.builder.toJSON()); - - logger.verbose(`🔧 Loaded command "${command.builder.name}"`); - }); - - // 4. Set the commands. - await application.commands.set(commands).then(() => { - logger.info("🔧 Deployed commands globally"); - }); - - // 5. Tell the user that development mode is enabled. - if (process.env.NODE_ENV === "development") { - logger.info("🔧 Development mode enabled"); - - await application.commands - .set(commands, process.env.DISCORD_GUILD_ID) - .then(() => { - logger.info(`🔧 Deployed commands to guild`); - }); - } - - // 6. Log that we are done with the command management. - logger.info("🔧 Finished command deployment"); -}; diff --git a/src/handlers/event/index.ts b/src/handlers/event/index.ts deleted file mode 100644 index 2048cd4..0000000 --- a/src/handlers/event/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* eslint-disable no-loops/no-loops */ -import { Client } from "discord.js"; -import checkDirectory from "../../helpers/checkDirectory"; -import { IEvent } from "../../interfaces/Event"; -import logger from "../../middlewares/logger"; - -// Registers all available events. -export const register = async (client: Client) => { - logger.info("📡 Started event management"); - - const eventNames = await checkDirectory("events"); - if (!eventNames) return logger.warn("No available events found"); - - const totalEvents = eventNames.length; - let loadedEvents = 0; - - logger.info(`📡 Loading ${totalEvents} events`); - - // Import an event. - const importEvent = async (name: string) => { - const event: IEvent = await import(`../../events/${name}`); - - // Create a new event execute function. - const eventExecutor = async (...args: Promise[]) => { - await event.execute(...args); - }; - - switch (event.options.type) { - case "once": - client.once(name, eventExecutor); - break; - - case "on": - client.on(name, eventExecutor); - break; - default: - throw new Error(`📡 Invalid event type for event: ${name}`); - } - - return loadedEvents++; - }; - - for await (const eventName of eventNames) { - await importEvent(eventName).then(() => { - return logger.verbose(`📡 Loaded event "${eventName}"`); - }); - - if (loadedEvents === totalEvents) { - return logger.info("📡 All events loaded"); - } - } - - return true; -}; diff --git a/src/handlers/executeSubcommand.ts b/src/handlers/executeSubcommand.ts new file mode 100644 index 0000000..06a6e0c --- /dev/null +++ b/src/handlers/executeSubcommand.ts @@ -0,0 +1,37 @@ +import { ChatInputCommandInteraction } from "discord.js"; + +export interface SubcommandHandlers { + [subcommand: string]: ( + interaction: ChatInputCommandInteraction + ) => Promise; +} + +export interface SubcommandGroupHandlers { + [subcommandGroup: string]: SubcommandHandlers; +} + +export const executeSubcommand = async ( + interaction: ChatInputCommandInteraction, + subcommandHandlers: SubcommandHandlers, + subcommandGroupHandlers?: SubcommandGroupHandlers +) => { + const subcommandGroup = interaction.options.getSubcommandGroup(); + if (subcommandGroupHandlers && subcommandGroup) { + const handlers = subcommandGroupHandlers?.[subcommandGroup]; + if (handlers) { + await executeSubcommand(interaction, handlers); + return; + } else { + throw new Error(`Subcommand group not found: ${subcommandGroup}`); + } + } + + const subcommand = interaction.options.getSubcommand(); + const handler = subcommandHandlers[subcommand]; + + if (handler) { + await handler(interaction); + } else { + throw new Error(`Subcommand not found: ${subcommand}`); + } +}; diff --git a/src/handlers/handleGuildMemberJoin.ts b/src/handlers/handleGuildMemberJoin.ts new file mode 100644 index 0000000..7440b2d --- /dev/null +++ b/src/handlers/handleGuildMemberJoin.ts @@ -0,0 +1,18 @@ +import { Guild, User } from "discord.js"; +import upsertGuildMember from "../helpers/upsertGuildMember"; +import logger from "../utils/logger"; + +const handleGuildMemberJoin = async (guild: Guild, user: User) => { + try { + // Create the user + await upsertGuildMember(guild, user); + + // Example: Logging the guild member join event + logger.info(`User ${user.tag} joined guild ${guild.name} (${guild.id}).`); + } catch (error) { + // Handle any errors that occur during the guild member join event handling + logger.error(`Error handling guild member join: ${error}`); + } +}; + +export default handleGuildMemberJoin; diff --git a/src/handlers/interactionErrorHandler.ts b/src/handlers/interactionErrorHandler.ts new file mode 100644 index 0000000..3345e1f --- /dev/null +++ b/src/handlers/interactionErrorHandler.ts @@ -0,0 +1,55 @@ +import { + ActionRowBuilder, + ButtonBuilder, + ButtonInteraction, + ButtonStyle, + CommandInteraction, + EmbedBuilder, + codeBlock, +} from "discord.js"; +import sendResponse from "../utils/sendResponse"; + +export default async ( + interaction: CommandInteraction | ButtonInteraction, + error: unknown +) => { + if (error instanceof Error) { + const buttons = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setLabel("Report Problem") + .setStyle(ButtonStyle.Link) + .setEmoji("✏️") + .setURL("https://discord.zyner.org") + ); + + const errorEmbed = new EmbedBuilder() + .setAuthor({ name: "⚠️ | Request Failed" }) + .setDescription( + "An error occurred while processing your request. Please try again later." + ) + .setColor("#FFCC66") + .setTimestamp(); + + if (error.message !== undefined) { + errorEmbed.addFields({ + name: "Error Message", + value: codeBlock(error.message), + }); + } + + if (process.env.NODE_ENV === "development" && error.stack !== undefined) { + errorEmbed.addFields({ + name: "Error Stack", + value: codeBlock(error.stack), + }); + } + + const response = { + embeds: [errorEmbed], + components: [buttons], + ephemeral: true, + }; + + await sendResponse(interaction, response); + } +}; diff --git a/src/handlers/prisma.ts b/src/handlers/prisma.ts new file mode 100644 index 0000000..030c862 --- /dev/null +++ b/src/handlers/prisma.ts @@ -0,0 +1,43 @@ +import { PrismaClient } from "@prisma/client"; +import logger from "../utils/logger"; + +const prisma = new PrismaClient(); +const LATENCY_THRESHOLD = 1000; // Threshold in milliseconds + +prisma.$use(async (params, next) => { + const before = Date.now(); + try { + const result = await next(params); + const after = Date.now(); + const duration = after - before; + + logger.debug({ + message: `Query ${params.model}.${params.action} took ${duration}ms`, + duration, + model: params.model, + action: params.action, + }); + + if (duration > LATENCY_THRESHOLD) { + logger.warn({ + message: `High latency query: ${params.model}.${params.action}`, + duration, + model: params.model, + action: params.action, + }); + } + + return result; + } catch (error) { + logger.error({ + message: `Error executing query ${params.model}.${params.action}`, + error, + model: params.model, + action: params.action, + }); + + throw error; + } +}); + +export default prisma; diff --git a/src/handlers/registerCommands.ts b/src/handlers/registerCommands.ts new file mode 100644 index 0000000..f99d54e --- /dev/null +++ b/src/handlers/registerCommands.ts @@ -0,0 +1,65 @@ +import { Client, RESTPostAPIApplicationCommandsJSONBody } from "discord.js"; +import { ICommand } from "../interfaces/Command"; +import logger from "../utils/logger"; +import checkDirectory from "../utils/readDirectory"; + +export default async (client: Client) => { + const profiler = logger.startTimer(); + const { application } = client; + + if (!application) throw new Error("No application found"); + + const builders: RESTPostAPIApplicationCommandsJSONBody[] = []; + + const commandNames = await checkDirectory("commands"); + + await Promise.all( + commandNames.map(async (commandName) => { + const commandProfiler = logger.startTimer(); + + try { + const command: ICommand = await import(`../commands/${commandName}`); + const commandBuilder = command.builder.toJSON(); + + const existingCommand = client.commands.get(commandBuilder.name); + if (existingCommand) { + client.commands.delete(commandBuilder.name); + commandProfiler.done({ + message: `Removed existing command '${commandBuilder.name}'`, + commandName, + level: "debug", + }); + } + + client.commands.set(commandBuilder.name, command); + builders.push(commandBuilder); + + commandProfiler.done({ + commandName, + message: `Registered command '${commandBuilder.name}'`, + level: "debug", + }); + } catch (error) { + commandProfiler.done({ + message: `Failed to register command '${commandName}'`, + commandName, + error, + level: "error", + }); + } + }) + ); + + await Promise.all([ + application.commands.set(builders), + process.env.NODE_ENV === "development" + ? application.commands.set(builders, process.env.DISCORD_GUILD_ID) + : Promise.resolve(), + ]).then(() => { + logger.info({ builders, message: "Registered commands!" }); + }); + + return profiler.done({ + message: "Successfully registered all commands!", + }); +}; diff --git a/src/handlers/registerEvents.ts b/src/handlers/registerEvents.ts new file mode 100644 index 0000000..6f6421f --- /dev/null +++ b/src/handlers/registerEvents.ts @@ -0,0 +1,58 @@ +import { Client } from "discord.js"; +import { IEvent } from "../interfaces/Event"; +import logger from "../utils/logger"; +import checkDirectory from "../utils/readDirectory"; + +export default async (client: Client) => { + const profiler = logger.startTimer(); + + try { + const eventNames = await checkDirectory("events"); + + const importEvent = async (name: string) => { + try { + const event = (await import(`../events/${name}`)) as IEvent; + + const eventExecutor = async (...args: Promise[]) => { + try { + await event.execute(...args); + } catch (error) { + logger.error(`Error occurred in event '${name}':`, error); + } + }; + + switch (event.options.type) { + case "once": + client.once(name, eventExecutor); + break; + case "on": + client.on(name, eventExecutor); + break; + default: + throw new Error(`Unknown event type: ${event.options.type}`); + } + + logger.debug({ + eventName: name, + type: event.options.type, + message: `Listening to event '${name}'`, + }); + + return event; + } catch (error) { + logger.error( + `Error occurred while registering event '${name}':`, + error + ); + } + }; + + await Promise.all(eventNames.map(importEvent)); + + profiler.done({ + message: "Successfully listening to all events!", + }); + } catch (error) { + logger.error("Error occurred during event registration:", error); + } +}; diff --git a/src/handlers/schedule/index.ts b/src/handlers/schedule/index.ts deleted file mode 100644 index de32418..0000000 --- a/src/handlers/schedule/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Client } from "discord.js"; -import schedule from "node-schedule"; -import checkDirectory from "../../helpers/checkDirectory"; -import { IJob } from "../../interfaces/Job"; -import logger from "../../middlewares/logger"; - -// Start all jobs that are in the schedules directory -export const start = async (client: Client) => { - logger.info("⏰ Started job management"); - - const jobNames = await checkDirectory("schedules"); - if (!jobNames) return logger.warn("⏰ No available jobs found"); - - return await Promise.all( - jobNames.map(async (jobName) => { - const job: IJob = await import(`../../schedules/${jobName}`); - - return schedule.scheduleJob(job.options.schedule, async () => { - logger.verbose(`⏰ Performed the job "${jobName}"`); - await job.execute(client); - }); - }) - ); -}; diff --git a/src/handlers/scheduleJobs.ts b/src/handlers/scheduleJobs.ts new file mode 100644 index 0000000..497bba3 --- /dev/null +++ b/src/handlers/scheduleJobs.ts @@ -0,0 +1,63 @@ +import { Client } from "discord.js"; +import schedule from "node-schedule"; +import { IJob } from "../interfaces/Job"; +import logger from "../utils/logger"; +import checkDirectory from "../utils/readDirectory"; + +export default async (client: Client) => { + const profiler = logger.startTimer(); + + const jobNames = await checkDirectory("jobs"); + + const executeJob = async (job: IJob, jobName: string) => { + const jobProfiler = logger.startTimer(); + try { + await job.execute(client); + jobProfiler.done({ + message: `Successfully executed job '${jobName}'`, + level: "debug", + job, + jobName, + }); + } catch (error) { + jobProfiler.done({ + message: `Failed executing job '${jobName}'`, + level: "debug", + job, + jobName, + }); + } + }; + + const importJob = async (jobName: string) => { + try { + const job = (await import(`../jobs/${jobName}`)) as IJob; + + // Check if the bot is already logged in + if (client.readyAt) { + schedule.scheduleJob(job.options.schedule, () => { + executeJob(job, jobName); + }); + } else { + // Wait for the bot to be ready before scheduling the job + client.once("ready", () => { + schedule.scheduleJob(job.options.schedule, () => { + executeJob(job, jobName); + }); + }); + } + } catch (error) { + logger.warn({ + jobName, + message: `Failed to schedule job ${jobName}`, + error, + }); + } + }; + + await Promise.all(jobNames.map(importJob)); + + return profiler.done({ + message: "Successfully scheduled all jobs!", + }); +}; diff --git a/src/handlers/updatePresence.ts b/src/handlers/updatePresence.ts new file mode 100644 index 0000000..c0e193a --- /dev/null +++ b/src/handlers/updatePresence.ts @@ -0,0 +1,52 @@ +import { ActivitiesOptions, ActivityType, Client } from "discord.js"; +import logger from "../utils/logger"; + +export default async (client: Client) => { + const { guilds, user } = client; + if (!user) { + logger.error("No user found"); + throw new Error("No user found"); + } + + const memberCount = guilds.cache.reduce( + (acc, guild) => acc + (guild.memberCount || 0), + 0 + ); + const guildCount = guilds.cache.size; + + const activities: ActivitiesOptions[] = [ + { + name: `${memberCount} users`, + type: ActivityType.Watching, + }, + { + name: `${guildCount} servers`, + type: ActivityType.Watching, + }, + ]; + + const shuffleArray = (array: T[]): T[] => { + return array.sort(() => Math.random() - 0.5); + }; + + const shuffledActivities = shuffleArray(activities); + const activity = shuffledActivities[0]; + + try { + await user.setActivity(activity); + logger.debug({ + guildCount, + memberCount, + message: "Presence updated", + activity, + }); + } catch (error) { + logger.error({ + guildCount, + memberCount, + message: "Failed to update presence", + error, + }); + throw new Error("Failed to update presence"); + } +}; diff --git a/src/handlers/updatePresence/index.ts b/src/handlers/updatePresence/index.ts deleted file mode 100644 index 9fdb486..0000000 --- a/src/handlers/updatePresence/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Dependencies -import { ActivityType, Client } from "discord.js"; -import logger from "../../middlewares/logger"; - -// Function -export default (client: Client) => { - // 1. Destructure the client. - const { guilds, user } = client; - if (!user) throw new Error("No user found"); - - // 2. Get the total number of guilds and members. - const memberCount = guilds.cache.reduce((a, g) => a + g.memberCount, 0); - const guildCount = guilds.cache.size; - - // 3. Set the presence. - user.setPresence({ - activities: [ - { - name: `${guildCount} guilds | ${memberCount} members`, - type: ActivityType.Watching, - }, - ], - }); - - // 4. Log the presence. - return logger.info( - `👀 Presence set to "${guildCount} guilds | ${memberCount} members"` - ); -}; diff --git a/src/helpers/baseEmbeds/index.ts b/src/helpers/baseEmbeds/index.ts deleted file mode 100644 index 5e7b94a..0000000 --- a/src/helpers/baseEmbeds/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { EmbedBuilder, Guild } from "discord.js"; -import getEmbedData from "../getEmbedData"; - -// Construct a base embed for success messages -export const success = async (guild: Guild | null, title: string) => { - const { successColor, footerText, footerIcon } = await getEmbedData(guild); - - return new EmbedBuilder() - .setTimestamp(new Date()) - .setTitle(title) - .setColor(successColor) - .setFooter({ text: footerText, iconURL: footerIcon }); -}; - -// Construct a base embed for wait messages -export const wait = async (guild: Guild | null, title: string) => { - const { waitColor, footerText, footerIcon } = await getEmbedData(guild); - - return new EmbedBuilder() - .setTimestamp(new Date()) - .setTitle(title) - .setColor(waitColor) - .setFooter({ text: footerText, iconURL: footerIcon }); -}; - -// Construct a base embed for error messages -export const error = async (guild: Guild | null, title: string) => { - const { errorColor, footerText, footerIcon } = await getEmbedData(guild); - - return new EmbedBuilder() - .setTimestamp(new Date()) - .setTitle(title) - .setColor(errorColor) - .setFooter({ text: footerText, iconURL: footerIcon }); -}; diff --git a/src/helpers/capitalizeFirstLetter/index.ts b/src/helpers/capitalizeFirstLetter/index.ts deleted file mode 100644 index 1190b36..0000000 --- a/src/helpers/capitalizeFirstLetter/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default (text: string): string => { - return text.charAt(0).toUpperCase() + text.slice(1); -}; diff --git a/src/helpers/checkDirectory/index.ts b/src/helpers/checkDirectory/index.ts deleted file mode 100644 index 5160e63..0000000 --- a/src/helpers/checkDirectory/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import fs from "fs"; -const fsPromises = fs.promises; - -export default async (path: string) => { - const result = await fsPromises.readdir(`${__dirname}/../../${path}`); - return result; -}; diff --git a/src/helpers/checkPermission/index.ts b/src/helpers/checkPermission/index.ts deleted file mode 100644 index a14c82d..0000000 --- a/src/helpers/checkPermission/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { BaseInteraction, PermissionResolvable } from "discord.js"; - -export default ( - interaction: BaseInteraction, - permission: PermissionResolvable -) => { - if (!interaction.memberPermissions) - throw new Error("Could not check user for permissions"); - - if (!interaction.memberPermissions.has(permission)) - throw new Error("Permission denied"); -}; diff --git a/src/helpers/credits/give.ts b/src/helpers/credits/give.ts deleted file mode 100644 index 04395ed..0000000 --- a/src/helpers/credits/give.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Guild, User } from "discord.js"; -import prisma from "../../handlers/database"; -import transactionRules from "./transactionRules"; - -export default async (guild: Guild, user: User, amount: number) => { - return await prisma.$transaction(async (tx) => { - // 1. Check if the transaction is valid. - transactionRules(guild, user, amount); - - // 2. Make the transaction. - const recipient = await tx.guildMember.upsert({ - update: { - creditsEarned: { - increment: amount, - }, - }, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - creditsEarned: amount, - }, - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - }); - - // 3. Verify that the recipient actually is created. - if (!recipient) throw new Error("No recipient available"); - - // 4. Return the recipient. - return recipient; - }); -}; diff --git a/src/helpers/credits/set.ts b/src/helpers/credits/set.ts deleted file mode 100644 index c8053e0..0000000 --- a/src/helpers/credits/set.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Guild, User } from "discord.js"; -import prisma from "../../handlers/database"; -import transactionRules from "./transactionRules"; - -export default async (guild: Guild, user: User, amount: number) => { - return await prisma.$transaction(async (tx) => { - // 1. Check if the transaction is valid. - transactionRules(guild, user, amount); - - // 2. Make the transaction. - const recipient = await tx.guildMember.upsert({ - update: { - creditsEarned: amount, - }, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - creditsEarned: amount, - }, - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - }); - - // 3. Verify that the recipient actually is created. - if (!recipient) throw new Error("No recipient available"); - - // 4. Return the recipient. - return recipient; - }); -}; diff --git a/src/helpers/credits/take.ts b/src/helpers/credits/take.ts deleted file mode 100644 index 7b97e2b..0000000 --- a/src/helpers/credits/take.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Guild, User } from "discord.js"; -import prisma from "../../handlers/database"; -import transactionRules from "./transactionRules"; - -export default async (guild: Guild, user: User, amount: number) => { - return await prisma.$transaction(async (tx) => { - // 1. Check if the transaction is valid. - transactionRules(guild, user, amount); - - // 2. Make the transaction. - const recipient = await tx.guildMember.upsert({ - update: { - creditsEarned: { - decrement: amount, - }, - }, - create: { - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - creditsEarned: -amount, - }, - where: { - userId_guildId: { - userId: user.id, - guildId: guild.id, - }, - }, - }); - - // 3. Verify that the recipient credits are not below zero. - if (recipient.creditsEarned < -100) - throw new Error("User do not have enough credits"); - - // 4. Return the recipient. - return recipient; - }); -}; diff --git a/src/helpers/credits/transactionRules.ts b/src/helpers/credits/transactionRules.ts deleted file mode 100644 index ea9d7b1..0000000 --- a/src/helpers/credits/transactionRules.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Guild, User } from "discord.js"; - -export default (guild: Guild, user: User, amount: number) => { - // 1. Verify that the amount is not above 100.000.000 credits. - if (amount > 100000000) { - throw new Error("You can't give more than 1.000.000 credits."); - } - - // 2. Verify that the amount is not below 1 credits. - if (amount <= 0) { - throw new Error("You can't give below one credit."); - } - - // 3. Verify that the user is not an bot. - if (user.bot) { - throw new Error("You can't give to an bot."); - } -}; diff --git a/src/helpers/credits/transfer.ts b/src/helpers/credits/transfer.ts deleted file mode 100644 index c85518e..0000000 --- a/src/helpers/credits/transfer.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { Guild, User } from "discord.js"; -import prisma from "../../handlers/database"; -import transactionRules from "./transactionRules"; - -export default async (guild: Guild, from: User, to: User, amount: number) => { - return await prisma.$transaction(async (tx) => { - // 1. Decrement amount from the sender. - const sender = await tx.guildMember.upsert({ - update: { - creditsEarned: { - decrement: amount, - }, - }, - create: { - user: { - connectOrCreate: { - create: { - id: from.id, - }, - where: { - id: from.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - creditsEarned: -amount, - }, - where: { - userId_guildId: { - userId: from.id, - guildId: guild.id, - }, - }, - }); - - // 4. Verify that the sender's balance didn't go below zero. - if (sender.creditsEarned < 0) { - throw new Error(`${from} doesn't have enough to send ${amount}`); - } - - // 5. Check if the transactions is valid. - transactionRules(guild, from, amount); - transactionRules(guild, to, amount); - - // 6. Verify that sender and recipient are not the same user. - if (from.id === to.id) throw new Error("You can't transfer to yourself."); - - // 7. Increment the recipient's balance by amount. - const recipient = await tx.guildMember.upsert({ - update: { - creditsEarned: { - increment: amount, - }, - }, - create: { - user: { - connectOrCreate: { - create: { - id: to.id, - }, - where: { - id: to.id, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - creditsEarned: amount, - }, - where: { - userId_guildId: { - userId: to.id, - guildId: guild.id, - }, - }, - }); - - return recipient; - }); -}; diff --git a/src/helpers/encryption/index.ts b/src/helpers/encryption/index.ts deleted file mode 100644 index 1b9fc34..0000000 --- a/src/helpers/encryption/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -import crypto from "crypto"; -import { IEncryptionData } from "../../interfaces/EncryptionData"; - -const iv = crypto.randomBytes(16); - -// Encrypts a string -const encrypt = (text: crypto.BinaryLike): IEncryptionData => { - const cipher = crypto.createCipheriv( - process.env.ENCRYPTION_ALGORITHM, - process.env.ENCRYPTION_SECRET, - iv - ); - const encrypted = Buffer.concat([cipher.update(text), cipher.final()]); - - return { - iv: iv.toString("hex"), - content: encrypted.toString("hex"), - }; -}; - -// Decrypts a string -const decrypt = (hash: IEncryptionData) => { - const decipher = crypto.createDecipheriv( - process.env.ENCRYPTION_ALGORITHM, - process.env.ENCRYPTION_SECRET, - Buffer.from(hash.iv, "hex") - ); - - const decrypted = Buffer.concat([ - decipher.update(Buffer.from(hash.content, "hex")), - decipher.final(), - ]); - - return decrypted.toString(); -}; - -export default { - encrypt, - decrypt, -}; diff --git a/src/helpers/generateCooldownName.ts b/src/helpers/generateCooldownName.ts new file mode 100644 index 0000000..31a636a --- /dev/null +++ b/src/helpers/generateCooldownName.ts @@ -0,0 +1,16 @@ +import { ChatInputCommandInteraction, CommandInteraction } from "discord.js"; + +export default async (interaction: CommandInteraction) => { + const { commandName } = interaction; + + if (interaction instanceof ChatInputCommandInteraction) { + const subcommandGroup = interaction.options.getSubcommandGroup(); + const subcommand = interaction.options.getSubcommand(); + + return subcommandGroup + ? `${commandName}-${subcommandGroup}-${subcommand}` + : `${commandName}-${subcommand}`; + } + + return commandName; +}; diff --git a/src/helpers/getEmbedData/index.ts b/src/helpers/getEmbedData/index.ts deleted file mode 100644 index 069ce9b..0000000 --- a/src/helpers/getEmbedData/index.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { ColorResolvable, Guild } from "discord.js"; -import prisma from "../../handlers/database"; -import logger from "../../middlewares/logger"; - -export default async (guild?: Guild | null) => { - const { - EMBED_COLOR_SUCCESS, - EMBED_COLOR_WAIT, - EMBED_COLOR_ERROR, - EMBED_FOOTER_TEXT, - EMBED_FOOTER_ICON, - } = process.env; - - const defaultEmbedConfig = { - successColor: EMBED_COLOR_SUCCESS, - waitColor: EMBED_COLOR_WAIT, - errorColor: EMBED_COLOR_ERROR, - footerText: EMBED_FOOTER_TEXT, - footerIcon: EMBED_FOOTER_ICON, - }; - - if (!guild) { - return defaultEmbedConfig; - } - - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId: guild?.ownerId, - guildId: guild.id, - }, - }, - update: {}, - create: { - user: { - connectOrCreate: { - create: { - id: guild.ownerId, - }, - where: { - id: guild.ownerId, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - - logger.silly(createGuildMember); - - if (!createGuildMember) { - return defaultEmbedConfig; - } - - return { - successColor: createGuildMember.guild.embedColorSuccess, - waitColor: createGuildMember.guild.embedColorWait, - errorColor: createGuildMember.guild.embedColorError, - footerText: createGuildMember.guild.embedFooterText, - footerIcon: createGuildMember.guild.embedFooterIcon, - }; -}; diff --git a/src/helpers/pluralize/index.ts b/src/helpers/pluralize/index.ts deleted file mode 100644 index 10a6796..0000000 --- a/src/helpers/pluralize/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import logger from "../../middlewares/logger"; - -export default (count: number, noun: string, suffix?: string): string => { - const result = `${count} ${noun}${count !== 1 ? suffix || "s" : ""}`; - logger?.silly(`Pluralized ${count} to ${result}`); - return result; -}; diff --git a/src/helpers/upsertApiCredentials.ts b/src/helpers/upsertApiCredentials.ts new file mode 100644 index 0000000..02d635a --- /dev/null +++ b/src/helpers/upsertApiCredentials.ts @@ -0,0 +1,27 @@ +import { Prisma } from "@prisma/client"; +import { Guild } from "discord.js"; +import prisma from "../handlers/prisma"; + +export const upsertApiCredentials = async ( + guild: Guild, + apiName: string, + credentials: + | Prisma.NullTypes.JsonNull + | Prisma.InputJsonValue + | Prisma.JsonObject + | Prisma.InputJsonObject +) => { + await prisma.apiCredentials.upsert({ + where: { + guildId_apiName: { guildId: guild.id, apiName }, + }, + create: { + guildId: guild.id, + apiName, + credentials, + }, + update: { + credentials, + }, + }); +}; diff --git a/src/helpers/upsertGuildMember/index.ts b/src/helpers/upsertGuildMember.ts similarity index 72% rename from src/helpers/upsertGuildMember/index.ts rename to src/helpers/upsertGuildMember.ts index 22a90a2..aff9bd7 100644 --- a/src/helpers/upsertGuildMember/index.ts +++ b/src/helpers/upsertGuildMember.ts @@ -1,14 +1,12 @@ -import { GuildMember } from "discord.js"; -import db from "../../handlers/database"; - -export default async (guildMember: GuildMember) => { - const { guild, user } = guildMember; +import { Guild, User } from "discord.js"; +import db from "../handlers/prisma"; +export default async (guild: Guild, user: User) => { return await db.guildMember.upsert({ where: { - userId_guildId: { - userId: user.id, + guildId_userId: { guildId: guild.id, + userId: user.id, }, }, update: {}, diff --git a/src/index.ts b/src/index.ts index b58112b..dd2f483 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,32 +1,27 @@ -import { Client, Collection, GatewayIntentBits } from "discord.js"; // discord.js +import { Client, Collection, GatewayIntentBits } from "discord.js"; import "dotenv/config"; +import registerEvents from "./handlers/registerEvents"; +import scheduleJobs from "./handlers/scheduleJobs"; +import logger from "./utils/logger"; -import { register as commandRegister } from "./handlers/command"; -import { register as eventRegister } from "./handlers/event"; -import { start as scheduleStart } from "./handlers/schedule"; -// Main process that starts all other sub processes -const main = async () => { - // Initiate client object - const client = new Client({ - intents: [ - GatewayIntentBits.Guilds, - GatewayIntentBits.GuildMembers, - GatewayIntentBits.GuildMessages, - GatewayIntentBits.MessageContent, - ], - }); +(async () => { + try { + const client = new Client({ + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMembers, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.MessageContent, + ], + }); - // Create command collection - client.commands = new Collection(); + client.commands = new Collection(); - // Start critical handlers - await scheduleStart(client); - await eventRegister(client); - await commandRegister(client); + await registerEvents(client); + await scheduleJobs(client); - // Authorize with Discord's API - await client.login(process.env.DISCORD_TOKEN); -}; - -// Start main process -main(); + await client.login(process.env.DISCORD_TOKEN); + } catch (error) { + logger.error("An error occurred in the main process:", error); + } +})(); diff --git a/src/interfaces/EncryptionData.ts b/src/interfaces/EncryptionData.ts deleted file mode 100644 index ac41844..0000000 --- a/src/interfaces/EncryptionData.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface IEncryptionData { - iv: string; - content: string; -} diff --git a/src/jobs/updatePresence.ts b/src/jobs/updatePresence.ts new file mode 100644 index 0000000..83d6ded --- /dev/null +++ b/src/jobs/updatePresence.ts @@ -0,0 +1,11 @@ +import { Client } from "discord.js"; + +import updatePresence from "../handlers/updatePresence"; + +export const options = { + schedule: "*/1 * * * *", // https://crontab.guru/ +}; + +export const execute = async (client: Client) => { + updatePresence(client); +}; diff --git a/src/middlewares/cooldown/index.ts b/src/middlewares/cooldown/index.ts deleted file mode 100644 index 09eb5be..0000000 --- a/src/middlewares/cooldown/index.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { add, formatDuration, intervalToDuration, isPast } from "date-fns"; -import { Guild, User } from "discord.js"; -import prisma from "../../handlers/database"; -import logger from "../logger"; - -export default async ( - guild: Guild, - user: User, - id: string, - cooldown: number, - silent?: boolean -) => { - // Check if user has a timeout - const isOnCooldown = await prisma.cooldown.findUnique({ - where: { - guildId_userId_timeoutId: { - guildId: guild.id, - userId: user.id, - timeoutId: id, - }, - }, - }); - logger.silly(isOnCooldown); - - if (isOnCooldown) { - const { userId, timeoutId, createdAt } = isOnCooldown; - const dueDate = add(createdAt, { seconds: cooldown }); - - const duration = formatDuration( - intervalToDuration({ - start: new Date(), - end: dueDate, - }) - ); - - if (isPast(dueDate)) { - return await prisma.cooldown.delete({ - where: { - guildId_userId_timeoutId: { - guildId: guild.id, - userId: user.id, - timeoutId: id, - }, - }, - }); - } - - if (silent) { - return logger.verbose( - `User ${userId} is on cooldown for ${timeoutId}, it ends in ${duration}.` - ); - } - - throw new Error( - `You need to wait for ${duration} before you can do that again` - ); - } - - const createCooldown = await prisma.cooldown.upsert({ - where: { - guildId_userId_timeoutId: { - userId: user.id, - guildId: guild.id, - timeoutId: id, - }, - }, - update: {}, - create: { - guild: { - connectOrCreate: { - create: { - id: guild.id, - }, - where: { - id: guild.id, - }, - }, - }, - user: { - connectOrCreate: { - create: { - id: user.id, - }, - where: { - id: user.id, - }, - }, - }, - timeoutId: id, - cooldown, - }, - }); - - logger.silly(createCooldown); - - return createCooldown; -}; diff --git a/src/middlewares/logger/index.ts b/src/middlewares/logger/index.ts deleted file mode 100644 index a91f01d..0000000 --- a/src/middlewares/logger/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import winston from "winston"; -import "winston-daily-rotate-file"; - -const { combine, timestamp, printf, errors, colorize, align, json } = - winston.format; - -export default winston.createLogger({ - level: process.env.LOG_LEVEL || "info", - transports: [ - new winston.transports.DailyRotateFile({ - filename: "logs/combined-%DATE%.log", - datePattern: "YYYY-MM-DD", - maxFiles: "14d", - format: combine(timestamp(), json()), - }), - new winston.transports.Console({ - format: combine( - errors({ stack: true, trace: true }), // <-- use errors format - colorize({ all: true }), - timestamp({ - format: "YYYY-MM-DD HH:MM:ss", - }), - align(), - printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`) - ), - }), - ], -}); diff --git a/src/schedules/cooldowns/index.ts b/src/schedules/cooldowns/index.ts deleted file mode 100644 index c825cc9..0000000 --- a/src/schedules/cooldowns/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* eslint-disable no-loops/no-loops */ -import { add, formatDuration, intervalToDuration, isPast } from "date-fns"; - -import prisma from "../../handlers/database"; -import logger from "../../middlewares/logger"; - -export const options = { - schedule: "*/30 * * * *", // https://crontab.guru/ -}; - -// Execute the job -export const execute = async () => { - const cooldownsObj = await prisma.cooldown.findMany(); - - for await (const cooldownObj of cooldownsObj) { - const { guildId, userId, timeoutId, cooldown, createdAt } = cooldownObj; - - const dueDate = add(createdAt, { seconds: cooldown }); - if (!isPast(dueDate)) return; - - const duration = formatDuration( - intervalToDuration({ - start: new Date(), - end: dueDate, - }) - ); - - const deleteCooldown = await prisma.cooldown.delete({ - where: { - guildId_userId_timeoutId: { - guildId, - userId, - timeoutId, - }, - }, - }); - logger.silly(deleteCooldown); - - logger.verbose( - `User ${userId} is on cooldown for ${timeoutId}, it ends in ${duration}.` - ); - } -}; diff --git a/src/schedules/shop/index.ts b/src/schedules/shop/index.ts deleted file mode 100644 index c99a542..0000000 --- a/src/schedules/shop/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Dependencies -import { Client } from "discord.js"; - -import { execute as RolesExecute } from "./modules/roles"; - -export const options = { - schedule: "*/5 * * * *", // https://crontab.guru/ -}; - -// Execute the function -export const execute = async (client: Client) => { - await RolesExecute(client); -}; diff --git a/src/schedules/shop/modules/roles/components/dueForPayment.ts b/src/schedules/shop/modules/roles/components/dueForPayment.ts deleted file mode 100644 index fd08ae7..0000000 --- a/src/schedules/shop/modules/roles/components/dueForPayment.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Client } from "discord.js"; -import logger from "../../../../../middlewares/logger"; - -import { GuildShopRoles } from "@prisma/client"; - -// Execute the dueForPayment function -export const execute = (_client: Client, role: GuildShopRoles) => { - const { roleId } = role; - - logger.silly(`Shop role ${roleId} is not due for payment.`); -}; diff --git a/src/schedules/shop/modules/roles/components/overDueForPayment.ts b/src/schedules/shop/modules/roles/components/overDueForPayment.ts deleted file mode 100644 index 7020db7..0000000 --- a/src/schedules/shop/modules/roles/components/overDueForPayment.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { Client } from "discord.js"; -import logger from "../../../../../middlewares/logger"; - -import { GuildShopRoles } from "@prisma/client"; -import prisma from "../../../../../handlers/database"; - -// Execute the component -export const execute = async (client: Client, role: GuildShopRoles) => { - const { guildId, userId, roleId } = role; - if (!userId) throw new Error("User ID not found for shop role."); - - const rGuild = client.guilds.cache.get(guildId); - if (!rGuild) throw new Error("Guild not found."); - - const rMember = await rGuild.members.fetch(userId); - if (!rMember) throw new Error("Member not found."); - - const rRole = rMember.roles.cache.get(roleId); - if (!rRole) throw new Error("Role not found."); - - logger.debug(`Shop role ${roleId} is due for payment.`); - - const getGuildMember = await prisma.guildMember.findUnique({ - where: { - userId_guildId: { - userId, - guildId, - }, - }, - include: { - user: true, - guild: true, - }, - }); - - logger.silly(getGuildMember); - - if (!getGuildMember) throw new Error("Could not find guild member."); - - const pricePerHour = getGuildMember.guild.shopRolesPricePerHour; - - if (getGuildMember.creditsEarned < pricePerHour) { - await rMember.roles - .remove(roleId) - .then(async () => { - const deleteShopRole = await prisma.guildShopRoles.delete({ - where: { - guildId_userId_roleId: { - guildId, - userId, - roleId, - }, - }, - }); - - logger.silly(deleteShopRole); - - logger.silly( - `Shop role document ${roleId} has been deleted from user ${userId}.` - ); - }) - .catch(() => { - throw new Error(`Failed removing role from user.`); - }); - - throw new Error("User does not have enough credits."); - } - - const createGuildMember = await prisma.guildMember.upsert({ - where: { - userId_guildId: { - userId, - guildId, - }, - }, - update: { creditsEarned: { decrement: pricePerHour } }, - create: { - creditsEarned: -pricePerHour, - user: { - connectOrCreate: { - create: { - id: userId, - }, - where: { - id: userId, - }, - }, - }, - guild: { - connectOrCreate: { - create: { - id: guildId, - }, - where: { - id: guildId, - }, - }, - }, - }, - include: { - user: true, - guild: true, - }, - }); - - logger.silly(createGuildMember); - - logger.silly(`User ${userId} has been updated.`); - - const updateGuildShopRole = await prisma.guildShopRoles.update({ - where: { - guildId_userId_roleId: { - guildId, - userId, - roleId, - }, - }, - data: { - lastPayed: new Date(), - }, - }); - - logger.silly(updateGuildShopRole); - - logger.silly(`Shop role ${roleId} has been updated.`); - - logger.debug(`Shop role ${roleId} has been paid.`); -}; diff --git a/src/schedules/shop/modules/roles/index.ts b/src/schedules/shop/modules/roles/index.ts deleted file mode 100644 index 197cecd..0000000 --- a/src/schedules/shop/modules/roles/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable no-loops/no-loops */ -import { Client } from "discord.js"; -import prisma from "../../../../handlers/database"; - -import { execute as dueForPaymentExecute } from "./components/dueForPayment"; -import { execute as overDueForPaymentExecute } from "./components/overDueForPayment"; - -// Execute the roles function -export const execute = async (client: Client) => { - const roles = await prisma.guildShopRoles.findMany(); - - for await (const role of roles) { - const { lastPayed } = role; - const nextPayment = new Date(lastPayed.setHours(lastPayed.getHours() + 1)); - - const now = new Date(); - - if (nextPayment > now) { - dueForPaymentExecute(client, role); - - return; - } - - if (nextPayment < now) { - await overDueForPaymentExecute(client, role); - } - } -}; diff --git a/src/services/CtrlPanelAPI.ts b/src/services/CtrlPanelAPI.ts new file mode 100644 index 0000000..b85099e --- /dev/null +++ b/src/services/CtrlPanelAPI.ts @@ -0,0 +1,118 @@ +import axios, { AxiosInstance } from "axios"; +import { Guild } from "discord.js"; +import prisma from "../handlers/prisma"; +import { upsertApiCredentials } from "../helpers/upsertApiCredentials"; +import Encryption, { EncryptedData } from "../utils/encryption"; + +const encryption = new Encryption(); + +interface ApiCredentials { + url: EncryptedData; + token: EncryptedData; + [key: string]: EncryptedData | unknown; +} + +export class CtrlPanelAPIError extends Error { + constructor(message: string) { + super(message); + this.name = "CtrlPanelAPIError"; + } +} + +class CtrlPanelAPI { + private guild: Guild; + private apiCredentials: ApiCredentials | null; + private api: AxiosInstance; + + constructor(guild: Guild) { + this.guild = guild; + this.apiCredentials = null; + this.api = axios.create(); + } + + private async fetchApiCredentials(): Promise { + const apiCredentials = await prisma.apiCredentials.findUnique({ + where: { + guildId_apiName: { + guildId: this.guild.id, + apiName: "Ctrlpanel.gg", + }, + }, + }); + + if (!apiCredentials || !apiCredentials.credentials) { + throw new CtrlPanelAPIError( + "API credentials are required for this functionality. Please configure the CtrlPanel.gg API credentials for this guild." + ); + } + + this.apiCredentials = apiCredentials.credentials as ApiCredentials; + } + + private async getPlainUrl(): Promise { + if (!this.apiCredentials) { + throw new CtrlPanelAPIError("API credentials not fetched"); + } + + const { url } = this.apiCredentials; + return await encryption.decrypt(url); + } + + private async getPlainToken(): Promise { + if (!this.apiCredentials) { + throw new CtrlPanelAPIError("API credentials not fetched"); + } + + const { token } = this.apiCredentials; + return await encryption.decrypt(token); + } + + public async generateVoucher( + code: string, + amount: number, + uses: number + ): Promise<{ redeemUrl: string }> { + await this.fetchApiCredentials(); + + const plainUrl = await this.getPlainUrl(); + const plainToken = await this.getPlainToken(); + + this.api.defaults.baseURL = plainUrl; + this.api.defaults.headers.common["Authorization"] = plainToken + ? `Bearer ${plainToken}` + : undefined; + + const shopUrl = `${plainUrl}/store`; + + await this.api.post("vouchers", { + uses, + code, + credits: amount, + memo: `Generated by Discord Bot: ${this.guild.client.user.tag}`, + }); + + return { redeemUrl: `${shopUrl}?voucher=${code}` }; + } + + public async updateApiCredentials( + scheme: string, + domain: string, + tokenData: string + ): Promise { + const url = await encryption.encrypt(`${scheme}://${domain}`); + const token = await encryption.encrypt(tokenData); + + if (!url || !token) { + throw new Error("URL and token must be set"); + } + + const credentials = { + url, + token, + }; + + await upsertApiCredentials(this.guild, "Ctrlpanel.gg", credentials); + } +} + +export default CtrlPanelAPI; diff --git a/src/utils/checkPermission.ts b/src/utils/checkPermission.ts new file mode 100644 index 0000000..0d954a7 --- /dev/null +++ b/src/utils/checkPermission.ts @@ -0,0 +1,9 @@ +import { Interaction, PermissionResolvable } from "discord.js"; + +export default (interaction: Interaction, permission: PermissionResolvable) => { + if (!interaction.memberPermissions) + throw new Error("Failed to check your permissions"); + + if (!interaction.memberPermissions.has(permission)) + throw new Error(`You do not have the required permission: ${permission}`); +}; diff --git a/src/utils/deferReply.ts b/src/utils/deferReply.ts new file mode 100644 index 0000000..0ef6f1b --- /dev/null +++ b/src/utils/deferReply.ts @@ -0,0 +1,28 @@ +import { + ButtonInteraction, + CommandInteraction, + EmbedBuilder, +} from "discord.js"; +import sendResponse from "./sendResponse"; + +export default async ( + interaction: CommandInteraction | ButtonInteraction, + ephemeral: boolean +) => { + if (!interaction.isRepliable()) { + throw new Error("Failed to reply to your request."); + } + + await interaction.deferReply({ ephemeral }); + + await sendResponse(interaction, { + embeds: [ + new EmbedBuilder() + .setTimestamp(new Date()) + .setTitle("🎉︱Hold on tight!") + .setDescription( + "We're working our magic. This might take a while, so prepare to be amazed! ✨" + ), + ], + }); +}; diff --git a/src/utils/encryption.ts b/src/utils/encryption.ts new file mode 100644 index 0000000..4fa9e9e --- /dev/null +++ b/src/utils/encryption.ts @@ -0,0 +1,104 @@ +import crypto, { CipherGCMTypes } from "crypto"; + +export type EncryptedData = { + iv: string; + content: string; + authTag: string; +}; + +class EncryptionError extends Error { + constructor(message: string) { + super(message); + this.name = "EncryptionError"; + } +} + +class Encryption { + private encryptionSecret: Buffer; + private encryptionAlgorithm: CipherGCMTypes; + private encryptionKeyLength: number; + + constructor() { + const encryptionSecret = process.env.ENCRYPTION_SECRET; + + if (!encryptionSecret) { + throw new EncryptionError("Encryption secret is required."); + } + + this.encryptionSecret = crypto + .createHash("sha256") + .update(encryptionSecret) + .digest(); + this.encryptionAlgorithm = "aes-256-gcm"; + this.encryptionKeyLength = 32; + } + + private generateRandomKey(length: number): Buffer { + return crypto.randomBytes(length); + } + + private createCipher(iv: Buffer): crypto.CipherGCM { + const key = this.encryptionSecret.slice(0, this.encryptionKeyLength); + return crypto.createCipheriv(this.encryptionAlgorithm, key, iv); + } + + private createDecipher(iv: Buffer): crypto.DecipherGCM { + const key = this.encryptionSecret.slice(0, this.encryptionKeyLength); + return crypto.createDecipheriv(this.encryptionAlgorithm, key, iv); + } + + private transformData( + data: Buffer, + transform: crypto.CipherGCM | crypto.DecipherGCM + ): Buffer { + return Buffer.concat([transform.update(data), transform.final()]); + } + + public async encrypt(text: string): Promise { + return new Promise((resolve, reject) => { + const iv = this.generateRandomKey(12); + const cipher = this.createCipher(iv); + + let encrypted: Buffer; + let authTag: Buffer; + + try { + encrypted = this.transformData(Buffer.from(text), cipher); + authTag = cipher.getAuthTag(); + } catch (error) { + reject(new EncryptionError("Encryption failed.")); + return; + } + + resolve({ + iv: iv.toString("hex"), + content: encrypted.toString("hex"), + authTag: authTag.toString("hex"), + }); + }); + } + + public async decrypt(data: EncryptedData): Promise { + return new Promise((resolve, reject) => { + const iv = Buffer.from(data.iv, "hex"); + const content = Buffer.from(data.content, "hex"); + const authTag = Buffer.from(data.authTag, "hex"); + + const decipher = this.createDecipher(iv); + decipher.setAuthTag(authTag); + + let decrypted: Buffer; + + try { + decrypted = this.transformData(content, decipher); + } catch (error) { + reject(new EncryptionError("Decryption failed.")); + return; + } + + resolve(decrypted.toString()); + }); + } +} + +export default Encryption; diff --git a/src/utils/logger.ts b/src/utils/logger.ts new file mode 100644 index 0000000..83bce30 --- /dev/null +++ b/src/utils/logger.ts @@ -0,0 +1,42 @@ +import winston from "winston"; +import "winston-daily-rotate-file"; + +const { combine, timestamp, json, errors, colorize, align, printf } = + winston.format; + +const logFormat = printf((info) => { + const formattedMessage = info.stack || info.message; + return `[${info.timestamp}] ${info.level}: ${formattedMessage}`; +}); + +const logger = winston.createLogger({ + level: process.env.LOG_LEVEL || "info", + format: combine( + errors({ stack: true }), + timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), + json() + ), + transports: [ + new winston.transports.DailyRotateFile({ + filename: "logs/combined-%DATE%.log", + datePattern: "YYYY-MM-DD", + maxFiles: "14d", + format: combine( + errors({ stack: true }), + timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), + json() + ), + }), + new winston.transports.Console({ + format: combine( + errors({ stack: true, trace: true }), + colorize({ all: true }), + timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), + align(), + logFormat + ), + }), + ], +}); + +export default logger; diff --git a/src/utils/readDirectory.ts b/src/utils/readDirectory.ts new file mode 100644 index 0000000..be258ab --- /dev/null +++ b/src/utils/readDirectory.ts @@ -0,0 +1,24 @@ +import fs from "fs/promises"; +import path from "path"; +import logger from "./logger"; + +export default async (filePath: string) => { + const directoryPath = path.join(process.cwd(), "dist", filePath); + + try { + const result = await fs.readdir(directoryPath); + logger.debug({ + message: `Checked directory ${filePath}`, + directoryPath, + result, + }); + return result; + } catch (error) { + logger.error({ + message: `Error checking directory ${filePath}`, + error, + directoryPath, + }); + throw new Error(`Error checking directory ${filePath}: ${error}`); + } +}; diff --git a/src/utils/sendResponse.ts b/src/utils/sendResponse.ts new file mode 100644 index 0000000..d6c67f9 --- /dev/null +++ b/src/utils/sendResponse.ts @@ -0,0 +1,32 @@ +import { + ButtonInteraction, + CommandInteraction, + InteractionEditReplyOptions, + InteractionReplyOptions, +} from "discord.js"; +import logger from "./logger"; + +export default async ( + interaction: CommandInteraction | ButtonInteraction, + response: InteractionReplyOptions | InteractionEditReplyOptions | string +) => { + try { + if (interaction instanceof ButtonInteraction) { + await (interaction as ButtonInteraction).reply( + response as InteractionReplyOptions + ); + } else { + if (interaction.deferred) { + await (interaction as CommandInteraction).editReply( + response as InteractionEditReplyOptions + ); + } else { + await (interaction as CommandInteraction).reply( + response as InteractionReplyOptions + ); + } + } + } catch (error) { + logger.error("Error occurred while sending the response:", error); + } +};