minor changes

(added redis and made the bot actually functional again)
This commit is contained in:
JandereDev 2022-07-15 17:38:13 +02:00
parent f333f2c78d
commit fc740b1795
No known key found for this signature in database
GPG key ID: 5D5E18ACB990F57A
47 changed files with 278 additions and 258 deletions

View file

@ -21,6 +21,7 @@
"express": "^4.17.2",
"log75": "^2.2.0",
"monk": "^7.3.4",
"redis": "^4.2.0",
"ulid": "^2.3.0",
"ws": "^8.4.2"
},

View file

@ -1,4 +1,5 @@
import Monk, { IMonkManager } from 'monk';
import Redis from 'redis';
import { logger } from '.';
export default (): IMonkManager => {
@ -7,6 +8,10 @@ export default (): IMonkManager => {
return db;
};
const redis = Redis.createClient({ url: process.env.REDIS_URL });
export { redis }
// Checks if all required env vars were supplied, and returns the mongo db URL
function getDBUrl() {
let env = process.env;

View file

@ -1,7 +1,7 @@
import { config } from 'dotenv';
import Express from "express";
import Log75, { LogLevel } from 'log75';
import buildDBClient from './db';
import buildDBClient, { redis } from './db';
config();
@ -19,6 +19,8 @@ app.use(Express.json());
export { logger, app, db, PORT, SESSION_LIFETIME }
(async () => {
await redis.connect();
const promises = [
import('./middlewares/log'),
import('./middlewares/updateTokenExpiry'),

View file

@ -1,17 +1,7 @@
import { Request, Response } from "express";
import { FindOneResult } from "monk";
import { app, db, logger } from "..";
const ratelimits = db.get('ratelimits');
type RateLimitObject = {
ip: string,
requests: { route: string, time: number }[],
lastActivity: number,
}
// Might use redis here later, idk
// I am also aware that there's better ways to do this
import { ulid } from "ulid";
import { app, logger } from "..";
import { redis } from "../db";
class RateLimiter {
route: string;
@ -27,25 +17,14 @@ class RateLimiter {
async execute(req: Request, res: Response, next: () => void) {
try {
const ip = req.ip;
const now = Date.now();
const reqId = ulid();
const entry: FindOneResult<RateLimitObject> = await ratelimits.findOne({ ip });
if (!entry) {
logger.debug('Ratelimiter: Request from new IP address, creating new document');
next();
await ratelimits.insert({
ip,
lastActivity: now,
requests: [{ route: this.route, time: now }],
});
return;
}
// ratelimit:ip_address_base64:route_base64
const redisKey = `ratelimit:${Buffer.from(ip).toString('base64')}:${Buffer.from(this.route).toString('base64')}`;
const reqs = entry.requests.filter(
r => r.route == this.route && r.time > now - (this.timeframe * 1000)
);
const reqs = await redis.SCARD(redisKey);
if (reqs.length >= this.limit) {
if (reqs >= this.limit) {
logger.debug(`Ratelimiter: IP address exceeded ratelimit for ${this.route} [${this.limit}/${this.timeframe}]`);
res
.status(429)
@ -54,56 +33,15 @@ class RateLimiter {
limit: this.limit,
timeframe: this.timeframe,
});
} else next();
// Can't put a $push and $pull into the same query
await Promise.all([
ratelimits.update({ ip }, {
$push: {
requests: { route: this.route, time: now }
},
$set: {
lastActivity: now
} else {
next();
await redis.SADD(redisKey, reqId);
await redis.sendCommand([ 'EXPIREMEMBER', redisKey, reqId, this.timeframe.toString() ]);
}
}),
ratelimits.update({ ip }, {
$pull: {
requests: {
route: this.route,
time: {
$lt: now - (this.timeframe * 1000)
}
}
}
}),
]);
} catch(e) { console.error(e) }
}
}
app.use('*', (...args) => (new RateLimiter('*', { limit: 20, timeframe: 1 })).execute(...args));
// Delete all documents where the last
// activity was more than 24 hours ago.
// This ensures that we don't store
// personally identifying data for longer
// than required.
const cleanDocuments = async () => {
try {
logger.info('Ratelimiter: Deleting old documents');
const { deletedCount } = await ratelimits.remove({
lastActivity: { $lt: Date.now() - 1000 * 60 * 60 * 24 }
}, { multi: true });
logger.done(`Ratelimiter: Deleted ${deletedCount ?? '??'} documents.`);
} catch(e) {
console.error(e);
}
}
setTimeout(cleanDocuments, 1000 * 10);
setInterval(cleanDocuments, 10000 * 60 * 60);
export { RateLimiter }

View file

@ -5,6 +5,62 @@ __metadata:
version: 6
cacheKey: 8
"@redis/bloom@npm:1.0.2":
version: 1.0.2
resolution: "@redis/bloom@npm:1.0.2"
peerDependencies:
"@redis/client": ^1.0.0
checksum: 4872e7e5e4ff03d63349ca88d3164d487f62805651ada91924de2592995993401c98a01cb93bff8d71e9a2e54985b2485b6cb0e084a7e8b1283e2ebb8bc4b833
languageName: node
linkType: hard
"@redis/client@npm:1.2.0":
version: 1.2.0
resolution: "@redis/client@npm:1.2.0"
dependencies:
cluster-key-slot: 1.1.0
generic-pool: 3.8.2
yallist: 4.0.0
checksum: 098a550a6728d9d3babb432a1c32f1678cbda5ad7fa3d59316fc334be42ef05d778fc4cf2e3d873a34817447870a5fc0486e62793698a279404b3b086ba7422e
languageName: node
linkType: hard
"@redis/graph@npm:1.0.1":
version: 1.0.1
resolution: "@redis/graph@npm:1.0.1"
peerDependencies:
"@redis/client": ^1.0.0
checksum: 72e485efa416bdff10420f6e13c9cb4e1e5c70752e5172717adf62fc1d4d9ba12e708229fd87876f3a93270ff74c4bcd4d916987438dc36a94f7f12c9785fa44
languageName: node
linkType: hard
"@redis/json@npm:1.0.3":
version: 1.0.3
resolution: "@redis/json@npm:1.0.3"
peerDependencies:
"@redis/client": ^1.0.0
checksum: 26a7003c2fbacfa5998671e3a301cb2285432bf90f237adedcf76c0be0d379528e6710d469a8ea93c04bbd22951f9c2f41d460dbd79e85856f199248c4a250d5
languageName: node
linkType: hard
"@redis/search@npm:1.0.6":
version: 1.0.6
resolution: "@redis/search@npm:1.0.6"
peerDependencies:
"@redis/client": ^1.0.0
checksum: 5c776143520b11ae2e49a05e7fe3df514a01460f2be90759b15e4f097bf4a985784c48c2184ac2c275ced3ec5a0c77b208a4d46a50161d1ad6025e3ab2990aa7
languageName: node
linkType: hard
"@redis/time-series@npm:1.0.3":
version: 1.0.3
resolution: "@redis/time-series@npm:1.0.3"
peerDependencies:
"@redis/client": ^1.0.0
checksum: 4d11518185dd15f31c5b4a433902e53a3ebc24614a0221080ab12abf4f6fc60b3db00a71a83de7b4b10f11077de611dc1c273274573646d63481d40ca246f82d
languageName: node
linkType: hard
"@types/body-parser@npm:*":
version: 1.19.2
resolution: "@types/body-parser@npm:1.19.2"
@ -151,6 +207,7 @@ __metadata:
express: ^4.17.2
log75: ^2.2.0
monk: ^7.3.4
redis: ^4.2.0
typescript: ^4.5.5
ulid: ^2.3.0
ws: ^8.4.2
@ -238,6 +295,13 @@ __metadata:
languageName: node
linkType: hard
"cluster-key-slot@npm:1.1.0":
version: 1.1.0
resolution: "cluster-key-slot@npm:1.1.0"
checksum: fc953c75209b1ef9088081bab4e40a0b2586491c974ab93460569c014515ca5a2e31c043f185285e177007162fc353d07836d98f570c171dbe055775430e495b
languageName: node
linkType: hard
"content-disposition@npm:0.5.4":
version: 0.5.4
resolution: "content-disposition@npm:0.5.4"
@ -419,6 +483,13 @@ __metadata:
languageName: node
linkType: hard
"generic-pool@npm:3.8.2":
version: 3.8.2
resolution: "generic-pool@npm:3.8.2"
checksum: f549077d90265e5e4d32a2410205b357ec61cf73d17861f1013637984390e09fe7bf537129a2c6ed30ae57662a57c8d54194f80046408d3349836330f422dbde
languageName: node
linkType: hard
"http-errors@npm:1.8.1":
version: 1.8.1
resolution: "http-errors@npm:1.8.1"
@ -746,6 +817,20 @@ __metadata:
languageName: node
linkType: hard
"redis@npm:^4.2.0":
version: 4.2.0
resolution: "redis@npm:4.2.0"
dependencies:
"@redis/bloom": 1.0.2
"@redis/client": 1.2.0
"@redis/graph": 1.0.1
"@redis/json": 1.0.3
"@redis/search": 1.0.6
"@redis/time-series": 1.0.3
checksum: 6c35b56c6b685e82973c5698c5736c07ccbc59f3bc18d8de61e45ead2df4b8fc82062e5618452f4d3f8c23f02ff8c0b847c8d6a681f909c403a0fb96adcc2b98
languageName: node
linkType: hard
"require-at@npm:^1.0.6":
version: 1.0.6
resolution: "require-at@npm:1.0.6"
@ -936,3 +1021,10 @@ __metadata:
checksum: 4369caaac8d1092a73871f5cf1d87fcbb995dc4183a1bc48e4f451bc2d02d0a8bf7c17edf1da18e2be3c773b09262275356b256d1c55bc7ca096154293ba2a8c
languageName: node
linkType: hard
"yallist@npm:4.0.0":
version: 4.0.0
resolution: "yallist@npm:4.0.0"
checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5
languageName: node
linkType: hard

View file

@ -3,7 +3,7 @@ import { client, dbs } from "../../..";
import CommandCategory from "../../../struct/commands/CommandCategory";
import SimpleCommand from "../../../struct/commands/SimpleCommand";
import MessageCommandContext from "../../../struct/MessageCommandContext";
import PendingLogin from "automod/types/PendingLogin";
import PendingLogin from "automod/dist/types/PendingLogin";
import logger from "../../logger";
import { DEFAULT_PREFIX } from "../../modules/command_handler";

View file

@ -3,7 +3,7 @@ import { client, dbs } from "../../..";
import CommandCategory from "../../../struct/commands/CommandCategory";
import SimpleCommand from "../../../struct/commands/SimpleCommand";
import MessageCommandContext from "../../../struct/MessageCommandContext";
import ServerConfig from "automod/types/ServerConfig";
import ServerConfig from "automod/dist/types/ServerConfig";
import { isBotManager, NO_MANAGER_MSG, parseUser } from "../../util";
const SYNTAX = '/whitelist add @user; /whitelist remove @user; /whitelist list';

View file

@ -1,7 +1,7 @@
import { ulid } from "ulid";
import { client } from "../../../index";
import Infraction from "automod/types/antispam/Infraction";
import InfractionType from "automod/types/antispam/InfractionType";
import Infraction from "automod/dist/types/antispam/Infraction";
import InfractionType from "automod/dist/types/antispam/InfractionType";
import SimpleCommand from "../../../struct/commands/SimpleCommand";
import { fetchUsername, logModAction } from "../../modules/mod_logs";
import { storeTempBan } from "../../modules/tempbans";

View file

@ -2,8 +2,8 @@ import { User } from "@janderedev/revolt.js";
import { SendableEmbed } from "revolt-api";
import { ulid } from "ulid";
import { client } from "../../../";
import Infraction from "automod/types/antispam/Infraction";
import InfractionType from "automod/types/antispam/InfractionType";
import Infraction from "automod/dist/types/antispam/Infraction";
import InfractionType from "automod/dist/types/antispam/InfractionType";
import CommandCategory from "../../../struct/commands/CommandCategory";
import SimpleCommand from "../../../struct/commands/SimpleCommand";
import logger from "../../logger";

View file

@ -1,8 +1,8 @@
import SimpleCommand from "../../../struct/commands/SimpleCommand";
import { dedupeArray, embed, EmbedColor, generateInfractionDMEmbed, getDmChannel, isModerator, NO_MANAGER_MSG, parseUserOrId, sanitizeMessageContent, storeInfraction } from "../../util";
import Infraction from "automod/types/antispam/Infraction";
import Infraction from "automod/dist/types/antispam/Infraction";
import { ulid } from "ulid";
import InfractionType from "automod/types/antispam/InfractionType";
import InfractionType from "automod/dist/types/antispam/InfractionType";
import { fetchUsername, logModAction } from "../../modules/mod_logs";
import CommandCategory from "../../../struct/commands/CommandCategory";
import { SendableEmbed } from "revolt-api";

View file

@ -1,7 +1,7 @@
import SimpleCommand from "../../../struct/commands/SimpleCommand";
import { dbs } from "../../..";
import Infraction from "automod/types/antispam/Infraction";
import InfractionType from "automod/types/antispam/InfractionType";
import Infraction from "automod/dist/types/antispam/Infraction";
import InfractionType from "automod/dist/types/antispam/InfractionType";
import { isModerator, NO_MANAGER_MSG, parseUserOrId, uploadFile } from "../../util";
import Day from 'dayjs';
import RelativeTime from 'dayjs/plugin/relativeTime';

View file

@ -1,10 +1,10 @@
import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
import { ulid } from "ulid";
import { dbs } from "../..";
import AntispamRule from "automod/types/antispam/AntispamRule";
import Infraction from "automod/types/antispam/Infraction";
import InfractionType from "automod/types/antispam/InfractionType";
import ModerationAction from "automod/types/antispam/ModerationAction";
import AntispamRule from "automod/dist/types/antispam/AntispamRule";
import Infraction from "automod/dist/types/antispam/Infraction";
import InfractionType from "automod/dist/types/antispam/InfractionType";
import ModerationAction from "automod/dist/types/antispam/ModerationAction";
import logger from "../logger";
import { isModerator, storeInfraction } from "../util";

View file

@ -1,7 +1,7 @@
import { Member } from "@janderedev/revolt.js/dist/maps/Members";
import { User } from "@janderedev/revolt.js/dist/maps/Users";
import { client, dbs } from "../../..";
import ServerConfig from "automod/types/ServerConfig";
import ServerConfig from "automod/dist/types/ServerConfig";
import { getPermissionLevel } from "../../util";
import { wsEvents, WSResponse } from "../api_communication";

View file

@ -8,7 +8,7 @@ import crypto from 'crypto';
import { client as bot, dbs } from '../..';
import { EventEmitter } from "events";
import { parseUser } from "../util";
import PendingLogin from "automod/types/PendingLogin";
import PendingLogin from "automod/dist/types/PendingLogin";
import { ulid } from "ulid";
const wsEvents = new EventEmitter();

View file

@ -1,5 +1,5 @@
import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
import CustomRuleAction from "automod/types/antispam/CustomRuleAction";
import CustomRuleAction from "automod/dist/types/antispam/CustomRuleAction";
async function execute(message: Message, action: CustomRuleAction) {
setTimeout(() => message.delete().catch(console.warn), (action.duration ?? 0) * 1000);

View file

@ -1,6 +1,6 @@
import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
import { client } from "../../../..";
import CustomRuleAction from "automod/types/antispam/CustomRuleAction";
import CustomRuleAction from "automod/dist/types/antispam/CustomRuleAction";
async function execute(message: Message, action: CustomRuleAction) {
let text = action.text || "Error: No text specified for `sendMessage` action";

View file

@ -1,9 +1,9 @@
import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
import CustomRuleAction from "automod/types/antispam/CustomRuleAction";
import CustomRuleAction from "automod/dist/types/antispam/CustomRuleAction";
import { storeInfraction } from '../../../util';
import Infraction from "automod/types/antispam/Infraction";
import Infraction from "automod/dist/types/antispam/Infraction";
import { ulid } from "ulid";
import InfractionType from "automod/types/antispam/InfractionType";
import InfractionType from "automod/dist/types/antispam/InfractionType";
async function execute(message: Message, action: CustomRuleAction) {
let warnMsg = action.text

View file

@ -1,6 +1,6 @@
import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
import { client } from "../../..";
import CustomRuleTrigger from "automod/types/antispam/CustomRuleTrigger";
import CustomRuleTrigger from "automod/dist/types/antispam/CustomRuleTrigger";
import VM from 'vm';
let ruleTimeouts: Map<string, number> = new Map();

View file

@ -1,8 +1,8 @@
import { ulid } from "ulid";
import crypto from "crypto";
import { client, dbs } from "../..";
import Infraction from "automod/types/antispam/Infraction";
import InfractionType from "automod/types/antispam/InfractionType";
import Infraction from "automod/dist/types/antispam/Infraction";
import InfractionType from "automod/dist/types/antispam/InfractionType";
import { BLACKLIST_BAN_REASON, BLACKLIST_MESSAGE } from "../commands/admin/botadm";
import logger from "../logger";
import { hasPermForChannel, storeInfraction } from "../util";

View file

@ -1,7 +1,7 @@
import { Member } from "@janderedev/revolt.js/dist/maps/Members";
import { Server } from "@janderedev/revolt.js/dist/maps/Servers";
import { client, dbs } from "../..";
import LogMessage from "automod/types/LogMessage";
import LogMessage from "automod/dist/types/LogMessage";
import logger from "../logger";
import { getAutumnURL, sanitizeMessageContent, sendLogMessage } from "../util";

View file

@ -1,6 +1,6 @@
import { FindResult } from "monk";
import { client, dbs } from "../..";
import TempBan from "automod/types/TempBan";
import TempBan from "automod/dist/types/TempBan";
import logger from "../logger";
// Array of ban IDs which should not get processed in this session

View file

@ -1,12 +1,12 @@
import { Member } from "@janderedev/revolt.js/dist/maps/Members";
import { User } from "@janderedev/revolt.js/dist/maps/Users";
import { client, dbs } from "..";
import Infraction from "automod/types/antispam/Infraction";
import Infraction from "automod/dist/types/antispam/Infraction";
import FormData from 'form-data';
import axios from 'axios';
import { Server } from "@janderedev/revolt.js/dist/maps/Servers";
import LogConfig from "automod/types/LogConfig";
import LogMessage from "automod/types/LogMessage";
import LogConfig from "automod/dist/types/LogConfig";
import LogMessage from "automod/dist/types/LogMessage";
import { ColorResolvable, MessageEmbed } from "discord.js";
import logger from "./logger";
import { ulid } from "ulid";
@ -16,7 +16,7 @@ import { Message } from "@janderedev/revolt.js/dist/maps/Messages";
import { isSudo } from "./commands/admin/botadm";
import { SendableEmbed } from "revolt-api";
import MessageCommandContext from "../struct/MessageCommandContext";
import ServerConfig from "automod/types/ServerConfig";
import ServerConfig from "automod/dist/types/ServerConfig";
const NO_MANAGER_MSG = '🔒 Missing permission';
const ULID_REGEX = /^[0-9A-HJ-KM-NP-TV-Z]{26}$/i;

View file

@ -4,15 +4,15 @@ config();
import logger from './bot/logger';
import AutomodClient, { login } from './struct/AutomodClient';
import MongoDB from './bot/db';
import DbUser from 'automod/types/DbUser';
import ServerConfig from 'automod/types/ServerConfig';
import Infraction from 'automod/types/antispam/Infraction';
import PendingLogin from 'automod/types/PendingLogin';
import TempBan from 'automod/types/TempBan';
import DbUser from 'automod/dist/types/DbUser';
import ServerConfig from 'automod/dist/types/ServerConfig';
import Infraction from 'automod/dist/types/antispam/Infraction';
import PendingLogin from 'automod/dist/types/PendingLogin';
import TempBan from 'automod/dist/types/TempBan';
import { VoteEntry } from './bot/commands/moderation/votekick';
import BridgeRequest from 'automod/types/BridgeRequest';
import BridgeConfig from 'automod/types/BridgeConfig';
import BridgedMessage from 'automod/types/BridgedMessage';
import BridgeRequest from 'automod/dist/types/BridgeRequest';
import BridgeConfig from 'automod/dist/types/BridgeConfig';
import BridgedMessage from 'automod/dist/types/BridgedMessage';
logger.info('Initializing client');

View file

@ -1,6 +1,6 @@
import CommandCategory from "./CommandCategory";
import MessageCommandContext from "../MessageCommandContext";
import ServerConfig from "automod/types/ServerConfig";
import ServerConfig from "automod/dist/types/ServerConfig";
/**
* A basic command, consisting of basic attributes

View file

@ -200,9 +200,9 @@ __metadata:
languageName: node
linkType: hard
"automod@portal:../lib::locator=revolt-automod%40workspace%3A.":
"automod@link:../lib::locator=revolt-automod%40workspace%3A.":
version: 0.0.0-use.local
resolution: "automod@portal:../lib::locator=revolt-automod%40workspace%3A."
resolution: "automod@link:../lib::locator=revolt-automod%40workspace%3A."
languageName: node
linkType: soft
@ -874,7 +874,7 @@ __metadata:
dependencies:
"@janderedev/revolt.js": ^6.0.0-2-patch.1
"@types/monk": ^6.0.0
automod: ^0.1.0
automod: "link:../lib"
axios: ^0.22.0
dayjs: ^1.10.7
discord.js: ^13.3.1

View file

@ -44,6 +44,7 @@ services:
- DB_USERNAME=mogus
- DB_PASS
- DB_NAME=admin
- REDIS_URL
expose:
- 9000
ports:
@ -95,3 +96,7 @@ services:
volumes:
- ./db:/data/db:rw
restart: unless-stopped
redis:
image: eqalpha/keydb
restart: always

View file

@ -3,7 +3,13 @@
"name": "automod",
"version": "1.0.0",
"description": "Shared code for AutoMod",
"scripts": {
"build": "rm -rf dist && tsc"
},
"keywords": [],
"author": "",
"license": "ISC"
"license": "ISC",
"devDependencies": {
"@types/node": "^18.0.4"
}
}

100
lib/tsconfig.json Normal file
View file

@ -0,0 +1,100 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
// "incremental": true, /* Enable incremental compilation */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es5", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
"rootDir": "./src", /* Specify the root folder within your source files. */
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "resolveJsonModule": true, /* Enable importing .json files */
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
"declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
"outDir": "./dist", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
"strictPropertyInitialization": false, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}

View file

@ -2,139 +2,7 @@
# yarn lockfile v1
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
dependencies:
path-key "^3.1.0"
shebang-command "^2.0.0"
which "^2.0.1"
duplexer@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
event-stream@=3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==
dependencies:
duplexer "~0.1.1"
from "~0"
map-stream "~0.1.0"
pause-stream "0.0.11"
split "0.3"
stream-combiner "~0.0.4"
through "~2.3.1"
from@~0:
version "0.1.7"
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
map-stream@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==
node-cleanup@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c"
integrity sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==
path-key@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
pause-stream@0.0.11:
version "0.0.11"
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==
dependencies:
through "~2.3"
ps-tree@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd"
integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==
dependencies:
event-stream "=3.3.4"
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
dependencies:
shebang-regex "^3.0.0"
shebang-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
split@0.3:
version "0.3.3"
resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==
dependencies:
through "2"
stream-combiner@~0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==
dependencies:
duplexer "~0.1.1"
string-argv@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.1.2.tgz#c5b7bc03fb2b11983ba3a72333dd0559e77e4738"
integrity sha512-mBqPGEOMNJKXRo7z0keX0wlAhbBAjilUdPW13nN0PecVryZxdHIeM7TqbsSUA7VYuS00HGC6mojP7DlQzfa9ZA==
strip-ansi@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
through@2, through@~2.3, through@~2.3.1:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
tsc-watch@^5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/tsc-watch/-/tsc-watch-5.0.3.tgz#4d0b2bda8f2677c8f9ed36e001c1a86c31701145"
integrity sha512-Hz2UawwELMSLOf0xHvAFc7anLeMw62cMVXr1flYmhRuOhOyOljwmb1l/O60ZwRyy1k7N1iC1mrn1QYM2zITfuw==
dependencies:
cross-spawn "^7.0.3"
node-cleanup "^2.1.2"
ps-tree "^1.2.0"
string-argv "^0.1.1"
strip-ansi "^6.0.0"
typescript@^4.7.4:
version "4.7.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
which@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
dependencies:
isexe "^2.0.0"
"@types/node@^18.0.4":
version "18.0.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.4.tgz#48aedbf35efb3af1248e4cd4d792c730290cd5d6"
integrity sha512-M0+G6V0Y4YV8cqzHssZpaNCqvYwlCiulmm0PwpNLF55r/+cT8Ol42CHRU1SEaYFH2rTwiiE1aYg/2g2rrtGdPA==

3
redis.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/bash
docker run -p 6379:6379 eqalpha/keydb