├── .gitignore ├── .prettierrc ├── src ├── util │ ├── validate-tree-name.ts │ ├── watering-interval.ts │ ├── tree-height.ts │ ├── leveling.ts │ ├── image-generation.ts │ └── tree-generation.ts ├── commands │ ├── index.ts │ ├── Help.ts │ ├── Ping.ts │ ├── Rename.ts │ ├── About.ts │ ├── Config.ts │ ├── Forest.ts │ ├── Profile.ts │ ├── Plant.ts │ ├── Background.ts │ ├── Leaderboard.ts │ └── Tree.ts ├── models │ ├── Player.ts │ └── Guild.ts └── index.ts ├── .eslintrc ├── tsconfig.json ├── Dockerfile ├── docker-compose.yml ├── README.md ├── package.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | db.pem 3 | 4 | node_modules 5 | dist -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "printWidth": 120 4 | } 5 | -------------------------------------------------------------------------------- /src/util/validate-tree-name.ts: -------------------------------------------------------------------------------- 1 | export function validateTreeName(name: string): boolean { 2 | if (name.length > 36) return false; 3 | if (name.length === 0) return false; 4 | if (!/^[a-zA-Z0-9\-' ]+$/.test(name)) return false; 5 | return true; 6 | } 7 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "plugin:@typescript-eslint/recommended" // Uses the recommended rules from the @typescript-eslint/eslint-plugin 4 | ], 5 | 6 | "parser": "@typescript-eslint/parser", 7 | "parserOptions": { 8 | "ecmaVersion": 2021, 9 | "sourceType": "module" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/commands/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./About"; 2 | export * from "./Background"; 3 | export * from "./Config"; 4 | export * from "./Forest"; 5 | export * from "./Help"; 6 | export * from "./Leaderboard"; 7 | export * from "./Ping"; 8 | export * from "./Plant"; 9 | export * from "./Profile"; 10 | export * from "./Rename"; 11 | export * from "./Tree"; 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | 5 | "lib": ["es2021"], 6 | "target": "es2022", 7 | 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | 11 | "outDir": "./dist", 12 | "declaration": true, 13 | "sourceMap": true 14 | }, 15 | "include": ["src", "tests"], 16 | "exclude": ["node_modules", "dist"] 17 | } 18 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16-alpine AS base 2 | 3 | WORKDIR /usr/app 4 | 5 | # Install dependencies 6 | 7 | COPY package.json . 8 | COPY yarn.lock . 9 | 10 | RUN yarn install 11 | 12 | # Build 13 | FROM base AS builder 14 | 15 | COPY .eslintrc . 16 | COPY .prettierrc . 17 | COPY tsconfig.json . 18 | COPY src src 19 | 20 | RUN yarn build 21 | 22 | # Copy and run 23 | FROM base AS runner 24 | 25 | COPY .env . 26 | COPY --from=builder /usr/app/dist ./dist 27 | 28 | CMD yarn start 29 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | 5 | image-server: 6 | image: gat-image-server:latest 7 | volumes: 8 | - /var/www/tiling-images/trees:/var/www/images 9 | restart: unless-stopped 10 | 11 | mongo: 12 | image: mongo 13 | volumes: 14 | - /opt/databases/grow-a-tree:/data/db 15 | ports: 16 | - "27017:27017" 17 | 18 | redis: 19 | image: redis 20 | 21 | grow-a-tree: 22 | container_name: grow-a-tree 23 | image: grow-a-tree:latest 24 | ports: 25 | - "8089:8080" 26 | restart: unless-stopped 27 | 28 | -------------------------------------------------------------------------------- /src/util/watering-interval.ts: -------------------------------------------------------------------------------- 1 | const cache = new Map(); 2 | 3 | cache.set(1, 0); 4 | cache.set(2, 0); 5 | 6 | export function getWateringInterval(size: number): number { 7 | const cached = cache.has(size); 8 | const result = cached ? cache.get(size) : Math.floor(Math.pow(size * 0.07 + 5, 1.1)); 9 | 10 | if (!cached) cache.set(size, result); 11 | 12 | return result; 13 | } 14 | 15 | export function getTreeAge(size: number): number { 16 | let age = 0; 17 | 18 | for (let i = 1; i <= size; i++) { 19 | age += getWateringInterval(i); 20 | } 21 | 22 | return age; 23 | } 24 | -------------------------------------------------------------------------------- /src/util/tree-height.ts: -------------------------------------------------------------------------------- 1 | import { HydratedDocument } from "mongoose"; 2 | import { ITree } from "../models/Guild"; 3 | import { getWateringInterval } from "./watering-interval"; 4 | 5 | export function getTreeHeight(tree: HydratedDocument) { 6 | const growthTime = getWateringInterval(tree.pieces.length - 1); 7 | 8 | const canBeWateredAt = tree.lastWateredAt + growthTime; 9 | const time = Math.floor(Date.now() / 1000); 10 | 11 | const growing = canBeWateredAt > time; 12 | 13 | return growing ? tree.size - Math.floor(((canBeWateredAt - time) / growthTime) * 10) / 10 : tree.size; 14 | } 15 | -------------------------------------------------------------------------------- /src/models/Player.ts: -------------------------------------------------------------------------------- 1 | import { model, Schema } from "mongoose"; 2 | 3 | interface IPlayer { 4 | id: string; 5 | 6 | level: number; 7 | xp: number; 8 | 9 | notifyXp: boolean; 10 | } 11 | 12 | const PlayerSchema = new Schema({ 13 | id: { type: String, required: true, unique: true, index: true }, 14 | 15 | level: { type: Number, required: true, default: 1 }, 16 | xp: { type: Number, required: true, default: 0 }, 17 | 18 | notifyXp: { type: Boolean, required: true, default: false } 19 | }); 20 | 21 | const Player = model("Player", PlayerSchema); 22 | 23 | export { Player, PlayerSchema, IPlayer }; 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Add The Bot To Your Server](https://discord.com/application-directory/972637072991068220) 2 | 3 | Work with your Discord community to grow the biggest tree you can! 4 | 5 | The tree cannot be watered by the same person twice, and takes longer to grow as its size increases. Work together to keep it growing regularly and compete to make yours the biggest tree in the forest. 6 | 7 | Uses the [interactions.ts](https://github.com/ssMMiles/interactions.ts) framework. 8 | 9 | ### This is an old and incomplete version of the bot, and relies on a now abandoned version of our image generation service that we never released. *We hope to bring it back up to date with the bot's current code at some point in the future.* 10 | 11 | -------------------------------------------------------------------------------- /src/commands/Help.ts: -------------------------------------------------------------------------------- 1 | import { EmbedBuilder, ISlashCommand, MessageBuilder, SlashCommandBuilder, SlashCommandContext } from "interactions.ts"; 2 | 3 | export class Help implements ISlashCommand { 4 | public builder = new SlashCommandBuilder("help", "Get support with using the bot."); 5 | 6 | public handler = async (ctx: SlashCommandContext): Promise => { 7 | return ctx.reply( 8 | new MessageBuilder( 9 | new EmbedBuilder( 10 | "Help", 11 | ` 12 | If you're just curious about how the game works, check the /about command for a basic run-down. 13 | 14 | If that's not enough, [click here](https://limbolabs.gg/discord) to visit our Discord server where you can get announcements and support for all of our bots.` 15 | ) 16 | ).setEphemeral(true) 17 | ); 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grow-a-tree", 3 | "version": "1.0.0", 4 | "description": "Grow a tree in your Discord server.", 5 | "main": "dist/index.js", 6 | "types": "dist/src/index.d.ts", 7 | "scripts": { 8 | "format": "prettier --write src", 9 | "lint": "eslint src/**/*.ts", 10 | "build": "yarn format & yarn lint && tsc -p tsconfig.json", 11 | "build:docker": "docker build -t grow-a-tree .", 12 | "start": "node dist/index.js", 13 | "dev": "yarn build && yarn start" 14 | }, 15 | "author": "ssMMiles", 16 | "license": "MIT", 17 | "dependencies": { 18 | "@types/humanize-duration": "^3.27.1", 19 | "@types/uuid": "^8.3.4", 20 | "dotenv": "^16.0.0", 21 | "fastify": "^3.27.4", 22 | "fastify-raw-body": "^3.2.0", 23 | "humanize-duration": "^3.27.1", 24 | "interactions.ts": "^1.0.38", 25 | "mongoose": "^6.3.2", 26 | "node-fetch": "2", 27 | "redis": "^4.1.0" 28 | }, 29 | "devDependencies": { 30 | "@types/node": "^14.18.3", 31 | "@types/node-fetch": "^2.6.1", 32 | "@typescript-eslint/eslint-plugin": "^5.17.0", 33 | "@typescript-eslint/parser": "^5.17.0", 34 | "discord-api-types": "^0.32.1", 35 | "eslint": "^8.12.0", 36 | "prettier": "^2.5.1", 37 | "typescript": "^4.5.4" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/util/leveling.ts: -------------------------------------------------------------------------------- 1 | import { HydratedDocument } from "mongoose"; 2 | import { IPlayer, Player } from "../models/Player"; 3 | 4 | /** 5 | * Increments the player's XP by the given amount. Returns the updated player document. 6 | */ 7 | export async function incrementPlayerXp(id: string, amount = 1): Promise> { 8 | // const session = await Player.startSession(); 9 | 10 | // session.startTransaction(); 11 | 12 | const player = await Player.findOne({ id }); //.session(session); 13 | 14 | if (!player) { 15 | // await session.abortTransaction(); 16 | throw new Error("player not found"); 17 | } 18 | 19 | player.xp += amount; 20 | 21 | while (true) { 22 | const required = getNextLevelRequiredXp(player.level); 23 | 24 | if (player.xp < required) break; 25 | 26 | player.level++; 27 | player.xp -= required; 28 | } 29 | 30 | await player.save(); 31 | 32 | // await session.commitTransaction(); 33 | // await session.endSession(); 34 | 35 | return player; 36 | } 37 | 38 | export function getNextLevelRequiredXp(level: number): number { 39 | return Math.floor(Math.pow(20 * level, 0.812) + 30); 40 | } 41 | 42 | export function getTreeXp(size: number): number { 43 | return Math.floor(Math.pow(size * 0.05 + 5, 1.08)); 44 | } 45 | -------------------------------------------------------------------------------- /src/commands/Ping.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ActionRowBuilder, 3 | Button, 4 | ButtonBuilder, 5 | ButtonContext, 6 | EmbedBuilder, 7 | ISlashCommand, 8 | MessageBuilder, 9 | SlashCommandBuilder, 10 | SlashCommandContext 11 | } from "interactions.ts"; 12 | 13 | type TestButtonState = { 14 | ping: boolean; 15 | }; 16 | 17 | export class Ping implements ISlashCommand { 18 | public builder = new SlashCommandBuilder("ping", "Simple ping command."); 19 | 20 | public handler = async (ctx: SlashCommandContext): Promise => { 21 | return ctx.reply( 22 | new MessageBuilder(new EmbedBuilder("Pong!")).addComponents( 23 | new ActionRowBuilder([await ctx.createComponent("pong", { ping: false })]) 24 | ) 25 | ); 26 | }; 27 | 28 | public components = [ 29 | new Button( 30 | "pong", 31 | new ButtonBuilder().setEmoji({ name: "🏓" }).setStyle(1), 32 | async (ctx: ButtonContext): Promise => { 33 | if (!ctx.state) throw new Error("State missing."); 34 | 35 | ctx.reply( 36 | new MessageBuilder(new EmbedBuilder().setTitle(ctx.state.ping ? "Pong!" : "Ping!")).addComponents( 37 | new ActionRowBuilder([await ctx.createComponent("pong", { ping: !ctx.state.ping })]) 38 | ) 39 | ); 40 | } 41 | ) 42 | ]; 43 | } 44 | -------------------------------------------------------------------------------- /src/commands/Rename.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ISlashCommand, 3 | PermissionBits, 4 | SimpleEmbed, 5 | SimpleError, 6 | SlashCommandBuilder, 7 | SlashCommandContext, 8 | SlashCommandStringOption 9 | } from "interactions.ts"; 10 | import { validateTreeName } from "../util/validate-tree-name"; 11 | 12 | export class Rename implements ISlashCommand { 13 | public builder = new SlashCommandBuilder("rename", "Rename your server's tree.") 14 | .addStringOption(new SlashCommandStringOption("name", "Your tree's new name.").setRequired(true)) 15 | .setDMEnabled(false) 16 | .addRequiredPermissions(PermissionBits.ADMINISTRATOR); 17 | 18 | public handler = async (ctx: SlashCommandContext): Promise => { 19 | if (ctx.game === null) return ctx.reply("Use /plant to plant a tree for your server first."); 20 | if (ctx.interaction.guild_id === undefined) return ctx.reply(SimpleError("Guild ID missing.")); 21 | 22 | const name = ctx.getStringOption("name").value; 23 | 24 | if (!validateTreeName(name)) 25 | return ctx.reply( 26 | SimpleError( 27 | "Your tree name must be 1-36 characters, and contain only alphanumeric characters, hyphens, and apostrophes." 28 | ) 29 | ); 30 | 31 | ctx.game.name = name; 32 | await ctx.game.save(); 33 | 34 | return ctx.reply(SimpleEmbed(`You server's tree is now called \`\`${name}\`\`!`)); 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/models/Guild.ts: -------------------------------------------------------------------------------- 1 | import { model, Schema } from "mongoose"; 2 | 3 | interface ITree { 4 | id: string; 5 | 6 | name: string; 7 | 8 | size: number; 9 | pieces: number[]; 10 | 11 | background: string; 12 | backgroundStyle: string; 13 | 14 | lastWateredBy: string; 15 | lastWateredAt: number; 16 | 17 | contributors: IContributor[]; 18 | } 19 | 20 | interface IContributor { 21 | userId: string; 22 | count: number; 23 | } 24 | 25 | const ContributorSchema = new Schema({ 26 | userId: { type: String, required: true }, 27 | count: { type: Number, required: true, default: 1 } 28 | }); 29 | 30 | const GuildSchema = new Schema({ 31 | id: { type: String, required: true, unique: true }, 32 | 33 | name: { type: String, required: true }, 34 | 35 | background: { type: String, required: true, default: "Ground" }, 36 | backgroundStyle: { type: String, required: true, default: "Base" }, 37 | 38 | size: { type: Number, required: true }, 39 | pieces: { type: [Number], required: true }, 40 | 41 | lastWateredBy: { type: String, required: false }, 42 | lastWateredAt: { type: Number, required: false }, 43 | 44 | contributors: { type: [ContributorSchema], required: true, default: [] } 45 | }); 46 | 47 | const Contributor = model("Contributor", ContributorSchema); 48 | const Guild = model("Guild", GuildSchema); 49 | 50 | export { Guild, GuildSchema, Contributor, ContributorSchema, ITree, IContributor }; 51 | -------------------------------------------------------------------------------- /src/util/image-generation.ts: -------------------------------------------------------------------------------- 1 | import { HydratedDocument } from "mongoose"; 2 | import fetch from "node-fetch"; 3 | import { ITree } from "../models/Guild"; 4 | 5 | const IMAGE_SERVER = "http://image-server:9090/tree/"; 6 | export const SHOW_LAST_X_BLOCKS = 5; 7 | 8 | export async function renderTree(tree: HydratedDocument): Promise { 9 | if (tree.lastWateredAt > Math.floor(Date.now() / 1000)) tree.pieces.pop(); 10 | 11 | const background = tree.background ?? "Ground"; 12 | 13 | const id = tree.id; 14 | const pieces = tree.pieces.slice(-SHOW_LAST_X_BLOCKS).reverse(); 15 | 16 | if (background === "Ground") pieces[pieces.length - 1] = 7; 17 | 18 | return fetchImage("", { 19 | id, 20 | 21 | background, 22 | pieces 23 | }); 24 | } 25 | 26 | async function fetchImage(path: string, data: unknown): Promise { 27 | try { 28 | const result = await fetch(IMAGE_SERVER + path, { 29 | method: "POST", 30 | headers: { 31 | "Content-Type": "application/json" 32 | }, 33 | 34 | body: JSON.stringify(data) 35 | }); 36 | 37 | if (!result.ok) { 38 | console.log(await result.text()); 39 | throw new Error(`Failed to fetch image: ${result.statusText}`); 40 | } 41 | 42 | const image = await result.json(); 43 | 44 | return `${image.url}`; 45 | } catch (err) { 46 | console.error(err); 47 | 48 | return "https://www.clipartmax.com/png/full/224-2247501_%C2%A0-tree-transparent.png"; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/commands/About.ts: -------------------------------------------------------------------------------- 1 | import { EmbedBuilder, ISlashCommand, MessageBuilder, SlashCommandBuilder, SlashCommandContext } from "interactions.ts"; 2 | 3 | export class About implements ISlashCommand { 4 | public builder = new SlashCommandBuilder("about", "Some information about the bot."); 5 | 6 | public handler = async (ctx: SlashCommandContext): Promise => { 7 | return ctx.reply( 8 | new MessageBuilder( 9 | new EmbedBuilder( 10 | "About The Bot", 11 | ` 12 | <@972637072991068220> is a chill clicker game that lets you plant and name a community tree for your Discord server, and watch it grow as your members take turns watering it :) 13 | 14 | A tree cannot be watered by the same person twice, and will take longer to grow as it gets taller. Taller trees also grant more XP, but might get competitive in large servers. 15 | 16 | Compete with your friends or work together and try to grow your tree into one of the tallest in the forest! 17 | 18 | You can invite it by clicking on its profile, or by clicking the link below. After that, use \`\`/plant\`\` and enjoy! 19 | 20 | [ToS](https://limbolabs.gg/terms-of-service) | [Privacy Policy](https://limbolabs.gg/privacy-policy) | [Discord Support](https://limbolabs.gg/discord) | [Invite The Bot](https://limbolabs.gg/bots/grow-a-tree/invite) | [Vote For Us!](https://top.gg/bot/972637072991068220/vote)` 21 | ).setFooter({ 22 | text: `This bot was made by Limbo Labs, find more from us at limbolabs.gg` 23 | }) 24 | ) 25 | ); 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/commands/Config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ActionRowBuilder, 3 | Button, 4 | ButtonBuilder, 5 | ButtonContext, 6 | ButtonStyle, 7 | CommandGroupBuilder, 8 | EmbedBuilder, 9 | ICommandGroup, 10 | MessageBuilder, 11 | SlashCommandContext, 12 | SubcommandOption 13 | } from "interactions.ts"; 14 | 15 | export class Config implements ICommandGroup { 16 | public builder = new CommandGroupBuilder("config", "Manage your settings.").addSubcommands( 17 | new SubcommandOption("xp-messages", "Whether to display XP messages after watering a tree.") 18 | ); 19 | 20 | public handlers = { 21 | "xp-messages": { 22 | handler: async (ctx: SlashCommandContext) => { 23 | await ctx.reply(await buildMessage(ctx)); 24 | } 25 | } 26 | }; 27 | 28 | public components = [ 29 | new Button( 30 | "toggleXpMessages", 31 | new ButtonBuilder().setStyle(ButtonStyle.Primary), 32 | async (ctx: ButtonContext) => { 33 | ctx.player.notifyXp = !ctx.player.notifyXp; 34 | 35 | await ctx.player.save(); 36 | 37 | await ctx.reply(await buildMessage(ctx)); 38 | } 39 | ) 40 | ]; 41 | } 42 | 43 | async function buildMessage(ctx: SlashCommandContext | ButtonContext): Promise { 44 | return new MessageBuilder( 45 | new EmbedBuilder() 46 | .setTitle("XP Notifications") 47 | .setDescription( 48 | `Whether to tell you how much XP was gained from watering a tree.\n\nCurrent: **${ 49 | ctx.player.notifyXp ? "Enabled" : "Disabled" 50 | }**` 51 | ) 52 | ) 53 | .addComponents( 54 | new ActionRowBuilder([ 55 | ((await ctx.createComponent("toggleXpMessages")) as ButtonBuilder).setEmoji({ 56 | name: ctx.player.notifyXp ? "🔕" : "🔔" 57 | }) 58 | ]) 59 | ) 60 | .setEphemeral(true); 61 | } 62 | -------------------------------------------------------------------------------- /src/commands/Forest.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ActionRowBuilder, 3 | Button, 4 | ButtonBuilder, 5 | ButtonContext, 6 | EmbedBuilder, 7 | ISlashCommand, 8 | MessageBuilder, 9 | SimpleError, 10 | SlashCommandBuilder, 11 | SlashCommandContext, 12 | SlashCommandIntegerOption 13 | } from "interactions.ts"; 14 | import { Guild } from "../models/Guild"; 15 | import { getTreeHeight } from "../util/tree-height"; 16 | 17 | type LeaderboardButtonState = { 18 | page: number; 19 | }; 20 | 21 | const MEDAL_EMOJIS = ["🥇", "🥈", "🥉"]; 22 | 23 | export class Forest implements ISlashCommand { 24 | public builder = new SlashCommandBuilder( 25 | "forest", 26 | "The tallest trees in the forest. (Global Leaderboard)" 27 | ).addIntegerOption( 28 | new SlashCommandIntegerOption("page", "Leaderboard page to display.").setMinValue(1).setMaxValue(10) 29 | ); 30 | 31 | public handler = async (ctx: SlashCommandContext): Promise => { 32 | return ctx.reply(await buildLeaderboardMessage(ctx)); 33 | }; 34 | 35 | public components = [ 36 | new Button( 37 | "refresh", 38 | new ButtonBuilder().setEmoji({ name: "🔄" }).setStyle(2), 39 | async (ctx: ButtonContext): Promise => { 40 | return ctx.reply(await buildLeaderboardMessage(ctx)); 41 | } 42 | ), 43 | new Button( 44 | "back", 45 | new ButtonBuilder().setEmoji({ name: "◀️" }).setStyle(2), 46 | async (ctx: ButtonContext): Promise => { 47 | if (!ctx.state) return; 48 | 49 | ctx.state.page--; 50 | return ctx.reply(await buildLeaderboardMessage(ctx)); 51 | } 52 | ), 53 | new Button( 54 | "next", 55 | new ButtonBuilder().setEmoji({ name: "▶️" }).setStyle(2), 56 | async (ctx: ButtonContext): Promise => { 57 | if (!ctx.state) return; 58 | 59 | ctx.state.page++; 60 | return ctx.reply(await buildLeaderboardMessage(ctx)); 61 | } 62 | ) 63 | ]; 64 | } 65 | 66 | async function buildLeaderboardMessage( 67 | ctx: SlashCommandContext | ButtonContext 68 | ): Promise { 69 | const state: LeaderboardButtonState = 70 | ctx instanceof SlashCommandContext 71 | ? { page: ctx.hasOption("page") ? Number(ctx.getIntegerOption("page").value) : 1 } 72 | : (ctx.state as LeaderboardButtonState); 73 | 74 | let description = "The tallest trees in all the Discord servers.\n\n"; 75 | 76 | const start = (state.page - 1) * 10; 77 | 78 | const trees = await Guild.find().sort({ size: -1, id: 1 }).skip(start).limit(11); 79 | 80 | if (trees.length === 0) return SimpleError("This page is empty."); 81 | 82 | for (let i = 0; i < 10; i++) { 83 | if (i === trees.length) break; 84 | const pos = i + start; 85 | 86 | const tree = trees[i]; 87 | 88 | description += `${pos < 3 ? `${MEDAL_EMOJIS[i]}` : `\`\`${pos + 1}${pos < 9 ? " " : ""}\`\``} - \`\`${ 89 | tree.name 90 | }\`\` - ${getTreeHeight(tree)}ft\n`; 91 | } 92 | 93 | const actionRow = new ActionRowBuilder([await ctx.createComponent("refresh", state)]); 94 | 95 | const backButton = await ctx.createComponent("back", state); 96 | const nextButton = await ctx.createComponent("next", state); 97 | 98 | if (state.page <= 1) { 99 | backButton.setDisabled(true); 100 | } 101 | 102 | if (trees.length <= 10) { 103 | nextButton.setDisabled(true); 104 | } 105 | 106 | actionRow.addComponents(backButton, nextButton); 107 | 108 | return new MessageBuilder(new EmbedBuilder().setTitle("Forest").setDescription(description)).addComponents(actionRow); 109 | } 110 | -------------------------------------------------------------------------------- /src/commands/Profile.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ActionRowBuilder, 3 | Button, 4 | ButtonBuilder, 5 | ButtonContext, 6 | EmbedBuilder, 7 | ISlashCommand, 8 | IUserCommand, 9 | MessageBuilder, 10 | SimpleEmbed, 11 | SlashCommandBuilder, 12 | SlashCommandContext, 13 | SlashCommandUserOption, 14 | UserCommandBuilder, 15 | UserCommandContext 16 | } from "interactions.ts"; 17 | import { Player } from "../models/Player"; 18 | import { getNextLevelRequiredXp } from "../util/leveling"; 19 | 20 | type State = { 21 | id: string; 22 | nick: string; 23 | }; 24 | 25 | export class UserContextProfile implements IUserCommand { 26 | public builder = new UserCommandBuilder("View Profile"); 27 | 28 | public handler = async (ctx: UserCommandContext) => { 29 | return ctx.reply(await buildProfileMessage(ctx)); 30 | }; 31 | 32 | public components = []; 33 | } 34 | 35 | export class Profile implements ISlashCommand { 36 | public builder = new SlashCommandBuilder("profile", "View a user's contributions to the tree.") 37 | .addUserOption(new SlashCommandUserOption("target", "User whose profile you want to view.")) 38 | .setDMEnabled(false); 39 | 40 | public handler = async (ctx: SlashCommandContext): Promise => { 41 | return ctx.reply(await buildProfileMessage(ctx)); 42 | }; 43 | 44 | public components = [ 45 | new Button( 46 | "refresh", 47 | new ButtonBuilder().setEmoji({ name: "🔄" }).setStyle(1), 48 | async (ctx: ButtonContext): Promise => { 49 | return ctx.reply(await buildProfileMessage(ctx)); 50 | } 51 | ) 52 | ]; 53 | } 54 | 55 | async function buildProfileMessage( 56 | ctx: SlashCommandContext | ButtonContext | UserCommandContext 57 | ): Promise { 58 | if (!ctx.game) 59 | return new MessageBuilder().setContent("Use /plant to plant a tree for your server first.").setEphemeral(true); 60 | 61 | let nick: string, id: string; 62 | 63 | if (ctx instanceof UserCommandContext) { 64 | id = ctx.target.user.id; 65 | nick = ctx.target?.member?.nick ?? ctx.target.user.username; 66 | } else if (ctx instanceof SlashCommandContext || !ctx.state) { 67 | const target = 68 | ctx instanceof SlashCommandContext && ctx.hasOption("target") 69 | ? ctx.interaction.data.resolved?.users?.[ctx.getStringOption("target").value] 70 | : undefined; 71 | 72 | id = target ? target.id : ctx.user.id; 73 | nick = 74 | ctx instanceof SlashCommandContext && target 75 | ? ctx.interaction.data?.resolved?.members?.[id]?.nick ?? target.username 76 | : ctx.interaction.member?.nick ?? ctx.user.username; 77 | } else { 78 | id = ctx.state.id; 79 | nick = ctx.state.nick; 80 | } 81 | 82 | const player = await Player.findOne({ id }); 83 | 84 | if (!player) return SimpleEmbed("This person hasn't used the bot yet, send them a link!"); 85 | 86 | const contributor = ctx.game.contributors.find((contributor) => contributor.userId === id); 87 | 88 | return new MessageBuilder( 89 | new EmbedBuilder( 90 | `${nick}'s Profile`, 91 | `Level: **${player.level}**\nXP: ${player.xp}/${getNextLevelRequiredXp(player.level)}\n\n${ 92 | ctx.user.id === id ? `You've` : `This player has` 93 | } ${ 94 | contributor 95 | ? `watered \`\`${ctx.game.name}\`\` ${contributor.count} times and are ranked #${ 96 | ctx.game.contributors 97 | .sort((a, b) => b.count - a.count) 98 | .findIndex((contributor) => contributor.userId === id) + 1 99 | }/${ctx.game.contributors.length} in this community.` 100 | : "not yet watered the tree." 101 | }` 102 | ) 103 | ).addComponents(new ActionRowBuilder([await ctx.createGlobalComponent("profile.refresh", { id, nick })])); 104 | } 105 | -------------------------------------------------------------------------------- /src/util/tree-generation.ts: -------------------------------------------------------------------------------- 1 | import { HydratedDocument } from "mongoose"; 2 | import { ITree } from "../models/Guild"; 3 | import { SHOW_LAST_X_BLOCKS } from "./image-generation"; 4 | 5 | export const TILES = { 6 | BASE: 0, 7 | SMALL_HOLE: 1, 8 | LARGE_HOLE: 2, 9 | RIGHT_BRANCH_1: 3, 10 | LEFT_BRANCH_1: 4, 11 | RIGHT_BRANCH_2: 5, 12 | LEFT_BRANCH_2: 6 13 | }; 14 | 15 | export const LEFT_BRANCHES = [TILES.LEFT_BRANCH_1, TILES.LEFT_BRANCH_2]; 16 | 17 | export const RIGHT_BRANCHES = [TILES.RIGHT_BRANCH_1, TILES.RIGHT_BRANCH_2]; 18 | 19 | export const BRANCHES = [...LEFT_BRANCHES, ...RIGHT_BRANCHES]; 20 | 21 | export function generateNextSegment(tree: HydratedDocument): number { 22 | const recentPieces = tree.pieces.slice(-SHOW_LAST_X_BLOCKS).reverse(); 23 | 24 | if (BRANCHES.includes(recentPieces[0])) return getRandomTileWithoutBranch(); 25 | 26 | if (BRANCHES.includes(recentPieces[1])) { 27 | if (LEFT_BRANCHES.includes(recentPieces[1])) return getRandomTileRightBranch(); 28 | if (RIGHT_BRANCHES.includes(recentPieces[1])) return getRandomTileLeftBranch(); 29 | } 30 | 31 | for (let i = 2; i < recentPieces.length; i++) { 32 | const piece = recentPieces[i]; 33 | 34 | if (LEFT_BRANCHES.includes(piece)) return getRandomTileRightBranch(); 35 | if (RIGHT_BRANCHES.includes(piece)) return getRandomTileRightBranch(); 36 | } 37 | 38 | return getRandomTile(); 39 | } 40 | 41 | export function weightedRandomizer(entries: { id: number; weight: number }[], tableSize = 10): () => number { 42 | const table: number[] = []; 43 | 44 | for (const { id, weight } of entries) { 45 | for (let j = 0; j < weight * tableSize; j++) { 46 | table.push(id); 47 | } 48 | } 49 | 50 | return function () { 51 | return table[Math.floor(Math.random() * table.length)]; 52 | }; 53 | } 54 | 55 | const getRandomTile = weightedRandomizer( 56 | [ 57 | { 58 | id: TILES.BASE, 59 | weight: 0.5 60 | }, 61 | { 62 | id: TILES.SMALL_HOLE, 63 | weight: 0.04 64 | }, 65 | { 66 | id: TILES.LARGE_HOLE, 67 | weight: 0.01 68 | }, 69 | { 70 | id: TILES.RIGHT_BRANCH_1, 71 | weight: 0.125 72 | }, 73 | { 74 | id: TILES.LEFT_BRANCH_1, 75 | weight: 0.125 76 | }, 77 | { 78 | id: TILES.RIGHT_BRANCH_2, 79 | weight: 0.125 80 | }, 81 | { 82 | id: TILES.LEFT_BRANCH_2, 83 | weight: 0.125 84 | } 85 | ], 86 | 100000 87 | ); 88 | 89 | const getRandomTileWithoutBranch = weightedRandomizer( 90 | [ 91 | { 92 | id: TILES.BASE, 93 | weight: 0.9 94 | }, 95 | { 96 | id: TILES.SMALL_HOLE, 97 | weight: 0.04 98 | }, 99 | { 100 | id: TILES.LARGE_HOLE, 101 | weight: 0.01 102 | } 103 | ], 104 | 10000 105 | ); 106 | 107 | const getRandomTileLeftBranch = weightedRandomizer( 108 | [ 109 | { 110 | id: TILES.BASE, 111 | weight: 0.55 112 | }, 113 | { 114 | id: TILES.SMALL_HOLE, 115 | weight: 0.04 116 | }, 117 | { 118 | id: TILES.LARGE_HOLE, 119 | weight: 0.01 120 | }, 121 | { 122 | id: TILES.LEFT_BRANCH_1, 123 | weight: 0.2 124 | }, 125 | { 126 | id: TILES.LEFT_BRANCH_2, 127 | weight: 0.2 128 | } 129 | ], 130 | 10000 131 | ); 132 | 133 | const getRandomTileRightBranch = weightedRandomizer( 134 | [ 135 | { 136 | id: TILES.BASE, 137 | weight: 0.55 138 | }, 139 | { 140 | id: TILES.SMALL_HOLE, 141 | weight: 0.04 142 | }, 143 | { 144 | id: TILES.LARGE_HOLE, 145 | weight: 0.01 146 | }, 147 | { 148 | id: TILES.RIGHT_BRANCH_1, 149 | weight: 0.2 150 | }, 151 | { 152 | id: TILES.RIGHT_BRANCH_2, 153 | weight: 0.2 154 | } 155 | ], 156 | 10000 157 | ); 158 | -------------------------------------------------------------------------------- /src/commands/Plant.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ActionRowBuilder, 3 | Button, 4 | ButtonBuilder, 5 | ButtonContext, 6 | ButtonStyle, 7 | EmbedBuilder, 8 | ISlashCommand, 9 | MessageBuilder, 10 | PermissionBits, 11 | SimpleError, 12 | SlashCommandBuilder, 13 | SlashCommandContext, 14 | SlashCommandStringOption 15 | } from "interactions.ts"; 16 | import { Guild } from "../models/Guild"; 17 | import { generateNextSegment } from "../util/tree-generation"; 18 | import { validateTreeName } from "../util/validate-tree-name"; 19 | import { buildTreeDisplayMessage } from "./Tree"; 20 | 21 | type State = { 22 | name: string; 23 | }; 24 | 25 | export class Plant implements ISlashCommand { 26 | public builder = new SlashCommandBuilder("plant", "Plant a tree for your server.") 27 | .addStringOption(new SlashCommandStringOption("name", "A name for your server's tree.").setRequired(true)) 28 | .setDMEnabled(false) 29 | .addRequiredPermissions(PermissionBits.ADMINISTRATOR); 30 | 31 | public handler = async (ctx: SlashCommandContext): Promise => { 32 | if (ctx.game !== null) { 33 | return ctx.reply( 34 | SimpleError( 35 | `A tree has already been planted in this server called \`\`${ctx.game.name}\`\`. You can only have one per community.` 36 | ).setEphemeral(true) 37 | ); 38 | } 39 | 40 | const name = ctx.getStringOption("name").value; 41 | 42 | if (!validateTreeName(name)) 43 | return ctx.reply( 44 | SimpleError( 45 | "Your tree name must be 1-36 characters, and contain only alphanumeric characters, hyphens, and apostrophes." 46 | ).setEphemeral(true) 47 | ); 48 | 49 | return ctx.reply( 50 | new MessageBuilder( 51 | new EmbedBuilder( 52 | `Are you sure you want to call your tree \`\`${name}\`\`?`, 53 | `*Your tree name is public, so please avoid any profanity/nsfw/links.* ***Thanks! :)***` 54 | ).setFooter({ 55 | text: "If there is a problem the name will first be changed along with a warning, repeat offenses will have it locked to something boring." 56 | }) 57 | ).addComponents( 58 | new ActionRowBuilder().addComponents( 59 | await ctx.createComponent("confirm", { name }), 60 | await ctx.createComponent("cancel") 61 | ) 62 | ) 63 | ); 64 | }; 65 | 66 | public components = [ 67 | new Button( 68 | "confirm", 69 | new ButtonBuilder().setEmoji({ name: "✔️" }).setStyle(ButtonStyle.Success), 70 | async (ctx: ButtonContext) => { 71 | if (ctx.game !== null) { 72 | return ctx.reply( 73 | SimpleError( 74 | `A tree has already been planted in this server called \`\`${ctx.game.name}\`\`. You can only have one per community.` 75 | ).setEphemeral(true) 76 | ); 77 | } 78 | 79 | const name = ctx.state?.name as string; 80 | 81 | ctx.game = new Guild({ 82 | id: ctx.interaction.guild_id, 83 | 84 | name, 85 | 86 | lastWateredAt: Math.floor(Date.now() / 1000), 87 | lastWateredBy: ctx.user.id, 88 | 89 | pieces: [7, 0], 90 | 91 | contributors: [ 92 | { 93 | userId: ctx.user.id, 94 | count: 1 95 | } 96 | ] 97 | }); 98 | 99 | ctx.game.size = ctx.game.pieces.push(generateNextSegment(ctx.game)); 100 | 101 | await ctx.game.save(); 102 | 103 | ctx.parentCommand = "tree"; 104 | 105 | await ctx.reply(await buildTreeDisplayMessage(ctx as ButtonContext, true)); 106 | } 107 | ), 108 | new Button( 109 | "cancel", 110 | new ButtonBuilder().setEmoji({ name: "✖️" }).setStyle(ButtonStyle.Danger), 111 | async (ctx: ButtonContext) => { 112 | await ctx.reply(SimpleError("Tree planting cancelled.").setComponents([])); 113 | } 114 | ) 115 | ]; 116 | } 117 | -------------------------------------------------------------------------------- /src/commands/Background.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ActionRowBuilder, 3 | Button, 4 | ButtonBuilder, 5 | ButtonContext, 6 | ButtonStyle, 7 | EmbedBuilder, 8 | ISlashCommand, 9 | MessageBuilder, 10 | PermissionBits, 11 | SimpleEmbed, 12 | SlashCommandBuilder, 13 | SlashCommandContext 14 | } from "interactions.ts"; 15 | 16 | type State = { 17 | background: string; 18 | }; 19 | 20 | const backgrounds: { [key: string]: number } = { 21 | Ground: 0, 22 | Sky: 5, 23 | SpaceEdge: 1000 24 | }; 25 | 26 | const backgroundNames = Object.keys(backgrounds); 27 | 28 | export class Background implements ISlashCommand { 29 | public builder = new SlashCommandBuilder("background", "Change your tree's background.") 30 | .setDMEnabled(false) 31 | .addRequiredPermissions(PermissionBits.ADMINISTRATOR); 32 | 33 | public handler = async (ctx: SlashCommandContext): Promise => { 34 | return ctx.reply(await buildBackgroundMenu(ctx)); 35 | }; 36 | 37 | public components = [ 38 | new Button( 39 | "set", 40 | new ButtonBuilder(ButtonStyle.Primary).setEmoji({ name: "🖌️" }).setStyle(1), 41 | async (ctx: ButtonContext) => { 42 | if (!ctx.state || !ctx.game) return; 43 | 44 | await ctx.defer(); 45 | 46 | ctx.game.background = ctx.state.background; 47 | await ctx.game.save(); 48 | 49 | await ctx.send(SimpleEmbed("Background set. Use ``/tree`` to take a look!").setEphemeral(true)); 50 | } 51 | ), 52 | new Button( 53 | "back", 54 | new ButtonBuilder().setEmoji({ name: "◀️" }).setStyle(2), 55 | async (ctx: ButtonContext): Promise => { 56 | if (!ctx.state) return; 57 | 58 | const position = backgroundNames.indexOf(ctx.state.background); 59 | ctx.state.background = backgroundNames[position - 1]; 60 | 61 | return ctx.reply(await buildBackgroundMenu(ctx)); 62 | } 63 | ), 64 | new Button( 65 | "next", 66 | new ButtonBuilder().setEmoji({ name: "▶️" }).setStyle(2), 67 | async (ctx: ButtonContext): Promise => { 68 | if (!ctx.state) return; 69 | 70 | const position = backgroundNames.indexOf(ctx.state.background); 71 | ctx.state.background = backgroundNames[position + 1]; 72 | 73 | return ctx.reply(await buildBackgroundMenu(ctx)); 74 | } 75 | ) 76 | ]; 77 | } 78 | 79 | async function buildBackgroundMenu(ctx: SlashCommandContext | ButtonContext): Promise { 80 | if (ctx.game === null) return SimpleEmbed("Use /plant to plant a tree for your server first.").setEphemeral(true); 81 | 82 | const background = "state" in ctx ? ctx.state!.background : ctx.game.background; 83 | 84 | let originalPosition = -1; 85 | for (const name of backgroundNames) { 86 | if (backgrounds[name] <= ctx.game.size) originalPosition++; 87 | } 88 | 89 | const position = backgroundNames.indexOf(background); 90 | 91 | const embed = new EmbedBuilder( 92 | "Backgrounds", 93 | ` 94 | As your tree grows, you'll notice the background change at certain height milestones. 95 | 96 | Here you can view all stages you've unlocked, and switch back to one if you'd like. 97 | ` 98 | ); 99 | 100 | if (position > originalPosition) { 101 | embed.setDescription(`You'll unlock this next stage at ${backgrounds[background]}ft.`); 102 | embed.setImage(`https://cdn.milesmoonlove.com/trees/backgrounds/Locked.png`); 103 | 104 | return new MessageBuilder(embed) 105 | .addComponents( 106 | new ActionRowBuilder([ 107 | (await ctx.createComponent("set", "state" in ctx ? ctx.state : { background })).setDisabled(true), 108 | await ctx.createComponent("back", "state" in ctx ? ctx.state : { background }), 109 | (await ctx.createComponent("next", "state" in ctx ? ctx.state : { background })).setDisabled(true) 110 | ]) 111 | ) 112 | .setEphemeral(true); 113 | } 114 | 115 | embed.setImage(`https://cdn.milesmoonlove.com/trees/backgrounds/${backgroundNames[position]}.png`); 116 | 117 | const buttons = new ActionRowBuilder([await ctx.createComponent("set", "state" in ctx ? ctx.state : { background })]); 118 | 119 | const back = await ctx.createComponent("back", "state" in ctx ? ctx.state : { background }); 120 | const next = await ctx.createComponent("next", "state" in ctx ? ctx.state : { background }); 121 | 122 | if (position === 0) { 123 | back.setDisabled(true); 124 | } 125 | 126 | if (position === backgroundNames.length - 1) { 127 | next.setDisabled(true); 128 | 129 | if (position === originalPosition) { 130 | embed.setFooter({ 131 | text: "Congratulations! You've unlocked all backgrounds! We're working on adding more, join our Discord server to be notified when this happens.." 132 | }); 133 | } 134 | } 135 | 136 | buttons.addComponents(back, next); 137 | 138 | return new MessageBuilder(embed).addComponents(buttons).setEphemeral(true); 139 | } 140 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import "dotenv/config"; 2 | import fastify from "fastify"; 3 | import rawBody from "fastify-raw-body"; 4 | import { 5 | AutocompleteContext, 6 | DiscordApplication, 7 | InteractionContext, 8 | InteractionHandlerTimedOut, 9 | PingContext, 10 | SimpleError, 11 | UnauthorizedInteraction, 12 | UnknownApplicationCommandType, 13 | UnknownComponentType, 14 | UnknownInteractionType 15 | } from "interactions.ts"; 16 | import { connect, HydratedDocument } from "mongoose"; 17 | import { createClient } from "redis"; 18 | import { 19 | About, 20 | Config, 21 | Forest, 22 | Help, 23 | Leaderboard, 24 | Ping, 25 | Plant, 26 | Profile, 27 | Rename, 28 | Tree, 29 | UserContextProfile 30 | } from "./commands"; 31 | import { Background } from "./commands/Background"; 32 | import { Guild, ITree } from "./models/Guild"; 33 | import { IPlayer, Player } from "./models/Player"; 34 | 35 | declare module "interactions.ts" { 36 | interface BaseInteractionContext { 37 | player: HydratedDocument; 38 | game: HydratedDocument | null; 39 | timeouts: Map; 40 | } 41 | } 42 | 43 | const timeouts = new Map(); 44 | const keys = ["CLIENT_ID", "TOKEN", "PUBLIC_KEY", "PORT", "MONGO_URI"]; 45 | 46 | if (keys.some((key) => !(key in process.env))) { 47 | console.error(`Missing Enviroment Variables`); 48 | process.exit(1); 49 | } 50 | 51 | (async () => { 52 | const redisClient = createClient({ 53 | url: "redis://redis" 54 | }); 55 | 56 | await redisClient.connect(); 57 | 58 | const app = new DiscordApplication({ 59 | clientId: process.env.CLIENT_ID as string, 60 | token: process.env.TOKEN as string, 61 | publicKey: process.env.PUBLIC_KEY as string, 62 | 63 | cache: { 64 | get: (key: string) => redisClient.get(key), 65 | set: (key: string, ttl: number, value: string) => redisClient.setEx(key, ttl, value) 66 | }, 67 | 68 | hooks: { 69 | interaction: async (ctx: InteractionContext) => { 70 | if (ctx instanceof PingContext) return; 71 | if (!ctx.interaction.guild_id) return; 72 | 73 | let player; 74 | let game; 75 | 76 | try { 77 | game = await Guild.findOne({ id: ctx.interaction.guild_id }); 78 | 79 | if (game) await game.populate("contributors"); 80 | 81 | player = await Player.findOne({ id: ctx.user.id }); 82 | 83 | if (!player) { 84 | player = new Player({ id: ctx.user.id }); 85 | await player.save(); 86 | } 87 | } catch (err) { 88 | console.error(err); 89 | 90 | if (ctx instanceof AutocompleteContext) { 91 | await ctx.reply([]); 92 | } else { 93 | await ctx.reply(SimpleError("There was an error loading your game data")); 94 | } 95 | 96 | return true; 97 | } 98 | 99 | ctx.decorate("player", player); 100 | ctx.decorate("game", game); 101 | 102 | ctx.decorate("timeouts", timeouts); 103 | } 104 | } 105 | }); 106 | 107 | await app.commands.register( 108 | [ 109 | new Ping(), 110 | new Plant(), 111 | new Tree(), 112 | new Background(), 113 | new Leaderboard(), 114 | new Forest(), 115 | new Profile(), 116 | new UserContextProfile(), 117 | new About(), 118 | new Rename(), 119 | new Config(), 120 | new Help() 121 | ], 122 | false 123 | ); 124 | 125 | const server = fastify(); 126 | server.register(rawBody); 127 | 128 | server.post("/", async (request, reply) => { 129 | const signature = request.headers["x-signature-ed25519"]; 130 | const timestamp = request.headers["x-signature-timestamp"]; 131 | 132 | if (typeof request.rawBody !== "string" || typeof signature !== "string" || typeof timestamp !== "string") { 133 | return reply.code(400).send({ 134 | error: "Invalid request" 135 | }); 136 | } 137 | 138 | try { 139 | await app.handleInteraction( 140 | async (response) => { 141 | reply.code(200).send(response); 142 | }, 143 | request.rawBody, 144 | timestamp, 145 | signature 146 | ); 147 | } catch (err) { 148 | if (err instanceof UnauthorizedInteraction) { 149 | console.error("Unauthorized Interaction"); 150 | return reply.code(401).send(); 151 | } 152 | 153 | if (err instanceof InteractionHandlerTimedOut) { 154 | console.error("Interaction Handler Timed Out"); 155 | 156 | return reply.code(408).send(); 157 | } 158 | 159 | if ( 160 | err instanceof UnknownInteractionType || 161 | err instanceof UnknownApplicationCommandType || 162 | err instanceof UnknownComponentType 163 | ) { 164 | console.error("Unknown Interaction - Library may be out of date."); 165 | console.dir(err.interaction); 166 | 167 | return reply.code(400).send(); 168 | } 169 | 170 | console.error(err); 171 | } 172 | }); 173 | 174 | connect(process.env.MONGO_URI as string) 175 | .then(async () => { 176 | const address = "0.0.0.0"; 177 | const port = process.env.PORT as string; 178 | 179 | await updateGuilds(); 180 | 181 | server.listen(port, address); 182 | console.log(`Listening for interactions on ${address}:${port}.`); 183 | }) 184 | .catch((err: unknown) => { 185 | console.error(err); 186 | }); 187 | })(); 188 | 189 | async function updateGuilds() { 190 | const trees = await Guild.find({}); 191 | 192 | for (const tree of trees) { 193 | // Update trees 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/commands/Leaderboard.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ActionRowBuilder, 3 | Button, 4 | ButtonBuilder, 5 | ButtonContext, 6 | EmbedBuilder, 7 | ISlashCommand, 8 | MessageBuilder, 9 | SimpleError, 10 | SlashCommandBuilder, 11 | SlashCommandContext, 12 | SlashCommandIntegerOption 13 | } from "interactions.ts"; 14 | import { Player } from "../models/Player"; 15 | 16 | type LeaderboardButtonState = { 17 | page: number; 18 | global: boolean; 19 | }; 20 | 21 | const MEDAL_EMOJIS = ["🥇", "🥈", "🥉"]; 22 | 23 | export class Leaderboard implements ISlashCommand { 24 | public builder = new SlashCommandBuilder( 25 | "leaderboard", 26 | "See a leaderboard of contributors to this server's tree. (Community Leaderboard)" 27 | ) 28 | .addIntegerOption( 29 | new SlashCommandIntegerOption("page", "Leaderboard page to display.").setMinValue(1).setMaxValue(10) 30 | ) 31 | .setDMEnabled(false); 32 | 33 | public handler = async (ctx: SlashCommandContext): Promise => { 34 | if (ctx.game === null) 35 | return ctx.reply(SimpleError("Use /plant to plant a tree for your server first.").setEphemeral(true)); 36 | 37 | return ctx.reply(await buildLeaderboardMessage(ctx)); 38 | }; 39 | 40 | public components = [ 41 | new Button( 42 | "refresh", 43 | new ButtonBuilder().setEmoji({ name: "🔄" }).setStyle(2), 44 | async (ctx: ButtonContext): Promise => { 45 | if (!ctx.state) return; 46 | 47 | return ctx.reply(await buildLeaderboardMessage(ctx)); 48 | } 49 | ), 50 | new Button( 51 | "toggleGlobal", 52 | new ButtonBuilder().setEmoji({ name: "🌎" }).setStyle(2), 53 | async (ctx: ButtonContext): Promise => { 54 | if (!ctx.state) return; 55 | 56 | ctx.state.global = !ctx.state.global; 57 | ctx.state.page = 1; 58 | 59 | return ctx.reply(await buildLeaderboardMessage(ctx)); 60 | } 61 | ), 62 | new Button( 63 | "back", 64 | new ButtonBuilder().setEmoji({ name: "◀️" }).setStyle(2), 65 | async (ctx: ButtonContext): Promise => { 66 | if (!ctx.state) return; 67 | 68 | ctx.state.page--; 69 | return ctx.reply(await buildLeaderboardMessage(ctx)); 70 | } 71 | ), 72 | new Button( 73 | "next", 74 | new ButtonBuilder().setEmoji({ name: "▶️" }).setStyle(2), 75 | async (ctx: ButtonContext): Promise => { 76 | if (!ctx.state) return; 77 | 78 | ctx.state.page++; 79 | return ctx.reply(await buildLeaderboardMessage(ctx)); 80 | } 81 | ) 82 | ]; 83 | } 84 | 85 | async function buildLeaderboardMessage( 86 | ctx: SlashCommandContext | ButtonContext 87 | ): Promise { 88 | if (ctx.game === null) throw new Error("Game data missing."); 89 | 90 | const state: LeaderboardButtonState = 91 | ctx instanceof SlashCommandContext 92 | ? { page: ctx.hasOption("page") ? Number(ctx.getIntegerOption("page").value) : 1, global: false } 93 | : (ctx.state as LeaderboardButtonState); 94 | 95 | if (state.global) return await buildGlobalLeaderboardMessage(ctx, state); 96 | 97 | let description = ""; 98 | 99 | const contributors = ctx.game.contributors.sort((a, b) => b.count - a.count); 100 | 101 | if (contributors.length === 0) return SimpleError("This page is empty."); 102 | 103 | const start = (state.page - 1) * 10; 104 | 105 | for (let i = start; i < start + 10; i++) { 106 | if (i === contributors.length) { 107 | if (i === start) description = `This page is empty.`; 108 | break; 109 | } 110 | 111 | const contributor = contributors[i]; 112 | 113 | description += `${i < 3 ? `${MEDAL_EMOJIS[i]}` : `\`\`${i + 1}${i < 9 ? " " : ""}\`\``} - 💧${ 114 | contributor.count 115 | } <@${contributor.userId}>\n`; 116 | } 117 | 118 | const actionRow = new ActionRowBuilder([await ctx.createComponent("refresh", state)]); 119 | 120 | const toggleGlobal = (await ctx.createComponent("toggleGlobal", state)) as ButtonBuilder; 121 | 122 | const backButton = await ctx.createComponent("back", state); 123 | const nextButton = await ctx.createComponent("next", state); 124 | 125 | if (state.page <= 1) { 126 | backButton.setDisabled(true); 127 | } 128 | 129 | if (state.page >= Math.ceil(contributors.length / 10)) { 130 | nextButton.setDisabled(true); 131 | } 132 | 133 | actionRow.addComponents(toggleGlobal, backButton, nextButton); 134 | 135 | return new MessageBuilder( 136 | new EmbedBuilder().setTitle("Greatest Gardeners").setDescription(description) 137 | ).addComponents(actionRow); 138 | } 139 | 140 | async function buildGlobalLeaderboardMessage( 141 | ctx: SlashCommandContext | ButtonContext, 142 | state: LeaderboardButtonState 143 | ): Promise { 144 | if (ctx.game === null) throw new Error("Game data missing."); 145 | 146 | let description = ""; 147 | 148 | const start = (state.page - 1) * 10; 149 | 150 | const players = await Player.find().sort({ level: -1 }).skip(start).limit(11); 151 | 152 | if (players.length === 0) return SimpleError("This page is empty."); 153 | 154 | for (let i = 0; i < 10; i++) { 155 | if (i === players.length) break; 156 | const pos = i + start; 157 | 158 | const player = players[i]; 159 | 160 | description += `${pos < 3 ? `${MEDAL_EMOJIS[i]}` : `\`\`${pos + 1}${pos < 9 ? " " : ""}\`\``} - Level ${ 161 | player.level 162 | } <@${player.id}>\n`; 163 | } 164 | 165 | const actionRow = new ActionRowBuilder([await ctx.createComponent("refresh", state)]); 166 | 167 | const toggleGlobal = (await ctx.createComponent("toggleGlobal", state)) as ButtonBuilder; 168 | 169 | toggleGlobal.setEmoji({ name: "🌳" }); 170 | 171 | const backButton = await ctx.createComponent("back", state); 172 | const nextButton = await ctx.createComponent("next", state); 173 | 174 | if (state.page <= 1) { 175 | backButton.setDisabled(true); 176 | } 177 | 178 | if (players.length <= 10) { 179 | nextButton.setDisabled(true); 180 | } 181 | 182 | actionRow.addComponents(toggleGlobal, backButton, nextButton); 183 | 184 | return new MessageBuilder(new EmbedBuilder("Greatest Gardeners (Global)", description)).addComponents(actionRow); 185 | } 186 | -------------------------------------------------------------------------------- /src/commands/Tree.ts: -------------------------------------------------------------------------------- 1 | import humanizeDuration = require("humanize-duration"); 2 | import { 3 | ActionRowBuilder, 4 | Button, 5 | ButtonBuilder, 6 | ButtonContext, 7 | EmbedBuilder, 8 | ISlashCommand, 9 | MessageBuilder, 10 | SimpleError, 11 | SlashCommandBuilder, 12 | SlashCommandContext 13 | } from "interactions.ts"; 14 | import { renderTree } from "../util/image-generation"; 15 | import { getNextLevelRequiredXp, getTreeXp, incrementPlayerXp } from "../util/leveling"; 16 | import { generateNextSegment } from "../util/tree-generation"; 17 | import { getTreeHeight } from "../util/tree-height"; 18 | import { getTreeAge, getWateringInterval } from "../util/watering-interval"; 19 | 20 | export class Tree implements ISlashCommand { 21 | public builder = new SlashCommandBuilder("tree", "Display your server's tree.").setDMEnabled(false); 22 | 23 | public handler = async (ctx: SlashCommandContext): Promise => { 24 | if (ctx.game === null) return ctx.reply("Use /plant to plant a tree for your server first."); 25 | 26 | await ctx.defer(); 27 | 28 | ctx.interaction.message = await ctx.send(await buildTreeDisplayMessage(ctx)); 29 | 30 | const growthTime = getWateringInterval(ctx.game.pieces.length - 1); 31 | const time = Math.floor(Date.now() / 1000); 32 | 33 | if (ctx.game.lastWateredAt + growthTime > time) { 34 | ctx.timeouts.set( 35 | ctx.interaction.message.id, 36 | setTimeout(async () => { 37 | try { 38 | await ctx.edit(await buildTreeDisplayMessage(ctx)); 39 | } catch (err) { 40 | console.error(err); 41 | } 42 | }, (ctx.game.lastWateredAt + growthTime - time) * 1000) 43 | ); 44 | } 45 | }; 46 | 47 | public components = [ 48 | new Button( 49 | "grow", 50 | new ButtonBuilder().setEmoji({ name: "💧" }).setStyle(1), 51 | async (ctx: ButtonContext): Promise => { 52 | if (!ctx.game) throw new Error("Game data missing."); 53 | 54 | if (ctx.game.lastWateredBy === ctx.user.id) { 55 | const timeout = ctx.timeouts.get(ctx.interaction.message.id); 56 | if (timeout) clearTimeout(timeout); 57 | 58 | ctx.timeouts.set( 59 | ctx.interaction.message.id, 60 | setTimeout(async () => { 61 | try { 62 | await ctx.edit(await buildTreeDisplayMessage(ctx)); 63 | } catch (err) { 64 | console.error(err); 65 | } 66 | }, 3000) 67 | ); 68 | 69 | await ctx.reply( 70 | SimpleError("You watered this tree last, you must let someone else water it first.").setEphemeral(true) 71 | ); 72 | 73 | return; 74 | } 75 | 76 | const wateringInterval = getWateringInterval(ctx.game.pieces.length - 1), 77 | time = Math.floor(Date.now() / 1000); 78 | 79 | if (ctx.game.lastWateredAt + wateringInterval > time) { 80 | const timeout = ctx.timeouts.get(ctx.interaction.message.id); 81 | if (timeout) clearTimeout(timeout); 82 | 83 | ctx.timeouts.set( 84 | ctx.interaction.message.id, 85 | setTimeout(async () => { 86 | try { 87 | await ctx.edit(await buildTreeDisplayMessage(ctx)); 88 | } catch (err) { 89 | console.error(err); 90 | } 91 | }, 3000) 92 | ); 93 | 94 | await ctx.reply( 95 | new MessageBuilder( 96 | new EmbedBuilder( 97 | `\`\`${ctx.game.name}\`\` is growing already.`, 98 | `It was recently watered by <@${ctx.game.lastWateredBy}>.\n\nYou can water it next: ` 101 | ) 102 | ) 103 | ); 104 | 105 | return; 106 | } 107 | 108 | ctx.game.lastWateredAt = time; 109 | ctx.game.lastWateredBy = ctx.user.id; 110 | 111 | ctx.game.size = ctx.game.pieces.push(generateNextSegment(ctx.game)); 112 | 113 | const contributor = ctx.game.contributors.find((contributor) => contributor.userId === ctx.user.id); 114 | 115 | if (contributor) { 116 | contributor.count++; 117 | } else { 118 | ctx.game.contributors.push({ userId: ctx.user.id, count: 1 }); 119 | } 120 | 121 | if (ctx.game.size === 1000) ctx.game.background = "SpaceEdge"; 122 | if (ctx.game.size === 6) ctx.game.background = "Sky"; 123 | 124 | await ctx.game.save(); 125 | 126 | await ctx.reply(await buildTreeDisplayMessage(ctx)); 127 | 128 | const gainedXp = getTreeXp(ctx.game.size); 129 | const updatedPlayer = await incrementPlayerXp(ctx.user.id, gainedXp); 130 | 131 | const firstWater = ctx.player.level === 0 && ctx.player.xp === 0; 132 | 133 | if (ctx.player.notifyXp || firstWater) { 134 | const description = `Thanks for watering the tree! **\`\`+${gainedXp}XP\`\`**${ 135 | updatedPlayer.level !== ctx.player.level ? `\n\nYou are now level **${updatedPlayer.level}**!` : "" 136 | }`; 137 | 138 | const embed = new EmbedBuilder() 139 | .setTitle( 140 | `Level ${updatedPlayer.level} - \`\`${updatedPlayer.xp}/${getNextLevelRequiredXp( 141 | updatedPlayer.level 142 | )}XP\`\`` 143 | ) 144 | .setDescription(description); 145 | 146 | if (firstWater) { 147 | embed.setFooter({ 148 | text: "By default you'll only see level ups here, but if you'd like to see your XP when you water - Use /config xp-messages :)" 149 | }); 150 | } 151 | 152 | await ctx.send(new MessageBuilder(embed).setEphemeral(true)); 153 | 154 | return; 155 | } 156 | 157 | if (updatedPlayer.level !== ctx.player.level) 158 | await ctx.send( 159 | new MessageBuilder( 160 | new EmbedBuilder(`Congratulations! You are now level **${updatedPlayer.level}**!`) 161 | ).setEphemeral(true) 162 | ); 163 | } 164 | ), 165 | new Button( 166 | "refresh", 167 | new ButtonBuilder().setEmoji({ name: "🔄" }).setStyle(2), 168 | async (ctx: ButtonContext): Promise => { 169 | return ctx.reply(await buildTreeDisplayMessage(ctx)); 170 | } 171 | ) 172 | ]; 173 | } 174 | 175 | export async function buildTreeDisplayMessage( 176 | ctx: SlashCommandContext | ButtonContext, 177 | starting = false 178 | ): Promise { 179 | if (ctx.game === null) throw new Error("Game data missing."); 180 | 181 | const message = new MessageBuilder().addComponents( 182 | new ActionRowBuilder().addComponents(await ctx.createComponent("grow"), await ctx.createComponent("refresh")) 183 | ); 184 | 185 | const growthTime = getWateringInterval(ctx.game.pieces.length - 1); 186 | 187 | const canBeWateredAt = ctx.game.lastWateredAt + growthTime; 188 | const time = Math.floor(Date.now() / 1000); 189 | 190 | const timeout = ctx.timeouts.get(ctx.interaction?.message?.id ?? ctx.interaction.id); 191 | 192 | if (timeout !== undefined && ctx.interaction?.message?.id) { 193 | clearTimeout(timeout); 194 | ctx.timeouts.delete(ctx.interaction.message.id); 195 | } 196 | 197 | if (canBeWateredAt > time && ctx.interaction?.message?.id) { 198 | ctx.timeouts.set( 199 | ctx.interaction.message.id, 200 | setTimeout(async () => { 201 | try { 202 | await ctx.edit(await buildTreeDisplayMessage(ctx)); 203 | } catch (err) { 204 | console.error(err); 205 | } 206 | }, (canBeWateredAt - time) * 1000) 207 | ); 208 | } 209 | 210 | const growing = canBeWateredAt > time; 211 | 212 | const treeAge = growing 213 | ? (getTreeAge(ctx.game.pieces.length - 1) + time - ctx.game.lastWateredAt) * 1000 214 | : getTreeAge(ctx.game.pieces.length) * 1000; 215 | 216 | const embed = new EmbedBuilder().setTitle(ctx.game.name).setFooter({ 217 | text: `Your community has spent ${humanizeDuration(treeAge) 218 | .replace("minute,", `minute${treeAge >= 3600000 ? `,` : ""} and`) 219 | .replace("minutes,", `minutes${treeAge >= 3600000 ? `,` : ""} and`)} growing this tree. Well done!` 220 | }); 221 | 222 | embed.setImage(await renderTree(ctx.game)); 223 | 224 | let description = starting 225 | ? "Congratulations, here's your tree!\n\nNow that you've planted it, press the 💧 button below for it to grow taller!\n\n" 226 | : ""; 227 | 228 | const height = getTreeHeight(ctx.game); 229 | 230 | if (canBeWateredAt <= time) { 231 | description += `**Your tree is ${height}ft tall.**\n\nLast watered by: <@${ctx.game.lastWateredBy}>\n**Ready to be watered!**`; 232 | } else { 233 | description += `**Your tree is ${height}ft tall.**\n\n**Thanks <@${ctx.game.lastWateredBy}> for watering the tree!**\nIt's growing right now, come back .`; 234 | } 235 | 236 | embed.setDescription(description); 237 | 238 | message.addEmbeds(embed); 239 | 240 | return message; 241 | } 242 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@discordjs/collection@^0.4.0": 6 | version "0.4.0" 7 | resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.4.0.tgz#b6488286a1cc7b41b644d7e6086f25a1c1e6f837" 8 | integrity sha512-zmjq+l/rV35kE6zRrwe8BHqV78JvIh2ybJeZavBi5NySjWXqN3hmmAKg7kYMMXSeiWtSsMoZ/+MQi0DiQWy2lw== 9 | 10 | "@discordjs/rest@^0.3.0": 11 | version "0.3.0" 12 | resolved "https://registry.yarnpkg.com/@discordjs/rest/-/rest-0.3.0.tgz#89e06a42b168c91598891d6bf860353e28fba5d2" 13 | integrity sha512-F9aeP3odlAlllM1ciBZLdd+adiAyBj4VaZBejj4UMj4afE2wfCkNTGvYYiRxrXUE9fN7e/BuDP2ePl0tVA2m7Q== 14 | dependencies: 15 | "@discordjs/collection" "^0.4.0" 16 | "@sapphire/async-queue" "^1.1.9" 17 | "@sapphire/snowflake" "^3.0.1" 18 | discord-api-types "^0.26.1" 19 | form-data "^4.0.0" 20 | node-fetch "^2.6.5" 21 | tslib "^2.3.1" 22 | 23 | "@eslint/eslintrc@^1.2.1": 24 | version "1.2.1" 25 | resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.1.tgz#8b5e1c49f4077235516bc9ec7d41378c0f69b8c6" 26 | integrity sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ== 27 | dependencies: 28 | ajv "^6.12.4" 29 | debug "^4.3.2" 30 | espree "^9.3.1" 31 | globals "^13.9.0" 32 | ignore "^5.2.0" 33 | import-fresh "^3.2.1" 34 | js-yaml "^4.1.0" 35 | minimatch "^3.0.4" 36 | strip-json-comments "^3.1.1" 37 | 38 | "@fastify/ajv-compiler@^1.0.0": 39 | version "1.1.0" 40 | resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz#5ce80b1fc8bebffc8c5ba428d5e392d0f9ed10a1" 41 | integrity sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg== 42 | dependencies: 43 | ajv "^6.12.6" 44 | 45 | "@humanwhocodes/config-array@^0.9.2": 46 | version "0.9.5" 47 | resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" 48 | integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== 49 | dependencies: 50 | "@humanwhocodes/object-schema" "^1.2.1" 51 | debug "^4.1.1" 52 | minimatch "^3.0.4" 53 | 54 | "@humanwhocodes/object-schema@^1.2.1": 55 | version "1.2.1" 56 | resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" 57 | integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== 58 | 59 | "@nodelib/fs.scandir@2.1.5": 60 | version "2.1.5" 61 | resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" 62 | integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== 63 | dependencies: 64 | "@nodelib/fs.stat" "2.0.5" 65 | run-parallel "^1.1.9" 66 | 67 | "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": 68 | version "2.0.5" 69 | resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" 70 | integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== 71 | 72 | "@nodelib/fs.walk@^1.2.3": 73 | version "1.2.8" 74 | resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" 75 | integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== 76 | dependencies: 77 | "@nodelib/fs.scandir" "2.1.5" 78 | fastq "^1.6.0" 79 | 80 | "@redis/bloom@1.0.2": 81 | version "1.0.2" 82 | resolved "https://registry.yarnpkg.com/@redis/bloom/-/bloom-1.0.2.tgz#42b82ec399a92db05e29fffcdfd9235a5fc15cdf" 83 | integrity sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw== 84 | 85 | "@redis/client@1.1.0": 86 | version "1.1.0" 87 | resolved "https://registry.yarnpkg.com/@redis/client/-/client-1.1.0.tgz#e52a85aee802796ceb14bf27daf9550f51f238b8" 88 | integrity sha512-xO9JDIgzsZYDl3EvFhl6LC52DP3q3GCMUer8zHgKV6qSYsq1zB+pZs9+T80VgcRogrlRYhi4ZlfX6A+bHiBAgA== 89 | dependencies: 90 | cluster-key-slot "1.1.0" 91 | generic-pool "3.8.2" 92 | yallist "4.0.0" 93 | 94 | "@redis/graph@1.0.1": 95 | version "1.0.1" 96 | resolved "https://registry.yarnpkg.com/@redis/graph/-/graph-1.0.1.tgz#eabc58ba99cd70d0c907169c02b55497e4ec8a99" 97 | integrity sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ== 98 | 99 | "@redis/json@1.0.3": 100 | version "1.0.3" 101 | resolved "https://registry.yarnpkg.com/@redis/json/-/json-1.0.3.tgz#a13fde1d22ebff0ae2805cd8e1e70522b08ea866" 102 | integrity sha512-4X0Qv0BzD9Zlb0edkUoau5c1bInWSICqXAGrpwEltkncUwcxJIGEcVryZhLgb0p/3PkKaLIWkjhHRtLe9yiA7Q== 103 | 104 | "@redis/search@1.0.6": 105 | version "1.0.6" 106 | resolved "https://registry.yarnpkg.com/@redis/search/-/search-1.0.6.tgz#53d7451c2783f011ebc48ec4c2891264e0b22f10" 107 | integrity sha512-pP+ZQRis5P21SD6fjyCeLcQdps+LuTzp2wdUbzxEmNhleighDDTD5ck8+cYof+WLec4csZX7ks+BuoMw0RaZrA== 108 | 109 | "@redis/time-series@1.0.3": 110 | version "1.0.3" 111 | resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.3.tgz#4cfca8e564228c0bddcdf4418cba60c20b224ac4" 112 | integrity sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA== 113 | 114 | "@sapphire/async-queue@^1.1.9": 115 | version "1.3.1" 116 | resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.3.1.tgz#9d861e626dbffae02d808e13f823d4510e450a78" 117 | integrity sha512-FFTlPOWZX1kDj9xCAsRzH5xEJfawg1lNoYAA+ecOWJMHOfiZYb1uXOI3ne9U4UILSEPwfE68p3T9wUHwIQfR0g== 118 | 119 | "@sapphire/snowflake@^3.0.1": 120 | version "3.2.1" 121 | resolved "https://registry.yarnpkg.com/@sapphire/snowflake/-/snowflake-3.2.1.tgz#027f217779ec7fd324d35cf941b3de49b4f67877" 122 | integrity sha512-vmZq1I6J6iNRQVXP+N9HzOMOY4ORB3MunoFeWCw/aBnZTf1cDgDvP0RZFQS53B1TN95AIgFY9T+ItQ/fWAUYWQ== 123 | 124 | "@types/humanize-duration@^3.27.1": 125 | version "3.27.1" 126 | resolved "https://registry.yarnpkg.com/@types/humanize-duration/-/humanize-duration-3.27.1.tgz#f14740d1f585a0a8e3f46359b62fda8b0eaa31e7" 127 | integrity sha512-K3e+NZlpCKd6Bd/EIdqjFJRFHbrq5TzPPLwREk5Iv/YoIjQrs6ljdAUCo+Lb2xFlGNOjGSE0dqsVD19cZL137w== 128 | 129 | "@types/json-schema@^7.0.9": 130 | version "7.0.11" 131 | resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" 132 | integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== 133 | 134 | "@types/node-fetch@^2.6.1": 135 | version "2.6.1" 136 | resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.1.tgz#8f127c50481db65886800ef496f20bbf15518975" 137 | integrity sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA== 138 | dependencies: 139 | "@types/node" "*" 140 | form-data "^3.0.0" 141 | 142 | "@types/node@*": 143 | version "17.0.31" 144 | resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.31.tgz#a5bb84ecfa27eec5e1c802c6bbf8139bdb163a5d" 145 | integrity sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q== 146 | 147 | "@types/node@^14.18.3": 148 | version "14.18.12" 149 | resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.12.tgz#0d4557fd3b94497d793efd4e7d92df2f83b4ef24" 150 | integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A== 151 | 152 | "@types/uuid@^8.3.4": 153 | version "8.3.4" 154 | resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" 155 | integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== 156 | 157 | "@types/webidl-conversions@*": 158 | version "6.1.1" 159 | resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz#e33bc8ea812a01f63f90481c666334844b12a09e" 160 | integrity sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q== 161 | 162 | "@types/whatwg-url@^8.2.1": 163 | version "8.2.1" 164 | resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-8.2.1.tgz#f1aac222dab7c59e011663a0cb0a3117b2ef05d4" 165 | integrity sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ== 166 | dependencies: 167 | "@types/node" "*" 168 | "@types/webidl-conversions" "*" 169 | 170 | "@typescript-eslint/eslint-plugin@^5.17.0": 171 | version "5.17.0" 172 | resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.17.0.tgz#704eb4e75039000531255672bf1c85ee85cf1d67" 173 | integrity sha512-qVstvQilEd89HJk3qcbKt/zZrfBZ+9h2ynpAGlWjWiizA7m/MtLT9RoX6gjtpE500vfIg8jogAkDzdCxbsFASQ== 174 | dependencies: 175 | "@typescript-eslint/scope-manager" "5.17.0" 176 | "@typescript-eslint/type-utils" "5.17.0" 177 | "@typescript-eslint/utils" "5.17.0" 178 | debug "^4.3.2" 179 | functional-red-black-tree "^1.0.1" 180 | ignore "^5.1.8" 181 | regexpp "^3.2.0" 182 | semver "^7.3.5" 183 | tsutils "^3.21.0" 184 | 185 | "@typescript-eslint/parser@^5.17.0": 186 | version "5.17.0" 187 | resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.17.0.tgz#7def77d5bcd8458d12d52909118cf3f0a45f89d5" 188 | integrity sha512-aRzW9Jg5Rlj2t2/crzhA2f23SIYFlF9mchGudyP0uiD6SenIxzKoLjwzHbafgHn39dNV/TV7xwQkLfFTZlJ4ig== 189 | dependencies: 190 | "@typescript-eslint/scope-manager" "5.17.0" 191 | "@typescript-eslint/types" "5.17.0" 192 | "@typescript-eslint/typescript-estree" "5.17.0" 193 | debug "^4.3.2" 194 | 195 | "@typescript-eslint/scope-manager@5.17.0": 196 | version "5.17.0" 197 | resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.17.0.tgz#4cea7d0e0bc0e79eb60cad431c89120987c3f952" 198 | integrity sha512-062iCYQF/doQ9T2WWfJohQKKN1zmmXVfAcS3xaiialiw8ZUGy05Em6QVNYJGO34/sU1a7a+90U3dUNfqUDHr3w== 199 | dependencies: 200 | "@typescript-eslint/types" "5.17.0" 201 | "@typescript-eslint/visitor-keys" "5.17.0" 202 | 203 | "@typescript-eslint/type-utils@5.17.0": 204 | version "5.17.0" 205 | resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.17.0.tgz#1c4549d68c89877662224aabb29fbbebf5fc9672" 206 | integrity sha512-3hU0RynUIlEuqMJA7dragb0/75gZmwNwFf/QJokWzPehTZousP/MNifVSgjxNcDCkM5HI2K22TjQWUmmHUINSg== 207 | dependencies: 208 | "@typescript-eslint/utils" "5.17.0" 209 | debug "^4.3.2" 210 | tsutils "^3.21.0" 211 | 212 | "@typescript-eslint/types@5.17.0": 213 | version "5.17.0" 214 | resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.17.0.tgz#861ec9e669ffa2aa9b873dd4d28d9b1ce26d216f" 215 | integrity sha512-AgQ4rWzmCxOZLioFEjlzOI3Ch8giDWx8aUDxyNw9iOeCvD3GEYAB7dxWGQy4T/rPVe8iPmu73jPHuaSqcjKvxw== 216 | 217 | "@typescript-eslint/typescript-estree@5.17.0": 218 | version "5.17.0" 219 | resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.17.0.tgz#a7cba7dfc8f9cc2ac78c18584e684507df4f2488" 220 | integrity sha512-X1gtjEcmM7Je+qJRhq7ZAAaNXYhTgqMkR10euC4Si6PIjb+kwEQHSxGazXUQXFyqfEXdkGf6JijUu5R0uceQzg== 221 | dependencies: 222 | "@typescript-eslint/types" "5.17.0" 223 | "@typescript-eslint/visitor-keys" "5.17.0" 224 | debug "^4.3.2" 225 | globby "^11.0.4" 226 | is-glob "^4.0.3" 227 | semver "^7.3.5" 228 | tsutils "^3.21.0" 229 | 230 | "@typescript-eslint/utils@5.17.0": 231 | version "5.17.0" 232 | resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.17.0.tgz#549a9e1d491c6ccd3624bc3c1b098f5cfb45f306" 233 | integrity sha512-DVvndq1QoxQH+hFv+MUQHrrWZ7gQ5KcJzyjhzcqB1Y2Xes1UQQkTRPUfRpqhS8mhTWsSb2+iyvDW1Lef5DD7vA== 234 | dependencies: 235 | "@types/json-schema" "^7.0.9" 236 | "@typescript-eslint/scope-manager" "5.17.0" 237 | "@typescript-eslint/types" "5.17.0" 238 | "@typescript-eslint/typescript-estree" "5.17.0" 239 | eslint-scope "^5.1.1" 240 | eslint-utils "^3.0.0" 241 | 242 | "@typescript-eslint/visitor-keys@5.17.0": 243 | version "5.17.0" 244 | resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.17.0.tgz#52daae45c61b0211b4c81b53a71841911e479128" 245 | integrity sha512-6K/zlc4OfCagUu7Am/BD5k8PSWQOgh34Nrv9Rxe2tBzlJ7uOeJ/h7ugCGDCeEZHT6k2CJBhbk9IsbkPI0uvUkA== 246 | dependencies: 247 | "@typescript-eslint/types" "5.17.0" 248 | eslint-visitor-keys "^3.0.0" 249 | 250 | abstract-logging@^2.0.0: 251 | version "2.0.1" 252 | resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" 253 | integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA== 254 | 255 | acorn-jsx@^5.3.1: 256 | version "5.3.2" 257 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" 258 | integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== 259 | 260 | acorn@^8.7.0: 261 | version "8.7.0" 262 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" 263 | integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== 264 | 265 | ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.4, ajv@^6.12.6: 266 | version "6.12.6" 267 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 268 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 269 | dependencies: 270 | fast-deep-equal "^3.1.1" 271 | fast-json-stable-stringify "^2.0.0" 272 | json-schema-traverse "^0.4.1" 273 | uri-js "^4.2.2" 274 | 275 | ajv@^8.1.0: 276 | version "8.11.0" 277 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" 278 | integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== 279 | dependencies: 280 | fast-deep-equal "^3.1.1" 281 | json-schema-traverse "^1.0.0" 282 | require-from-string "^2.0.2" 283 | uri-js "^4.2.2" 284 | 285 | ansi-regex@^5.0.1: 286 | version "5.0.1" 287 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 288 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 289 | 290 | ansi-styles@^4.1.0: 291 | version "4.3.0" 292 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 293 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 294 | dependencies: 295 | color-convert "^2.0.1" 296 | 297 | archy@^1.0.0: 298 | version "1.0.0" 299 | resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" 300 | integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= 301 | 302 | argparse@^2.0.1: 303 | version "2.0.1" 304 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 305 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 306 | 307 | array-union@^2.1.0: 308 | version "2.1.0" 309 | resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" 310 | integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== 311 | 312 | asynckit@^0.4.0: 313 | version "0.4.0" 314 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 315 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 316 | 317 | atomic-sleep@^1.0.0: 318 | version "1.0.0" 319 | resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" 320 | integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== 321 | 322 | avvio@^7.1.2: 323 | version "7.2.5" 324 | resolved "https://registry.yarnpkg.com/avvio/-/avvio-7.2.5.tgz#65ba255f10b0bea7ac6eded71a5344cd88f5de19" 325 | integrity sha512-AOhBxyLVdpOad3TujtC9kL/9r3HnTkxwQ5ggOsYrvvZP1cCFvzHWJd5XxZDFuTn+IN8vkKSG5SEJrd27vCSbeA== 326 | dependencies: 327 | archy "^1.0.0" 328 | debug "^4.0.0" 329 | fastq "^1.6.1" 330 | queue-microtask "^1.1.2" 331 | 332 | balanced-match@^1.0.0: 333 | version "1.0.2" 334 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 335 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 336 | 337 | base64-js@^1.3.1: 338 | version "1.5.1" 339 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" 340 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 341 | 342 | brace-expansion@^1.1.7: 343 | version "1.1.11" 344 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 345 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 346 | dependencies: 347 | balanced-match "^1.0.0" 348 | concat-map "0.0.1" 349 | 350 | braces@^3.0.2: 351 | version "3.0.2" 352 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 353 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 354 | dependencies: 355 | fill-range "^7.0.1" 356 | 357 | bson@^4.6.2: 358 | version "4.6.3" 359 | resolved "https://registry.yarnpkg.com/bson/-/bson-4.6.3.tgz#d1a9a0b84b9e84b62390811fc5580f6a8b1d858c" 360 | integrity sha512-rAqP5hcUVJhXP2MCSNVsf0oM2OGU1So6A9pVRDYayvJ5+hygXHQApf87wd5NlhPM1J9RJnbqxIG/f8QTzRoQ4A== 361 | dependencies: 362 | buffer "^5.6.0" 363 | 364 | buffer@^5.6.0: 365 | version "5.7.1" 366 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" 367 | integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== 368 | dependencies: 369 | base64-js "^1.3.1" 370 | ieee754 "^1.1.13" 371 | 372 | bytes@3.1.2: 373 | version "3.1.2" 374 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 375 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 376 | 377 | callsites@^3.0.0: 378 | version "3.1.0" 379 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 380 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 381 | 382 | chalk@^4.0.0: 383 | version "4.1.2" 384 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 385 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 386 | dependencies: 387 | ansi-styles "^4.1.0" 388 | supports-color "^7.1.0" 389 | 390 | cluster-key-slot@1.1.0: 391 | version "1.1.0" 392 | resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" 393 | integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw== 394 | 395 | color-convert@^2.0.1: 396 | version "2.0.1" 397 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 398 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 399 | dependencies: 400 | color-name "~1.1.4" 401 | 402 | color-name@~1.1.4: 403 | version "1.1.4" 404 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 405 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 406 | 407 | combined-stream@^1.0.8: 408 | version "1.0.8" 409 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 410 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 411 | dependencies: 412 | delayed-stream "~1.0.0" 413 | 414 | concat-map@0.0.1: 415 | version "0.0.1" 416 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 417 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 418 | 419 | cookie@^0.4.0: 420 | version "0.4.2" 421 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" 422 | integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== 423 | 424 | cross-spawn@^7.0.2: 425 | version "7.0.3" 426 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 427 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 428 | dependencies: 429 | path-key "^3.1.0" 430 | shebang-command "^2.0.0" 431 | which "^2.0.1" 432 | 433 | debug@4.x, debug@^4.0.0, debug@^4.1.1, debug@^4.3.2: 434 | version "4.3.4" 435 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 436 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 437 | dependencies: 438 | ms "2.1.2" 439 | 440 | deep-is@^0.1.3: 441 | version "0.1.4" 442 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" 443 | integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== 444 | 445 | deepmerge@^4.2.2: 446 | version "4.2.2" 447 | resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" 448 | integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== 449 | 450 | delayed-stream@~1.0.0: 451 | version "1.0.0" 452 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 453 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 454 | 455 | denque@^2.0.1: 456 | version "2.0.1" 457 | resolved "https://registry.yarnpkg.com/denque/-/denque-2.0.1.tgz#bcef4c1b80dc32efe97515744f21a4229ab8934a" 458 | integrity sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ== 459 | 460 | depd@2.0.0: 461 | version "2.0.0" 462 | resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 463 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 464 | 465 | dir-glob@^3.0.1: 466 | version "3.0.1" 467 | resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" 468 | integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== 469 | dependencies: 470 | path-type "^4.0.0" 471 | 472 | discord-api-types@^0.26.1: 473 | version "0.26.1" 474 | resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.26.1.tgz#726f766ddc37d60da95740991d22cb6ef2ed787b" 475 | integrity sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ== 476 | 477 | discord-api-types@^0.32.1: 478 | version "0.32.1" 479 | resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.32.1.tgz#c468ec31a1ac2565673619ba1e0d35f01d339a65" 480 | integrity sha512-/ewl0CPYT5xjOC+SJ7wADJKjtpZfiiUaYXOP/Ns54lnBcv4Xqa4iKSqRF/w1fjiUvWTYN9W8UuOiyCHtmu5fJw== 481 | 482 | doctrine@^3.0.0: 483 | version "3.0.0" 484 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" 485 | integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 486 | dependencies: 487 | esutils "^2.0.2" 488 | 489 | dotenv@^16.0.0: 490 | version "16.0.0" 491 | resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" 492 | integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== 493 | 494 | escape-string-regexp@^4.0.0: 495 | version "4.0.0" 496 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 497 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 498 | 499 | eslint-scope@^5.1.1: 500 | version "5.1.1" 501 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" 502 | integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== 503 | dependencies: 504 | esrecurse "^4.3.0" 505 | estraverse "^4.1.1" 506 | 507 | eslint-scope@^7.1.1: 508 | version "7.1.1" 509 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" 510 | integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== 511 | dependencies: 512 | esrecurse "^4.3.0" 513 | estraverse "^5.2.0" 514 | 515 | eslint-utils@^3.0.0: 516 | version "3.0.0" 517 | resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" 518 | integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== 519 | dependencies: 520 | eslint-visitor-keys "^2.0.0" 521 | 522 | eslint-visitor-keys@^2.0.0: 523 | version "2.1.0" 524 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" 525 | integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== 526 | 527 | eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: 528 | version "3.3.0" 529 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" 530 | integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== 531 | 532 | eslint@^8.12.0: 533 | version "8.12.0" 534 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.12.0.tgz#c7a5bd1cfa09079aae64c9076c07eada66a46e8e" 535 | integrity sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q== 536 | dependencies: 537 | "@eslint/eslintrc" "^1.2.1" 538 | "@humanwhocodes/config-array" "^0.9.2" 539 | ajv "^6.10.0" 540 | chalk "^4.0.0" 541 | cross-spawn "^7.0.2" 542 | debug "^4.3.2" 543 | doctrine "^3.0.0" 544 | escape-string-regexp "^4.0.0" 545 | eslint-scope "^7.1.1" 546 | eslint-utils "^3.0.0" 547 | eslint-visitor-keys "^3.3.0" 548 | espree "^9.3.1" 549 | esquery "^1.4.0" 550 | esutils "^2.0.2" 551 | fast-deep-equal "^3.1.3" 552 | file-entry-cache "^6.0.1" 553 | functional-red-black-tree "^1.0.1" 554 | glob-parent "^6.0.1" 555 | globals "^13.6.0" 556 | ignore "^5.2.0" 557 | import-fresh "^3.0.0" 558 | imurmurhash "^0.1.4" 559 | is-glob "^4.0.0" 560 | js-yaml "^4.1.0" 561 | json-stable-stringify-without-jsonify "^1.0.1" 562 | levn "^0.4.1" 563 | lodash.merge "^4.6.2" 564 | minimatch "^3.0.4" 565 | natural-compare "^1.4.0" 566 | optionator "^0.9.1" 567 | regexpp "^3.2.0" 568 | strip-ansi "^6.0.1" 569 | strip-json-comments "^3.1.0" 570 | text-table "^0.2.0" 571 | v8-compile-cache "^2.0.3" 572 | 573 | espree@^9.3.1: 574 | version "9.3.1" 575 | resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" 576 | integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== 577 | dependencies: 578 | acorn "^8.7.0" 579 | acorn-jsx "^5.3.1" 580 | eslint-visitor-keys "^3.3.0" 581 | 582 | esquery@^1.4.0: 583 | version "1.4.0" 584 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" 585 | integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== 586 | dependencies: 587 | estraverse "^5.1.0" 588 | 589 | esrecurse@^4.3.0: 590 | version "4.3.0" 591 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 592 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 593 | dependencies: 594 | estraverse "^5.2.0" 595 | 596 | estraverse@^4.1.1: 597 | version "4.3.0" 598 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" 599 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 600 | 601 | estraverse@^5.1.0, estraverse@^5.2.0: 602 | version "5.3.0" 603 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" 604 | integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 605 | 606 | esutils@^2.0.2: 607 | version "2.0.3" 608 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 609 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 610 | 611 | fast-decode-uri-component@^1.0.1: 612 | version "1.0.1" 613 | resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" 614 | integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== 615 | 616 | fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: 617 | version "3.1.3" 618 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 619 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 620 | 621 | fast-glob@^3.2.9: 622 | version "3.2.11" 623 | resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" 624 | integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== 625 | dependencies: 626 | "@nodelib/fs.stat" "^2.0.2" 627 | "@nodelib/fs.walk" "^1.2.3" 628 | glob-parent "^5.1.2" 629 | merge2 "^1.3.0" 630 | micromatch "^4.0.4" 631 | 632 | fast-json-stable-stringify@^2.0.0: 633 | version "2.1.0" 634 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 635 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 636 | 637 | fast-json-stringify@^2.5.2: 638 | version "2.7.13" 639 | resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz#277aa86c2acba4d9851bd6108ed657aa327ed8c0" 640 | integrity sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA== 641 | dependencies: 642 | ajv "^6.11.0" 643 | deepmerge "^4.2.2" 644 | rfdc "^1.2.0" 645 | string-similarity "^4.0.1" 646 | 647 | fast-levenshtein@^2.0.6: 648 | version "2.0.6" 649 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 650 | integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= 651 | 652 | fast-redact@^3.0.0: 653 | version "3.1.1" 654 | resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.1.tgz#790fcff8f808c2e12fabbfb2be5cb2deda448fa0" 655 | integrity sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A== 656 | 657 | fast-safe-stringify@^2.0.8: 658 | version "2.1.1" 659 | resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" 660 | integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== 661 | 662 | fastify-error@^0.3.0: 663 | version "0.3.1" 664 | resolved "https://registry.yarnpkg.com/fastify-error/-/fastify-error-0.3.1.tgz#8eb993e15e3cf57f0357fc452af9290f1c1278d2" 665 | integrity sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ== 666 | 667 | fastify-plugin@^2.0.0: 668 | version "2.3.4" 669 | resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-2.3.4.tgz#b17abdc36a97877d88101fb86ad8a07f2c07de87" 670 | integrity sha512-I+Oaj6p9oiRozbam30sh39BiuiqBda7yK2nmSPVwDCfIBlKnT8YB3MY+pRQc2Fcd07bf6KPGklHJaQ2Qu81TYQ== 671 | dependencies: 672 | semver "^7.3.2" 673 | 674 | fastify-raw-body@^3.2.0: 675 | version "3.2.0" 676 | resolved "https://registry.yarnpkg.com/fastify-raw-body/-/fastify-raw-body-3.2.0.tgz#ec4db996164cf3149064fbb8ad30cdf82cb866e8" 677 | integrity sha512-Eci5FobK2eks5TdnZPysdT05/LCERSRqjm68+xYZQhyNuvin8hR4LkmuwpfUc01uTitFqSakHcu9/LOvdqN0vQ== 678 | dependencies: 679 | fastify-plugin "^2.0.0" 680 | raw-body "^2.4.1" 681 | secure-json-parse "^2.1.0" 682 | 683 | fastify@^3.27.4: 684 | version "3.27.4" 685 | resolved "https://registry.yarnpkg.com/fastify/-/fastify-3.27.4.tgz#67ffd61b5bea74768a7de28dbef5b6bc58f9e953" 686 | integrity sha512-SOfnHBxG9zxCSIvt6aHoR/cao8QBddWmGP/mb5KQKRc+KI1kB7b79M2hCDOTSyHdLAF2OX+oI6X3weeLc+MqKg== 687 | dependencies: 688 | "@fastify/ajv-compiler" "^1.0.0" 689 | abstract-logging "^2.0.0" 690 | avvio "^7.1.2" 691 | fast-json-stringify "^2.5.2" 692 | fastify-error "^0.3.0" 693 | find-my-way "^4.5.0" 694 | flatstr "^1.0.12" 695 | light-my-request "^4.2.0" 696 | pino "^6.13.0" 697 | process-warning "^1.0.0" 698 | proxy-addr "^2.0.7" 699 | rfdc "^1.1.4" 700 | secure-json-parse "^2.0.0" 701 | semver "^7.3.2" 702 | tiny-lru "^8.0.1" 703 | 704 | fastq@^1.6.0, fastq@^1.6.1: 705 | version "1.13.0" 706 | resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" 707 | integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== 708 | dependencies: 709 | reusify "^1.0.4" 710 | 711 | file-entry-cache@^6.0.1: 712 | version "6.0.1" 713 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" 714 | integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== 715 | dependencies: 716 | flat-cache "^3.0.4" 717 | 718 | fill-range@^7.0.1: 719 | version "7.0.1" 720 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 721 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 722 | dependencies: 723 | to-regex-range "^5.0.1" 724 | 725 | find-my-way@^4.5.0: 726 | version "4.5.1" 727 | resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-4.5.1.tgz#758e959194b90aea0270db18fff75e2fceb2239f" 728 | integrity sha512-kE0u7sGoUFbMXcOG/xpkmz4sRLCklERnBcg7Ftuu1iAxsfEt2S46RLJ3Sq7vshsEy2wJT2hZxE58XZK27qa8kg== 729 | dependencies: 730 | fast-decode-uri-component "^1.0.1" 731 | fast-deep-equal "^3.1.3" 732 | safe-regex2 "^2.0.0" 733 | semver-store "^0.3.0" 734 | 735 | flat-cache@^3.0.4: 736 | version "3.0.4" 737 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" 738 | integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== 739 | dependencies: 740 | flatted "^3.1.0" 741 | rimraf "^3.0.2" 742 | 743 | flatstr@^1.0.12: 744 | version "1.0.12" 745 | resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" 746 | integrity sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw== 747 | 748 | flatted@^3.1.0: 749 | version "3.2.5" 750 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" 751 | integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== 752 | 753 | form-data@^3.0.0: 754 | version "3.0.1" 755 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" 756 | integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== 757 | dependencies: 758 | asynckit "^0.4.0" 759 | combined-stream "^1.0.8" 760 | mime-types "^2.1.12" 761 | 762 | form-data@^4.0.0: 763 | version "4.0.0" 764 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" 765 | integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== 766 | dependencies: 767 | asynckit "^0.4.0" 768 | combined-stream "^1.0.8" 769 | mime-types "^2.1.12" 770 | 771 | forwarded@0.2.0: 772 | version "0.2.0" 773 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" 774 | integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== 775 | 776 | fs.realpath@^1.0.0: 777 | version "1.0.0" 778 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 779 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 780 | 781 | functional-red-black-tree@^1.0.1: 782 | version "1.0.1" 783 | resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" 784 | integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= 785 | 786 | generic-pool@3.8.2: 787 | version "3.8.2" 788 | resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.8.2.tgz#aab4f280adb522fdfbdc5e5b64d718d3683f04e9" 789 | integrity sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg== 790 | 791 | glob-parent@^5.1.2: 792 | version "5.1.2" 793 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 794 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 795 | dependencies: 796 | is-glob "^4.0.1" 797 | 798 | glob-parent@^6.0.1: 799 | version "6.0.2" 800 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" 801 | integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== 802 | dependencies: 803 | is-glob "^4.0.3" 804 | 805 | glob@^7.1.3: 806 | version "7.2.0" 807 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" 808 | integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== 809 | dependencies: 810 | fs.realpath "^1.0.0" 811 | inflight "^1.0.4" 812 | inherits "2" 813 | minimatch "^3.0.4" 814 | once "^1.3.0" 815 | path-is-absolute "^1.0.0" 816 | 817 | globals@^13.6.0, globals@^13.9.0: 818 | version "13.13.0" 819 | resolved "https://registry.yarnpkg.com/globals/-/globals-13.13.0.tgz#ac32261060d8070e2719dd6998406e27d2b5727b" 820 | integrity sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A== 821 | dependencies: 822 | type-fest "^0.20.2" 823 | 824 | globby@^11.0.4: 825 | version "11.1.0" 826 | resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" 827 | integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== 828 | dependencies: 829 | array-union "^2.1.0" 830 | dir-glob "^3.0.1" 831 | fast-glob "^3.2.9" 832 | ignore "^5.2.0" 833 | merge2 "^1.4.1" 834 | slash "^3.0.0" 835 | 836 | has-flag@^4.0.0: 837 | version "4.0.0" 838 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 839 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 840 | 841 | http-errors@2.0.0: 842 | version "2.0.0" 843 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 844 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 845 | dependencies: 846 | depd "2.0.0" 847 | inherits "2.0.4" 848 | setprototypeof "1.2.0" 849 | statuses "2.0.1" 850 | toidentifier "1.0.1" 851 | 852 | humanize-duration@^3.27.1: 853 | version "3.27.1" 854 | resolved "https://registry.yarnpkg.com/humanize-duration/-/humanize-duration-3.27.1.tgz#2cd4ea4b03bd92184aee6d90d77a8f3d7628df69" 855 | integrity sha512-jCVkMl+EaM80rrMrAPl96SGG4NRac53UyI1o/yAzebDntEY6K6/Fj2HOjdPg8omTqIe5Y0wPBai2q5xXrIbarA== 856 | 857 | iconv-lite@0.4.24: 858 | version "0.4.24" 859 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 860 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 861 | dependencies: 862 | safer-buffer ">= 2.1.2 < 3" 863 | 864 | ieee754@^1.1.13: 865 | version "1.2.1" 866 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 867 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 868 | 869 | ignore@^5.1.8, ignore@^5.2.0: 870 | version "5.2.0" 871 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" 872 | integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== 873 | 874 | import-fresh@^3.0.0, import-fresh@^3.2.1: 875 | version "3.3.0" 876 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" 877 | integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 878 | dependencies: 879 | parent-module "^1.0.0" 880 | resolve-from "^4.0.0" 881 | 882 | imurmurhash@^0.1.4: 883 | version "0.1.4" 884 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 885 | integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= 886 | 887 | inflight@^1.0.4: 888 | version "1.0.6" 889 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 890 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 891 | dependencies: 892 | once "^1.3.0" 893 | wrappy "1" 894 | 895 | inherits@2, inherits@2.0.4: 896 | version "2.0.4" 897 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 898 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 899 | 900 | interactions.ts@^1.0.38: 901 | version "1.0.38" 902 | resolved "https://registry.yarnpkg.com/interactions.ts/-/interactions.ts-1.0.38.tgz#e9676d7f0964678aee4461216a8ee2fd18580049" 903 | integrity sha512-HmYgYlHvDkkAcd6t2EXtC7FeSf5iti4mxMGm3Ug6eyLYjjkbOfKJDI2+HARTs2FTaiTeaQ92XqEwG5j8TMjuxA== 904 | dependencies: 905 | "@discordjs/rest" "^0.3.0" 906 | discord-api-types "^0.32.1" 907 | uuid "^8.3.2" 908 | 909 | ip@^1.1.5: 910 | version "1.1.5" 911 | resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" 912 | integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= 913 | 914 | ipaddr.js@1.9.1: 915 | version "1.9.1" 916 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" 917 | integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 918 | 919 | is-extglob@^2.1.1: 920 | version "2.1.1" 921 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 922 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 923 | 924 | is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: 925 | version "4.0.3" 926 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 927 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 928 | dependencies: 929 | is-extglob "^2.1.1" 930 | 931 | is-number@^7.0.0: 932 | version "7.0.0" 933 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 934 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 935 | 936 | isexe@^2.0.0: 937 | version "2.0.0" 938 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 939 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 940 | 941 | js-yaml@^4.1.0: 942 | version "4.1.0" 943 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 944 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 945 | dependencies: 946 | argparse "^2.0.1" 947 | 948 | json-schema-traverse@^0.4.1: 949 | version "0.4.1" 950 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 951 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 952 | 953 | json-schema-traverse@^1.0.0: 954 | version "1.0.0" 955 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" 956 | integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== 957 | 958 | json-stable-stringify-without-jsonify@^1.0.1: 959 | version "1.0.1" 960 | resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 961 | integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= 962 | 963 | kareem@2.3.5: 964 | version "2.3.5" 965 | resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.5.tgz#111fe9dbab754c8ed88b7a2360e2680cec1420ca" 966 | integrity sha512-qxCyQtp3ioawkiRNQr/v8xw9KIviMSSNmy+63Wubj7KmMn3g7noRXIZB4vPCAP+ETi2SR8eH6CvmlKZuGpoHOg== 967 | 968 | levn@^0.4.1: 969 | version "0.4.1" 970 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" 971 | integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== 972 | dependencies: 973 | prelude-ls "^1.2.1" 974 | type-check "~0.4.0" 975 | 976 | light-my-request@^4.2.0: 977 | version "4.9.0" 978 | resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-4.9.0.tgz#83559c7ce7e503466113e36f40a1d596a1886626" 979 | integrity sha512-b1U3z4OVPoO/KanT14NRkXMr9rRtXAiq0ORqNrqhDyb5bGkZjAdEc6GRN1GWCfgaLBG+aq73qkCLDNeB3c2sLw== 980 | dependencies: 981 | ajv "^8.1.0" 982 | cookie "^0.4.0" 983 | process-warning "^1.0.0" 984 | set-cookie-parser "^2.4.1" 985 | 986 | lodash.merge@^4.6.2: 987 | version "4.6.2" 988 | resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" 989 | integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== 990 | 991 | lru-cache@^6.0.0: 992 | version "6.0.0" 993 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 994 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 995 | dependencies: 996 | yallist "^4.0.0" 997 | 998 | memory-pager@^1.0.2: 999 | version "1.5.0" 1000 | resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" 1001 | integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== 1002 | 1003 | merge2@^1.3.0, merge2@^1.4.1: 1004 | version "1.4.1" 1005 | resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" 1006 | integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== 1007 | 1008 | micromatch@^4.0.4: 1009 | version "4.0.5" 1010 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" 1011 | integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== 1012 | dependencies: 1013 | braces "^3.0.2" 1014 | picomatch "^2.3.1" 1015 | 1016 | mime-db@1.52.0: 1017 | version "1.52.0" 1018 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 1019 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 1020 | 1021 | mime-types@^2.1.12: 1022 | version "2.1.35" 1023 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 1024 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 1025 | dependencies: 1026 | mime-db "1.52.0" 1027 | 1028 | minimatch@^3.0.4: 1029 | version "3.1.2" 1030 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 1031 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 1032 | dependencies: 1033 | brace-expansion "^1.1.7" 1034 | 1035 | mongodb-connection-string-url@^2.5.2: 1036 | version "2.5.2" 1037 | resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz#f075c8d529e8d3916386018b8a396aed4f16e5ed" 1038 | integrity sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA== 1039 | dependencies: 1040 | "@types/whatwg-url" "^8.2.1" 1041 | whatwg-url "^11.0.0" 1042 | 1043 | mongodb@4.5.0: 1044 | version "4.5.0" 1045 | resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-4.5.0.tgz#d74c2008567b606dccef220f62a44cd7b934eb92" 1046 | integrity sha512-A2l8MjEpKojnhbCM0MK3+UOGUSGvTNNSv7AkP1fsT7tkambrkkqN/5F2y+PhzsV0Nbv58u04TETpkaSEdI2zKA== 1047 | dependencies: 1048 | bson "^4.6.2" 1049 | denque "^2.0.1" 1050 | mongodb-connection-string-url "^2.5.2" 1051 | socks "^2.6.2" 1052 | optionalDependencies: 1053 | saslprep "^1.0.3" 1054 | 1055 | mongoose@^6.3.2: 1056 | version "6.3.2" 1057 | resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-6.3.2.tgz#7cac2d11119896c8235ce03ae65c322257435142" 1058 | integrity sha512-4SEa8ynhJYkGMMbx6KOZ5kJz6qhKIYM8nAGufGq3xh+gNrKP3QwthNfc0X4DvTKhE0DQLMS1/Oy3cMl0AXm5RQ== 1059 | dependencies: 1060 | bson "^4.6.2" 1061 | kareem "2.3.5" 1062 | mongodb "4.5.0" 1063 | mpath "0.9.0" 1064 | mquery "4.0.2" 1065 | ms "2.1.3" 1066 | sift "16.0.0" 1067 | 1068 | mpath@0.9.0: 1069 | version "0.9.0" 1070 | resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.9.0.tgz#0c122fe107846e31fc58c75b09c35514b3871904" 1071 | integrity sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew== 1072 | 1073 | mquery@4.0.2: 1074 | version "4.0.2" 1075 | resolved "https://registry.yarnpkg.com/mquery/-/mquery-4.0.2.tgz#a13add5ecd7c2e5a67e0f814b3c7acdfb6772804" 1076 | integrity sha512-oAVF0Nil1mT3rxty6Zln4YiD6x6QsUWYz927jZzjMxOK2aqmhEz5JQ7xmrKK7xRFA2dwV+YaOpKU/S+vfNqKxA== 1077 | dependencies: 1078 | debug "4.x" 1079 | 1080 | ms@2.1.2: 1081 | version "2.1.2" 1082 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 1083 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1084 | 1085 | ms@2.1.3: 1086 | version "2.1.3" 1087 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 1088 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 1089 | 1090 | natural-compare@^1.4.0: 1091 | version "1.4.0" 1092 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 1093 | integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= 1094 | 1095 | node-fetch@2, node-fetch@^2.6.5: 1096 | version "2.6.7" 1097 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" 1098 | integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== 1099 | dependencies: 1100 | whatwg-url "^5.0.0" 1101 | 1102 | once@^1.3.0: 1103 | version "1.4.0" 1104 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1105 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 1106 | dependencies: 1107 | wrappy "1" 1108 | 1109 | optionator@^0.9.1: 1110 | version "0.9.1" 1111 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" 1112 | integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== 1113 | dependencies: 1114 | deep-is "^0.1.3" 1115 | fast-levenshtein "^2.0.6" 1116 | levn "^0.4.1" 1117 | prelude-ls "^1.2.1" 1118 | type-check "^0.4.0" 1119 | word-wrap "^1.2.3" 1120 | 1121 | parent-module@^1.0.0: 1122 | version "1.0.1" 1123 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 1124 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 1125 | dependencies: 1126 | callsites "^3.0.0" 1127 | 1128 | path-is-absolute@^1.0.0: 1129 | version "1.0.1" 1130 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1131 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 1132 | 1133 | path-key@^3.1.0: 1134 | version "3.1.1" 1135 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 1136 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 1137 | 1138 | path-type@^4.0.0: 1139 | version "4.0.0" 1140 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" 1141 | integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== 1142 | 1143 | picomatch@^2.3.1: 1144 | version "2.3.1" 1145 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 1146 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 1147 | 1148 | pino-std-serializers@^3.1.0: 1149 | version "3.2.0" 1150 | resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz#b56487c402d882eb96cd67c257868016b61ad671" 1151 | integrity sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg== 1152 | 1153 | pino@^6.13.0: 1154 | version "6.14.0" 1155 | resolved "https://registry.yarnpkg.com/pino/-/pino-6.14.0.tgz#b745ea87a99a6c4c9b374e4f29ca7910d4c69f78" 1156 | integrity sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg== 1157 | dependencies: 1158 | fast-redact "^3.0.0" 1159 | fast-safe-stringify "^2.0.8" 1160 | flatstr "^1.0.12" 1161 | pino-std-serializers "^3.1.0" 1162 | process-warning "^1.0.0" 1163 | quick-format-unescaped "^4.0.3" 1164 | sonic-boom "^1.0.2" 1165 | 1166 | prelude-ls@^1.2.1: 1167 | version "1.2.1" 1168 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" 1169 | integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== 1170 | 1171 | prettier@^2.5.1: 1172 | version "2.6.2" 1173 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" 1174 | integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== 1175 | 1176 | process-warning@^1.0.0: 1177 | version "1.0.0" 1178 | resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" 1179 | integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== 1180 | 1181 | proxy-addr@^2.0.7: 1182 | version "2.0.7" 1183 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" 1184 | integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== 1185 | dependencies: 1186 | forwarded "0.2.0" 1187 | ipaddr.js "1.9.1" 1188 | 1189 | punycode@^2.1.0, punycode@^2.1.1: 1190 | version "2.1.1" 1191 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 1192 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 1193 | 1194 | queue-microtask@^1.1.2, queue-microtask@^1.2.2: 1195 | version "1.2.3" 1196 | resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" 1197 | integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 1198 | 1199 | quick-format-unescaped@^4.0.3: 1200 | version "4.0.4" 1201 | resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" 1202 | integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== 1203 | 1204 | raw-body@^2.4.1: 1205 | version "2.5.1" 1206 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" 1207 | integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== 1208 | dependencies: 1209 | bytes "3.1.2" 1210 | http-errors "2.0.0" 1211 | iconv-lite "0.4.24" 1212 | unpipe "1.0.0" 1213 | 1214 | redis@^4.1.0: 1215 | version "4.1.0" 1216 | resolved "https://registry.yarnpkg.com/redis/-/redis-4.1.0.tgz#6e400e8edf219e39281afe95e66a3d5f7dcf7289" 1217 | integrity sha512-5hvJ8wbzpCCiuN1ges6tx2SAh2XXCY0ayresBmu40/SGusWHFW86TAlIPpbimMX2DFHOX7RN34G2XlPA1Z43zg== 1218 | dependencies: 1219 | "@redis/bloom" "1.0.2" 1220 | "@redis/client" "1.1.0" 1221 | "@redis/graph" "1.0.1" 1222 | "@redis/json" "1.0.3" 1223 | "@redis/search" "1.0.6" 1224 | "@redis/time-series" "1.0.3" 1225 | 1226 | regexpp@^3.2.0: 1227 | version "3.2.0" 1228 | resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" 1229 | integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== 1230 | 1231 | require-from-string@^2.0.2: 1232 | version "2.0.2" 1233 | resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" 1234 | integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== 1235 | 1236 | resolve-from@^4.0.0: 1237 | version "4.0.0" 1238 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 1239 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1240 | 1241 | ret@~0.2.0: 1242 | version "0.2.2" 1243 | resolved "https://registry.yarnpkg.com/ret/-/ret-0.2.2.tgz#b6861782a1f4762dce43402a71eb7a283f44573c" 1244 | integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ== 1245 | 1246 | reusify@^1.0.4: 1247 | version "1.0.4" 1248 | resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" 1249 | integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== 1250 | 1251 | rfdc@^1.1.4, rfdc@^1.2.0: 1252 | version "1.3.0" 1253 | resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" 1254 | integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== 1255 | 1256 | rimraf@^3.0.2: 1257 | version "3.0.2" 1258 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 1259 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1260 | dependencies: 1261 | glob "^7.1.3" 1262 | 1263 | run-parallel@^1.1.9: 1264 | version "1.2.0" 1265 | resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" 1266 | integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== 1267 | dependencies: 1268 | queue-microtask "^1.2.2" 1269 | 1270 | safe-regex2@^2.0.0: 1271 | version "2.0.0" 1272 | resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-2.0.0.tgz#b287524c397c7a2994470367e0185e1916b1f5b9" 1273 | integrity sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ== 1274 | dependencies: 1275 | ret "~0.2.0" 1276 | 1277 | "safer-buffer@>= 2.1.2 < 3": 1278 | version "2.1.2" 1279 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1280 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 1281 | 1282 | saslprep@^1.0.3: 1283 | version "1.0.3" 1284 | resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226" 1285 | integrity sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag== 1286 | dependencies: 1287 | sparse-bitfield "^3.0.3" 1288 | 1289 | secure-json-parse@^2.0.0, secure-json-parse@^2.1.0: 1290 | version "2.4.0" 1291 | resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.4.0.tgz#5aaeaaef85c7a417f76271a4f5b0cc3315ddca85" 1292 | integrity sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg== 1293 | 1294 | semver-store@^0.3.0: 1295 | version "0.3.0" 1296 | resolved "https://registry.yarnpkg.com/semver-store/-/semver-store-0.3.0.tgz#ce602ff07df37080ec9f4fb40b29576547befbe9" 1297 | integrity sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg== 1298 | 1299 | semver@^7.3.2, semver@^7.3.5: 1300 | version "7.3.5" 1301 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" 1302 | integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== 1303 | dependencies: 1304 | lru-cache "^6.0.0" 1305 | 1306 | set-cookie-parser@^2.4.1: 1307 | version "2.4.8" 1308 | resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz#d0da0ed388bc8f24e706a391f9c9e252a13c58b2" 1309 | integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg== 1310 | 1311 | setprototypeof@1.2.0: 1312 | version "1.2.0" 1313 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 1314 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 1315 | 1316 | shebang-command@^2.0.0: 1317 | version "2.0.0" 1318 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 1319 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1320 | dependencies: 1321 | shebang-regex "^3.0.0" 1322 | 1323 | shebang-regex@^3.0.0: 1324 | version "3.0.0" 1325 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 1326 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1327 | 1328 | sift@16.0.0: 1329 | version "16.0.0" 1330 | resolved "https://registry.yarnpkg.com/sift/-/sift-16.0.0.tgz#447991577db61f1a8fab727a8a98a6db57a23eb8" 1331 | integrity sha512-ILTjdP2Mv9V1kIxWMXeMTIRbOBrqKc4JAXmFMnFq3fKeyQ2Qwa3Dw1ubcye3vR+Y6ofA0b9gNDr/y2t6eUeIzQ== 1332 | 1333 | slash@^3.0.0: 1334 | version "3.0.0" 1335 | resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" 1336 | integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== 1337 | 1338 | smart-buffer@^4.2.0: 1339 | version "4.2.0" 1340 | resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" 1341 | integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== 1342 | 1343 | socks@^2.6.2: 1344 | version "2.6.2" 1345 | resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a" 1346 | integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== 1347 | dependencies: 1348 | ip "^1.1.5" 1349 | smart-buffer "^4.2.0" 1350 | 1351 | sonic-boom@^1.0.2: 1352 | version "1.4.1" 1353 | resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-1.4.1.tgz#d35d6a74076624f12e6f917ade7b9d75e918f53e" 1354 | integrity sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg== 1355 | dependencies: 1356 | atomic-sleep "^1.0.0" 1357 | flatstr "^1.0.12" 1358 | 1359 | sparse-bitfield@^3.0.3: 1360 | version "3.0.3" 1361 | resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" 1362 | integrity sha1-/0rm5oZWBWuks+eSqzM004JzyhE= 1363 | dependencies: 1364 | memory-pager "^1.0.2" 1365 | 1366 | statuses@2.0.1: 1367 | version "2.0.1" 1368 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 1369 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 1370 | 1371 | string-similarity@^4.0.1: 1372 | version "4.0.4" 1373 | resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" 1374 | integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== 1375 | 1376 | strip-ansi@^6.0.1: 1377 | version "6.0.1" 1378 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1379 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1380 | dependencies: 1381 | ansi-regex "^5.0.1" 1382 | 1383 | strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: 1384 | version "3.1.1" 1385 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1386 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1387 | 1388 | supports-color@^7.1.0: 1389 | version "7.2.0" 1390 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1391 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1392 | dependencies: 1393 | has-flag "^4.0.0" 1394 | 1395 | text-table@^0.2.0: 1396 | version "0.2.0" 1397 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 1398 | integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= 1399 | 1400 | tiny-lru@^8.0.1: 1401 | version "8.0.2" 1402 | resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-8.0.2.tgz#812fccbe6e622ded552e3ff8a4c3b5ff34a85e4c" 1403 | integrity sha512-ApGvZ6vVvTNdsmt676grvCkUCGwzG9IqXma5Z07xJgiC5L7akUMof5U8G2JTI9Rz/ovtVhJBlY6mNhEvtjzOIg== 1404 | 1405 | to-regex-range@^5.0.1: 1406 | version "5.0.1" 1407 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1408 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1409 | dependencies: 1410 | is-number "^7.0.0" 1411 | 1412 | toidentifier@1.0.1: 1413 | version "1.0.1" 1414 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 1415 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 1416 | 1417 | tr46@^3.0.0: 1418 | version "3.0.0" 1419 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" 1420 | integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== 1421 | dependencies: 1422 | punycode "^2.1.1" 1423 | 1424 | tr46@~0.0.3: 1425 | version "0.0.3" 1426 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 1427 | integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= 1428 | 1429 | tslib@^1.8.1: 1430 | version "1.14.1" 1431 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" 1432 | integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== 1433 | 1434 | tslib@^2.3.1: 1435 | version "2.3.1" 1436 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" 1437 | integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== 1438 | 1439 | tsutils@^3.21.0: 1440 | version "3.21.0" 1441 | resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" 1442 | integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== 1443 | dependencies: 1444 | tslib "^1.8.1" 1445 | 1446 | type-check@^0.4.0, type-check@~0.4.0: 1447 | version "0.4.0" 1448 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" 1449 | integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== 1450 | dependencies: 1451 | prelude-ls "^1.2.1" 1452 | 1453 | type-fest@^0.20.2: 1454 | version "0.20.2" 1455 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" 1456 | integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== 1457 | 1458 | typescript@^4.5.4: 1459 | version "4.6.3" 1460 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" 1461 | integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== 1462 | 1463 | unpipe@1.0.0: 1464 | version "1.0.0" 1465 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 1466 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= 1467 | 1468 | uri-js@^4.2.2: 1469 | version "4.4.1" 1470 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 1471 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1472 | dependencies: 1473 | punycode "^2.1.0" 1474 | 1475 | uuid@^8.3.2: 1476 | version "8.3.2" 1477 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" 1478 | integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== 1479 | 1480 | v8-compile-cache@^2.0.3: 1481 | version "2.3.0" 1482 | resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" 1483 | integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== 1484 | 1485 | webidl-conversions@^3.0.0: 1486 | version "3.0.1" 1487 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 1488 | integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= 1489 | 1490 | webidl-conversions@^7.0.0: 1491 | version "7.0.0" 1492 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" 1493 | integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== 1494 | 1495 | whatwg-url@^11.0.0: 1496 | version "11.0.0" 1497 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" 1498 | integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== 1499 | dependencies: 1500 | tr46 "^3.0.0" 1501 | webidl-conversions "^7.0.0" 1502 | 1503 | whatwg-url@^5.0.0: 1504 | version "5.0.0" 1505 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 1506 | integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= 1507 | dependencies: 1508 | tr46 "~0.0.3" 1509 | webidl-conversions "^3.0.0" 1510 | 1511 | which@^2.0.1: 1512 | version "2.0.2" 1513 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1514 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1515 | dependencies: 1516 | isexe "^2.0.0" 1517 | 1518 | word-wrap@^1.2.3: 1519 | version "1.2.3" 1520 | resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" 1521 | integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== 1522 | 1523 | wrappy@1: 1524 | version "1.0.2" 1525 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1526 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1527 | 1528 | yallist@4.0.0, yallist@^4.0.0: 1529 | version "4.0.0" 1530 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 1531 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 1532 | --------------------------------------------------------------------------------