From cb539b9810dc9405c469f65bd5eef36d0d6c7597 Mon Sep 17 00:00:00 2001 From: JandereDev Date: Thu, 2 Dec 2021 21:12:43 +0100 Subject: [PATCH] custom mod rules --- .gitignore | 1 + src/bot/modules/command_handler.ts | 4 +- .../modules/custom_rules/actions/delete.ts | 8 + .../custom_rules/actions/sendMessage.ts | 22 + src/bot/modules/custom_rules/actions/warn.ts | 34 ++ src/bot/modules/custom_rules/custom_rules.ts | 43 ++ .../custom_rules/message_content_trigger.ts | 93 +++++ src/struct/antispam/AutomodSettings.ts | 2 + src/struct/antispam/CustomRule.ts | 10 + src/struct/antispam/CustomRuleAction.ts | 21 + src/struct/antispam/CustomRuleTrigger.ts | 21 + yarn-error.log | 391 ------------------ 12 files changed, 258 insertions(+), 392 deletions(-) create mode 100644 src/bot/modules/custom_rules/actions/delete.ts create mode 100644 src/bot/modules/custom_rules/actions/sendMessage.ts create mode 100644 src/bot/modules/custom_rules/actions/warn.ts create mode 100644 src/bot/modules/custom_rules/custom_rules.ts create mode 100644 src/bot/modules/custom_rules/message_content_trigger.ts create mode 100644 src/struct/antispam/CustomRule.ts create mode 100644 src/struct/antispam/CustomRuleAction.ts create mode 100644 src/struct/antispam/CustomRuleTrigger.ts delete mode 100644 yarn-error.log diff --git a/.gitignore b/.gitignore index 9c97bbd..a58e32a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules dist .env +yarn-error.log diff --git a/src/bot/modules/command_handler.ts b/src/bot/modules/command_handler.ts index 68c4c20..2813975 100644 --- a/src/bot/modules/command_handler.ts +++ b/src/bot/modules/command_handler.ts @@ -5,6 +5,7 @@ import fs from 'fs'; import path from 'path'; import ServerConfig from "../../struct/ServerConfig"; import { antispam } from "./antispam"; +import checkCustomRules from "./custom_rules/custom_rules"; const DEFAULT_PREFIX = process.env['PREFIX'] ?? process.env['BOT_PREFIX'] @@ -22,8 +23,9 @@ client.on('message', async message => { message.author_id == client.user?._id || !message.channel?.server) return; - // Send message through anti spam check + // Send message through anti spam check and custom rules if (!antispam(message)) return; + checkCustomRules(message); let config: ServerConfig = (await client.db.get('servers').findOne({ 'id': message.channel?.server_id })) ?? {}; let guildPrefix = config.prefix ?? DEFAULT_PREFIX; diff --git a/src/bot/modules/custom_rules/actions/delete.ts b/src/bot/modules/custom_rules/actions/delete.ts new file mode 100644 index 0000000..ea065aa --- /dev/null +++ b/src/bot/modules/custom_rules/actions/delete.ts @@ -0,0 +1,8 @@ +import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import CustomRuleAction from "../../../../struct/antispam/CustomRuleAction"; + +async function execute(message: Message, action: CustomRuleAction) { + setTimeout(() => message.delete().catch(console.warn), (action.duration ?? 0) * 1000); +} + +export default execute; diff --git a/src/bot/modules/custom_rules/actions/sendMessage.ts b/src/bot/modules/custom_rules/actions/sendMessage.ts new file mode 100644 index 0000000..b1172cf --- /dev/null +++ b/src/bot/modules/custom_rules/actions/sendMessage.ts @@ -0,0 +1,22 @@ +import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import { client } from "../../../.."; +import CustomRuleAction from "../../../../struct/antispam/CustomRuleAction"; + +async function execute(message: Message, action: CustomRuleAction) { + let text = action.text || "Error: No text specified for `sendMessage` action"; + if (text.length > 2000) { + text = text.slice(0, 1996) + ' ...'; + } + + if (!message.channel) await client.channels.fetch(message.channel_id); + let msg = await message.channel!.sendMessage(text); + + if (action.duration) { + setTimeout(() => { + msg.delete() + .catch(console.warn); + }, action.duration * 1000); + } +} + +export default execute; diff --git a/src/bot/modules/custom_rules/actions/warn.ts b/src/bot/modules/custom_rules/actions/warn.ts new file mode 100644 index 0000000..56fa028 --- /dev/null +++ b/src/bot/modules/custom_rules/actions/warn.ts @@ -0,0 +1,34 @@ +import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import CustomRuleAction from "../../../../struct/antispam/CustomRuleAction"; +import { storeInfraction } from '../../../util'; +import Infraction from "../../../../struct/antispam/Infraction"; +import { ulid } from "ulid"; +import InfractionType from "../../../../struct/antispam/InfractionType"; + +async function execute(message: Message, action: CustomRuleAction) { + let warnMsg = action.text + ? `${action.text}\n(Triggered on ${message.channel_id} / ${message._id})` + : `Moderation rule triggered on ${message.channel_id} / ${message._id}`; + + let infraction: Infraction = { + _id: ulid(), + date: Date.now(), + createdBy: null, + reason: warnMsg, + server: message.channel?.server_id!, + type: InfractionType.Automatic, + user: message.author_id + } + + let { userWarnCount } = await storeInfraction(infraction); + + if (action.silent !== true) { + message.channel?.sendMessage( + `### User has been warned\n` + + `This is warn number \`${userWarnCount}\` for @${message.author?.username}.\n` + + `**Reason:** ${warnMsg}` + ).catch(console.warn); + } +} + +export default execute; diff --git a/src/bot/modules/custom_rules/custom_rules.ts b/src/bot/modules/custom_rules/custom_rules.ts new file mode 100644 index 0000000..91a090f --- /dev/null +++ b/src/bot/modules/custom_rules/custom_rules.ts @@ -0,0 +1,43 @@ +import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import { client } from "../../.."; +import ServerConfig from "../../../struct/ServerConfig"; +import logger from "../../logger"; +import messageContentTrigger from "./message_content_trigger"; + +import custom_sendMessage from "./actions/sendMessage"; +import custom_delete from "./actions/delete"; +import custom_warn from "./actions/warn"; + +async function checkCustomRules(message: Message, isEdit: boolean = false) { + let serverConfig: ServerConfig = await client.db.get('servers').findOne({ id: message.channel?.server_id }) ?? {}; + let rules = serverConfig?.automodSettings?.custom; + if (!rules) return; + + for (let rule of rules) { + let onEdit = rule.trigger.on.includes('message/update'); + let onNew = rule.trigger.on.includes('message/create'); + + // tired + if (!((onEdit && isEdit) || (onNew && !isEdit) || (onNew && onEdit))) break; + + if (await messageContentTrigger(message, rule.trigger)) { + for (const action of rule.action) { + switch(action.action) { + case 'sendMessage': + await custom_sendMessage(message, action); + break; + case 'delete': + await custom_delete(message, action); + break; + case 'warn': + await custom_warn(message, action); + break; + default: + logger.warn(`Unknown action ${action.action} in custom rule ${rule._id} in server ${message.channel?.server_id}`); + } + } + } + } +} + +export default checkCustomRules; diff --git a/src/bot/modules/custom_rules/message_content_trigger.ts b/src/bot/modules/custom_rules/message_content_trigger.ts new file mode 100644 index 0000000..9c8ab7b --- /dev/null +++ b/src/bot/modules/custom_rules/message_content_trigger.ts @@ -0,0 +1,93 @@ +import { Message } from "@janderedev/revolt.js/dist/maps/Messages"; +import { client } from "../../.."; +import CustomRuleTrigger from "../../../struct/antispam/CustomRuleTrigger"; +import VM from 'vm'; + +let ruleTimeouts: Map = new Map(); + +async function messageContentTrigger(message: Message, trigger: CustomRuleTrigger): Promise { + + /* Match message content */ + + let matched = false; + if (trigger.matcher) { + if (trigger.matcher instanceof RegExp) { + /** + * Since users will eventually be able to provide regexes, we need to protect + * againt ReDoS (Regular Expression Denial of Service). + * Therefore all RegExes will have an execution limit of 2ms. + * An additional mitigation step would be to disable rules that are frequently + * found to hit that limit, but that is out of scope for now. + * + * (If someone finds a flaw in my logic, please report it) + */ + + // We use node's built-in `vm` module to limit execution time. + // No idea if this works the way I want it to + try { + let ctx = VM.createContext({ + regex: trigger.matcher!, + matchedStrings: [], + content: message.content as string, + }); + + let script = new VM.Script('matchedStrings = content.match(regex);', { timeout: 2 }); + script.runInContext(ctx); + + if (ctx.matchedStrings?.length) matched = true; + } catch(e) { + console.error('Exception thrown while parsing RegEx: ' + e); + } + + } else { + if ((message.content as string).includes(trigger.matcher)) matched = true; + } + } + if (!matched) return false; + + + /* Timeouts */ + + let timeoutKeys = { + global: trigger._id, + channel: trigger._id + '/channel/' + message.channel_id, + user: trigger._id + '/user/' + message.author_id, + } + let timeoutPass = true; + + // Global + if (trigger.timeout?.global && ruleTimeouts.has(timeoutKeys.global)) { + if (ruleTimeouts.get(timeoutKeys.global)! + (trigger.timeout.global * 1000) < Date.now()) { + ruleTimeouts.set(timeoutKeys.global, Date.now()); + } else timeoutPass = false; + } + + // Per Channel + if (trigger.timeout?.perChannel && ruleTimeouts.has(timeoutKeys.channel)) { + if (ruleTimeouts.get(timeoutKeys.channel)! + (trigger.timeout.perChannel * 1000) < Date.now()) { + ruleTimeouts.set(timeoutKeys.channel, Date.now()); + } else timeoutPass = false; + } + + // Per User + if (trigger.timeout?.perUser && ruleTimeouts.has(timeoutKeys.user)) { + if (ruleTimeouts.get(timeoutKeys.user)! + (trigger.timeout.perUser * 1000) < Date.now()) { + ruleTimeouts.set(timeoutKeys.user, Date.now()); + } else timeoutPass = false; + } + + if (!timeoutPass) return false; + + + /* User/bot filter comes last because we want to avoid fetching users if possible */ + + if (trigger.userFilter && trigger.userFilter != 'any') { + let user = message.author || await client.users.fetch(message.author_id); + if (trigger.userFilter == 'bot' && !user.bot) return false; + if (trigger.userFilter == 'user' && user.bot) return false; + } + + return true; +} + +export default messageContentTrigger; diff --git a/src/struct/antispam/AutomodSettings.ts b/src/struct/antispam/AutomodSettings.ts index ee135b5..44edcba 100644 --- a/src/struct/antispam/AutomodSettings.ts +++ b/src/struct/antispam/AutomodSettings.ts @@ -1,7 +1,9 @@ import AntispamRule from "./AntispamRule"; +import CustomRule from "./CustomRule"; class AutomodSettings { spam: AntispamRule[]; + custom: CustomRule[]; } export default AutomodSettings; diff --git a/src/struct/antispam/CustomRule.ts b/src/struct/antispam/CustomRule.ts new file mode 100644 index 0000000..36116e3 --- /dev/null +++ b/src/struct/antispam/CustomRule.ts @@ -0,0 +1,10 @@ +import CustomRuleAction from "./CustomRuleAction"; +import CustomRuleTrigger from "./CustomRuleTrigger"; + +class CustomRule { + _id: string; + trigger: CustomRuleTrigger; + action: CustomRuleAction[]; +} + +export default CustomRule; diff --git a/src/struct/antispam/CustomRuleAction.ts b/src/struct/antispam/CustomRuleAction.ts new file mode 100644 index 0000000..d0474a6 --- /dev/null +++ b/src/struct/antispam/CustomRuleAction.ts @@ -0,0 +1,21 @@ +class CustomRuleAction { + _id: string; + + // The action to perform on the user/message + // todo: kick and ban are not implemented, either remove them or implement them + action: 'delete' | 'warn' | 'kick' | 'ban' | 'sendMessage'; + + // If the action accepts a text parameter, this is it + text?: string; + + // If the action accepts a duration parameter, this is it + // sendMessage will delete the message after the duration + // delete/kick/ban will wait for the duration to pass + duration?: number; + + // Whether to send the action in chat. Off by default. + // Not supported by sendMessage + silent?: boolean; +} + +export default CustomRuleAction; diff --git a/src/struct/antispam/CustomRuleTrigger.ts b/src/struct/antispam/CustomRuleTrigger.ts new file mode 100644 index 0000000..45a935e --- /dev/null +++ b/src/struct/antispam/CustomRuleTrigger.ts @@ -0,0 +1,21 @@ +class CustomRuleTrigger { + _id: string; + + // Which events this rule should apply to + // todo: message/update is not implemented + on: ('message/create' | 'message/update')[]; + + // Regex or string to match the content of the message against. If omitted, rule applies to every message + matcher?: RegExp|string; + + userFilter?: 'user' | 'bot' | 'any'; + + // The minimum delay between rule matches. If omitted, rule matches every message + timeout?: { + perUser?: number; + perChannel?: number; + global?: number; // "Global" is per-server + }; +} + +export default CustomRuleTrigger; diff --git a/yarn-error.log b/yarn-error.log deleted file mode 100644 index e9297cd..0000000 --- a/yarn-error.log +++ /dev/null @@ -1,391 +0,0 @@ -Arguments: - /usr/bin/node /usr/bin/yarn add day.js - -PATH: - /home/jan/bin:/home/jan/.cargo/bin/:/usr/local/bin:/home/jan/bin:/home/jan/.cargo/bin/:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/var/lib/flatpak/exports/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/usr/lib/jvm/default/bin - -Yarn version: - 1.22.15 - -Node version: - 16.11.0 - -Platform: - linux x64 - -Trace: - Error: https://registry.yarnpkg.com/day.js: Not found - at Request.params.callback [as _callback] (/usr/lib/node_modules/yarn/lib/cli.js:67031:18) - at Request.self.callback (/usr/lib/node_modules/yarn/lib/cli.js:140885:22) - at Request.emit (node:events:390:28) - at Request. (/usr/lib/node_modules/yarn/lib/cli.js:141857:10) - at Request.emit (node:events:390:28) - at IncomingMessage. (/usr/lib/node_modules/yarn/lib/cli.js:141779:12) - at Object.onceWrapper (node:events:509:28) - at IncomingMessage.emit (node:events:402:35) - at endReadableNT (node:internal/streams/readable:1343:12) - at processTicksAndRejections (node:internal/process/task_queues:83:21) - -npm manifest: - { - "name": "revolt-automod", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "build": "rm -rf dist && tsc", - "start": "node dist/index", - "dev": "yarn build && yarn start" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "@types/monk": "^6.0.0", - "axios": "^0.22.0", - "dotenv": "^10.0.0", - "log75": "2.0.1", - "monk": "^7.3.4", - "revolt.js": "^5.1.0-alpha.6", - "ulid": "^2.3.0" - }, - "devDependencies": { - "typescript": "^4.4.3" - } - } - -yarn manifest: - No manifest - -Lockfile: - # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. - # yarn lockfile v1 - - - "@types/bson@*": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@types/bson/-/bson-4.2.0.tgz#a2f71e933ff54b2c3bf267b67fa221e295a33337" - integrity sha512-ELCPqAdroMdcuxqwMgUpifQyRoTpyYCNr1V9xKyF40VsBobsj+BbWNRvwGchMgBPGqkw655ypkjj2MEF5ywVwg== - dependencies: - bson "*" - - "@types/mongodb@^3.5.25": - version "3.6.20" - resolved "https://registry.yarnpkg.com/@types/mongodb/-/mongodb-3.6.20.tgz#b7c5c580644f6364002b649af1c06c3c0454e1d2" - integrity sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ== - dependencies: - "@types/bson" "*" - "@types/node" "*" - - "@types/monk@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@types/monk/-/monk-6.0.0.tgz#236750988e24d92c674529a81b9a296f8bbc3763" - integrity sha512-9qy4Gva0uVgaQsDqlcWD+XOXUmgInPAoxyyoN8uFUTjNFvswyCH1hwpnYuh2MVr60ekZgYiquWEjBYvfYfE1Jw== - dependencies: - monk "*" - - "@types/node@*": - version "16.10.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.3.tgz#7a8f2838603ea314d1d22bb3171d899e15c57bd5" - integrity sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ== - - ansi-colors@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - - axios@^0.21.4: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - - axios@^0.22.0: - version "0.22.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.22.0.tgz#bf702c41fb50fbca4539589d839a077117b79b25" - integrity sha512-Z0U3uhqQeg1oNcihswf4ZD57O3NrR1+ZXhxaROaWpDmsDTx7T2HNBV2ulBtie2hwJptu8UvgnJoK+BIqdzh/1w== - dependencies: - follow-redirects "^1.14.4" - - base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - - bl@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.1.tgz#8c11a7b730655c5d56898cdc871224f40fd901d5" - integrity sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g== - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - - bson@*: - version "4.5.3" - resolved "https://registry.yarnpkg.com/bson/-/bson-4.5.3.tgz#de3783b357a407d935510beb1fbb285fef43bb06" - integrity sha512-qVX7LX79Mtj7B3NPLzCfBiCP6RAsjiV8N63DjlaVVpZW+PFoDTxQ4SeDbSpcqgE6mXksM5CAwZnXxxxn/XwC0g== - dependencies: - buffer "^5.6.0" - - bson@^1.1.4: - version "1.1.6" - resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.6.tgz#fb819be9a60cd677e0853aee4ca712a785d6618a" - integrity sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg== - - buffer@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - - core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - - debug@*: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - - denque@^1.4.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" - integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== - - dotenv@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" - integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== - - eventemitter3@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - - exponential-backoff@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.0.tgz#9409c7e579131f8bd4b32d7d8094a911040f2e68" - integrity sha512-oBuz5SYz5zzyuHINoe9ooePwSu0xApKWgeNzok4hZ5YKXFh9zrQBEM15CXqoZkJJPuI2ArvqjPQd8UKJA753XA== - - follow-redirects@^1.14.0, follow-redirects@^1.14.4: - version "1.14.4" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" - integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g== - - ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - - inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - - isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - - isomorphic-ws@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" - integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== - - lodash.defaultsdeep@^4.6.1: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz#512e9bd721d272d94e3d3a63653fa17516741ca6" - integrity sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA== - - lodash.isequal@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - - log75@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/log75/-/log75-2.0.1.tgz#dd0e2bd0935df0c4fd3984c2731e7eaa3034c635" - integrity sha512-yoG7E0Hh2izZaZAhqL2WbwJ0PIkNcuEV09vFsX5owebLl4/xSmTaEd3gUle/j2ivUbuv2toUeEcJKUSG/MAO+A== - dependencies: - ansi-colors "^4.1.1" - - memory-pager@^1.0.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" - integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== - - mobx@^6.3.2: - version "6.3.3" - resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.3.3.tgz#a3006c56243b1c7ea4ee671a66f963b9f43cf1af" - integrity sha512-JoNU50rO6d1wHwKPJqKq4rmUMbYnI9CsJmBo+Cu4exBYenFvIN77LWrZENpzW6reZPADtXMmB1DicbDSfy8Clw== - - mongodb@^3.2.3: - version "3.7.2" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.7.2.tgz#d0d43b08ff1e5c13f4112175e321fa292cf35a3d" - integrity sha512-/Qi0LmOjzIoV66Y2JQkqmIIfFOy7ZKsXnQNlUXPFXChOw3FCdNqVD5zvci9ybm6pkMe/Nw+Rz9I0Zsk2a+05iQ== - dependencies: - bl "^2.2.1" - bson "^1.1.4" - denque "^1.4.1" - optional-require "^1.1.8" - safe-buffer "^5.1.2" - optionalDependencies: - saslprep "^1.0.0" - - monk-middleware-cast-ids@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/monk-middleware-cast-ids/-/monk-middleware-cast-ids-0.2.1.tgz#40c40e5a6cb33ccedc289220943275ee8861c529" - integrity sha1-QMQOWmyzPM7cKJIglDJ17ohhxSk= - - monk-middleware-fields@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/monk-middleware-fields/-/monk-middleware-fields-0.2.0.tgz#ff637af35f5948879ccb2be15a91360911bea6c1" - integrity sha1-/2N6819ZSIecyyvhWpE2CRG+psE= - - monk-middleware-handle-callback@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/monk-middleware-handle-callback/-/monk-middleware-handle-callback-0.2.2.tgz#47de6cc1248726c72a2be0c81bc4e68310c32146" - integrity sha512-5hBynb7asZ2uw9XVze7C3XH0zXT51yFDvYydk/5HnWWzh2NLglDSiKDcX0yLKPHzFgiq+5Z4Laq5fFVnFsmm8w== - - monk-middleware-options@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/monk-middleware-options/-/monk-middleware-options-0.2.1.tgz#58dae1c518d46636ebdff506fadfc773bb442886" - integrity sha1-WNrhxRjUZjbr3/UG+t/Hc7tEKIY= - - monk-middleware-query@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/monk-middleware-query/-/monk-middleware-query-0.2.0.tgz#a926c677d4a5620c62151b0a56d0c0c151675874" - integrity sha1-qSbGd9SlYgxiFRsKVtDAwVFnWHQ= - - monk-middleware-wait-for-connection@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/monk-middleware-wait-for-connection/-/monk-middleware-wait-for-connection-0.2.0.tgz#312958d30e588b57d09754dd7c97b4843316835a" - integrity sha1-MSlY0w5Yi1fQl1TdfJe0hDMWg1o= - - monk@*, monk@^7.3.4: - version "7.3.4" - resolved "https://registry.yarnpkg.com/monk/-/monk-7.3.4.tgz#50ccd7daebb4c16ace58d45b2c28c29112f8a85e" - integrity sha512-PkPNiElwroVyKQj01usyziOvwiKYBUVSq7YU1FB4KFr0J3v0GeXW0TebYsLR4u33WB8JGqPiAcuzDspfdujqQg== - dependencies: - "@types/mongodb" "^3.5.25" - debug "*" - mongodb "^3.2.3" - monk-middleware-cast-ids "^0.2.1" - monk-middleware-fields "^0.2.0" - monk-middleware-handle-callback "^0.2.0" - monk-middleware-options "^0.2.1" - monk-middleware-query "^0.2.0" - monk-middleware-wait-for-connection "^0.2.0" - object-assign "^4.1.1" - - ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - - object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - - optional-require@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/optional-require/-/optional-require-1.1.8.tgz#16364d76261b75d964c482b2406cb824d8ec44b7" - integrity sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA== - dependencies: - require-at "^1.0.6" - - process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - - readable-stream@^2.3.5: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - - require-at@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/require-at/-/require-at-1.0.6.tgz#9eb7e3c5e00727f5a4744070a7f560d4de4f6e6a" - integrity sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g== - - revolt.js@^5.1.0-alpha.6: - version "5.1.0-alpha.6" - resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-5.1.0-alpha.6.tgz#bdd1c9f3bdd7e0f45e309a3e1fa5239138e1cb1a" - integrity sha512-XqdP24tGc+En9M8ccWkk74z/v2DBtH7OboTbFQBQTjWIT4fLMP/ox+GLdDVWSF7Zg6M/xPrMbg4oL/nP+xqZHQ== - dependencies: - axios "^0.21.4" - eventemitter3 "^4.0.7" - exponential-backoff "^3.1.0" - isomorphic-ws "^4.0.1" - lodash.defaultsdeep "^4.6.1" - lodash.isequal "^4.5.0" - mobx "^6.3.2" - ulid "^2.3.0" - ws "^8.2.2" - - safe-buffer@^5.1.1, safe-buffer@^5.1.2: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - - safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - - saslprep@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226" - integrity sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag== - dependencies: - sparse-bitfield "^3.0.3" - - sparse-bitfield@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" - integrity sha1-/0rm5oZWBWuks+eSqzM004JzyhE= - dependencies: - memory-pager "^1.0.2" - - string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - - typescript@^4.4.3: - version "4.4.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324" - integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA== - - ulid@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/ulid/-/ulid-2.3.0.tgz#93063522771a9774121a84d126ecd3eb9804071f" - integrity sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw== - - util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - - ws@^8.2.2: - version "8.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" - integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==