1
0
mirror of https://github.com/spacebarchat/server.git synced 2024-11-10 20:52:42 +01:00

Merge pull request #372 from fosscord/unittests

Automatic Unittests + documentation
This commit is contained in:
Flam3rboy 2021-09-23 17:03:36 +02:00 committed by GitHub
commit 5823f8efb4
73 changed files with 26880 additions and 2965 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

6
api/babel.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
presets: [
["@babel/preset-env", { targets: { node: "current" } }],
["@babel/preset-typescript", { allowDeclareFields: true }]
]
};

View File

@ -0,0 +1,66 @@
const { traverseDirectory } = require("lambert-server");
const path = require("path");
const express = require("express");
const RouteUtility = require("../dist/util/route");
const Router = express.Router;
/**
* Some documentation.
*
* @type {Map<string, RouteUtility.RouteOptions>}
*/
const routes = new Map();
let currentPath = "";
let currentFile = "";
const methods = ["get", "post", "put", "delete", "patch"];
function registerPath(file, method, prefix, path, ...args) {
const urlPath = prefix + path;
const sourceFile = file.replace("/dist/", "/src/").replace(".js", ".ts");
const opts = args.find((x) => typeof x === "object");
if (opts) {
routes.set(urlPath + "|" + method, opts); // @ts-ignore
opts.file = sourceFile;
// console.log(method, urlPath, opts);
} else {
console.log(`${sourceFile}\nrouter.${method}("${path}") is missing the "route()" description middleware\n`);
}
}
function routeOptions(opts) {
return opts;
}
// @ts-ignore
RouteUtility.route = routeOptions;
express.Router = (opts) => {
const path = currentPath;
const file = currentFile;
const router = Router(opts);
for (const method of methods) {
router[method] = registerPath.bind(null, file, method, path);
}
return router;
};
module.exports = function getRouteDescriptions() {
const root = path.join(__dirname, "..", "dist", "routes", "/");
traverseDirectory({ dirname: root, recursive: true }, (file) => {
currentFile = file;
let path = file.replace(root.slice(0, -1), "");
path = path.split(".").slice(0, -1).join("."); // trancate .js/.ts file extension of path
path = path.replaceAll("#", ":").replaceAll("\\", "/"); // replace # with : for path parameters and windows paths with slashes
if (path.endsWith("/index")) path = path.slice(0, "/index".length * -1); // delete index from path
currentPath = path;
try {
require(file);
} catch (error) {
console.error("error loading file " + file, error);
}
});
return routes;
};

View File

@ -1,3 +1,4 @@
const { Config, initDatabase } = require("@fosscord/util");
const fs = require("fs");
const path = require("path");
const { FosscordServer } = require("../dist/Server");
@ -5,8 +6,12 @@ const Server = new FosscordServer({ port: 3001 });
global.server = Server;
module.exports = async () => {
try {
fs.unlinkSync(path.join(__dirname, "..", "database.db"));
fs.unlinkSync(path.join(process.cwd(), "database.db"));
} catch {}
await initDatabase();
await Config.init();
Config.get().limits.rate.disabled = true;
return await Server.start();
};

5624
api/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,17 +5,17 @@
"main": "dist/Server.js",
"types": "dist/Server.d.ts",
"scripts": {
"test:only": "node -r ./scripts/tsconfig-paths-bootstrap.js node_modules/.bin/jest --coverage --verbose --forceExit ./tests",
"test:only": "jest --coverage --verbose --forceExit ./tests",
"test": "npm run build && npm run test:only",
"test:watch": "jest --watch",
"start": "npm run build && node -r ./scripts/tsconfig-paths-bootstrap.js dist/start",
"start": "npm run build && node dist/start",
"build": "npx tsc -b .",
"build-docker": "tsc -p tsconfig-docker.json",
"dev": "tsnd --respawn src/start.ts",
"patch": "npx patch-package",
"patch": "ts-patch install -s && npx patch-package",
"postinstall": "npm run patch",
"generate:docs": "ts-node scripts/generate_openapi_schema.ts",
"generate:schema": "ts-node scripts/generate_body_schema.ts"
"generate:docs": "node scripts/generate_openapi.ts",
"generate:schema": "node scripts/generate_schema.ts"
},
"repository": {
"type": "git",
@ -36,11 +36,15 @@
},
"homepage": "https://fosscord.com",
"devDependencies": {
"@babel/core": "^7.15.5",
"@babel/preset-env": "^7.15.6",
"@babel/preset-typescript": "^7.15.0",
"@types/amqplib": "^0.8.1",
"@types/bcrypt": "^5.0.0",
"@types/express": "^4.17.9",
"@types/i18next-node-fs-backend": "^2.1.0",
"@types/jest": "^27.0.1",
"@types/jest-expect-message": "^1.0.3",
"@types/jsonwebtoken": "^8.5.0",
"@types/mongodb": "^3.6.9",
"@types/mongoose": "^5.10.5",
@ -49,14 +53,19 @@
"@types/multer": "^1.4.5",
"@types/node": "^14.17.9",
"@types/node-fetch": "^2.5.7",
"@types/supertest": "^2.0.11",
"@zerollup/ts-transform-paths": "^1.7.18",
"0x": "^4.10.2",
"babel-jest": "^27.2.0",
"caxa": "^2.1.0",
"image-size": "^1.0.0",
"jest": "^26.6.3",
"jest-expect-message": "^1.0.2",
"jest-runtime": "^27.2.1",
"saslprep": "^1.0.3",
"ts-node": "^9.1.1",
"ts-node-dev": "^1.1.6",
"ts-patch": "^1.4.4",
"typescript": "^4.4.2",
"typescript-json-schema": "0.50.1"
},
@ -77,7 +86,7 @@
"express": "^4.17.1",
"express-validator": "^6.9.2",
"form-data": "^3.0.0",
"i18next": "^19.8.5",
"i18next": "^19.9.2",
"i18next-http-middleware": "^3.1.3",
"i18next-node-fs-backend": "^2.1.3",
"jsonwebtoken": "^8.5.1",
@ -98,7 +107,10 @@
"setupFiles": [
"<rootDir>/jest/setup.js"
],
"globalSetup": "<rootDir>/scripts/globalSetup.js",
"setupFilesAfterEnv": [
"jest-expect-message"
],
"globalSetup": "<rootDir>/jest/globalSetup.js",
"verbose": true
}
}

View File

@ -0,0 +1,137 @@
// https://mermade.github.io/openapi-gui/#
// https://editor.swagger.io/
const getRouteDescriptions = require("../jest/getRouteDescriptions");
const path = require("path");
const fs = require("fs");
require("missing-native-js-functions");
const openapiPath = path.join(__dirname, "..", "assets", "openapi.json");
const SchemaPath = path.join(__dirname, "..", "assets", "schemas.json");
const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" }));
const specification = JSON.parse(fs.readFileSync(openapiPath, { encoding: "utf8" }));
function combineSchemas(schemas) {
var definitions = {};
for (const name in schemas) {
definitions = {
...definitions,
...schemas[name].definitions,
[name]: { ...schemas[name], definitions: undefined, $schema: undefined }
};
}
for (const key in definitions) {
specification.components.schemas[key] = definitions[key];
delete definitions[key].additionalProperties;
delete definitions[key].$schema;
const definition = definitions[key];
if (typeof definition.properties === "object") {
for (const property of Object.values(definition.properties)) {
if (Array.isArray(property.type)) {
if (property.type.includes("null")) {
property.type = property.type.find((x) => x !== "null");
property.nullable = true;
}
}
}
}
}
return definitions;
}
function getTag(key) {
return key.match(/\/([\w-]+)/)[1];
}
function apiRoutes() {
const routes = getRouteDescriptions();
const tags = Array.from(routes.keys()).map((x) => getTag(x));
specification.tags = [...specification.tags.map((x) => x.name), ...tags].unique().map((x) => ({ name: x }));
routes.forEach((route, pathAndMethod) => {
const [p, method] = pathAndMethod.split("|");
const path = p.replace(/:(\w+)/g, "{$1}");
let obj = specification.paths[path]?.[method] || {};
if (!obj.description) {
const permission = route.permission ? `##### Requires the \`\`${route.permission}\`\` permission\n` : "";
const event = route.test?.event ? `##### Fires a \`\`${route.test?.event}\`\` event\n` : "";
obj.description = permission + event;
}
if (route.body) {
obj.requestBody = {
required: true,
content: {
"application/json": {
schema: { $ref: `#/components/schemas/${route.body}` }
}
}
}.merge(obj.requestBody);
}
if (!obj.responses) {
obj.responses = {
default: {
description: "not documented"
}
};
}
if (route.test?.response) {
const status = route.test.response.status || 200;
let schema = {
allOf: [
{
$ref: `#/components/schemas/${route.test.response.body}`
},
{
example: route.test.body
}
]
};
if (!route.test.body) schema = schema.allOf[0];
obj.responses = {
[status]: {
...(route.test.response.body
? {
description: obj.responses[status].description || "",
content: {
"application/json": {
schema: schema
}
}
}
: {})
}
}.merge(obj.responses);
delete obj.responses.default;
}
if (p.includes(":")) {
obj.parameters = p.match(/:\w+/g)?.map((x) => ({
name: x.replace(":", ""),
in: "path",
required: true,
schema: { type: "string" },
description: x.replace(":", "")
}));
}
obj.tags = [...(obj.tags || []), getTag(p)].unique();
specification.paths[path] = { ...specification.paths[path], [method]: obj };
});
}
function main() {
combineSchemas(schemas);
apiRoutes();
fs.writeFileSync(
openapiPath,
JSON.stringify(specification, null, 4).replaceAll("#/definitions", "#/components/schemas").replaceAll("bigint", "number")
);
}
main();

View File

@ -1,99 +0,0 @@
// https://mermade.github.io/openapi-gui/#
// https://editor.swagger.io/
import path from "path";
import fs from "fs";
import * as TJS from "typescript-json-schema";
import "missing-native-js-functions";
const settings: TJS.PartialArgs = {
required: true,
ignoreErrors: true,
excludePrivate: true,
defaultNumberType: "integer",
noExtraProps: true,
defaultProps: false
};
const compilerOptions: TJS.CompilerOptions = {
strictNullChecks: false
};
const openapiPath = path.join(__dirname, "..", "assets", "openapi.json");
var specification = JSON.parse(fs.readFileSync(openapiPath, { encoding: "utf8" }));
async function utilSchemas() {
const program = TJS.getProgramFromFiles([path.join(__dirname, "..", "..", "util", "src", "index.ts")], compilerOptions);
const generator = TJS.buildGenerator(program, settings);
const schemas = ["UserPublic", "UserPrivate", "PublicConnectedAccount"];
// @ts-ignore
combineSchemas({ schemas, generator, program });
}
function combineSchemas(opts: { program: TJS.Program; generator: TJS.JsonSchemaGenerator; schemas: string[] }) {
var definitions: any = {};
for (const name of opts.schemas) {
const part = TJS.generateSchema(opts.program, name, settings, [], opts.generator as TJS.JsonSchemaGenerator);
if (!part) continue;
definitions = { ...definitions, [name]: { ...part, definitions: undefined, $schema: undefined } };
}
for (const key in definitions) {
specification.components.schemas[key] = definitions[key];
delete definitions[key].additionalProperties;
delete definitions[key].$schema;
}
return definitions;
}
function apiSchemas() {
const program = TJS.getProgramFromFiles([path.join(__dirname, "..", "src", "schema", "index.ts")], compilerOptions);
const generator = TJS.buildGenerator(program, settings);
const schemas = [
"BanCreateSchema",
"DmChannelCreateSchema",
"ChannelModifySchema",
"ChannelGuildPositionUpdateSchema",
"ChannelGuildPositionUpdateSchema",
"EmojiCreateSchema",
"GuildCreateSchema",
"GuildUpdateSchema",
"GuildTemplateCreateSchema",
"GuildUpdateWelcomeScreenSchema",
"InviteCreateSchema",
"MemberCreateSchema",
"MemberNickChangeSchema",
"MemberChangeSchema",
"MessageCreateSchema",
"RoleModifySchema",
"TemplateCreateSchema",
"TemplateModifySchema",
"UserModifySchema",
"UserSettingsSchema",
"WidgetModifySchema",
""
];
// @ts-ignore
combineSchemas({ schemas, generator, program });
}
function addDefaultResponses() {
Object.values(specification.paths).forEach((path: any) => Object.values(path).forEach((request: any) => {}));
}
function main() {
addDefaultResponses();
utilSchemas();
apiSchemas();
fs.writeFileSync(
openapiPath,
JSON.stringify(specification, null, 4).replaceAll("#/definitions", "#/components/schemas").replaceAll("bigint", "number")
);
}
main();

View File

@ -6,7 +6,7 @@ import * as TJS from "typescript-json-schema";
import "missing-native-js-functions";
const schemaPath = path.join(__dirname, "..", "assets", "schemas.json");
const settings: TJS.PartialArgs = {
const settings = {
required: true,
ignoreErrors: true,
excludePrivate: true,
@ -14,23 +14,34 @@ const settings: TJS.PartialArgs = {
noExtraProps: true,
defaultProps: false
};
const compilerOptions: TJS.CompilerOptions = {
const compilerOptions = {
strictNullChecks: true
};
const ExcludedSchemas = ["DefaultSchema", "Schema", "EntitySchema"];
const Excluded = [
"DefaultSchema",
"Schema",
"EntitySchema",
"ServerResponse",
"Http2ServerResponse",
"global.Express.Response",
"Response",
"e.Response",
"request.Response",
"supertest.Response"
];
function main() {
const program = TJS.getProgramFromFiles(walk(path.join(__dirname, "..", "src", "routes")), compilerOptions);
const generator = TJS.buildGenerator(program, settings);
if (!generator || !program) return;
const schemas = generator.getUserSymbols().filter((x) => x.endsWith("Schema") && !ExcludedSchemas.includes(x));
const schemas = generator.getUserSymbols().filter((x) => (x.endsWith("Schema") || x.endsWith("Response")) && !Excluded.includes(x));
console.log(schemas);
var definitions: any = {};
var definitions = {};
for (const name of schemas) {
const part = TJS.generateSchema(program, name, settings, [], generator as TJS.JsonSchemaGenerator);
const part = TJS.generateSchema(program, name, settings, [], generator);
if (!part) continue;
definitions = { ...definitions, [name]: { ...part } };
@ -39,11 +50,10 @@ function main() {
fs.writeFileSync(schemaPath, JSON.stringify(definitions, null, 4));
}
// #/definitions/
main();
function walk(dir: string) {
var results = [] as string[];
function walk(dir) {
var results = [];
var list = fs.readdirSync(dir);
list.forEach(function (file) {
file = dir + "/" + file;

View File

@ -1,10 +0,0 @@
const tsConfigPaths = require("tsconfig-paths");
const path = require("path");
const cleanup = tsConfigPaths.register({
baseUrl: path.join(__dirname, ".."),
paths: {
"@fosscord/api": ["dist/index.js"],
"@fosscord/api/*": ["dist/*"]
}
});

View File

@ -6,6 +6,8 @@ export function BodyParser(opts?: OptionsJson) {
const jsonParser = bodyParser.json(opts);
return (req: Request, res: Response, next: NextFunction) => {
if (!req.headers["content-type"]) req.headers["content-type"] = "application/json";
jsonParser(req, res, (err) => {
if (err) {
// TODO: different errors for body parser (request size limit, wrong body type, invalid body, ...)

View File

@ -3,6 +3,7 @@ import { HTTPError } from "lambert-server";
import { EntityNotFoundError } from "typeorm";
import { FieldError } from "@fosscord/api";
import { ApiError } from "@fosscord/util";
const EntityNotFoundErrorRegex = /"(\w+)"/;
export function ErrorHandler(error: Error, req: Request, res: Response, next: NextFunction) {
if (!error) return next();
@ -18,9 +19,9 @@ export function ErrorHandler(error: Error, req: Request, res: Response, next: Ne
code = error.code;
message = error.message;
httpcode = error.httpStatus;
} else if (error instanceof EntityNotFoundError) {
message = `${(error as any).stringifyTarget || "Item"} could not be found`;
code = 404;
} else if (error.name === "EntityNotFoundError") {
message = `${error.message.match(EntityNotFoundErrorRegex)?.[1] || "Item"} could not be found`;
code = httpcode = 404;
} else if (error instanceof FieldError) {
code = Number(error.code);
message = error.message;

View File

@ -107,7 +107,8 @@ export default function rateLimit(opts: {
}
export async function initRateLimits(app: Router) {
const { routes, global, ip, error } = Config.get().limits.rate;
const { routes, global, ip, error, disabled } = Config.get().limits.rate;
if (disabled) return;
await listenEvent(EventRateLimit, (event) => {
Cache.set(event.channel_id as string, event.data);
event.acknowledge?.();

View File

@ -1,10 +1,11 @@
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
const router: Router = Router();
router.get("/", async (req: Request, res: Response) => {
router.get("/", route({}), async (req: Request, res: Response) => {
//TODO
res.json([]).status(200);
});
export default router;
export default router;

View File

@ -1,9 +1,7 @@
import { Request, Response, Router } from "express";
import { FieldErrors, route } from "@fosscord/api";
import bcrypt from "bcrypt";
import jwt from "jsonwebtoken";
import { Config, User } from "@fosscord/util";
import { adjustEmail } from "./register";
import { Config, User, generateToken, adjustEmail } from "@fosscord/util";
const router: Router = Router();
export default router;
@ -68,25 +66,6 @@ router.post("/", route({ body: "LoginSchema" }), async (req: Request, res: Respo
res.json({ token, settings: user.settings });
});
export async function generateToken(id: string) {
const iat = Math.floor(Date.now() / 1000);
const algorithm = "HS256";
return new Promise((res, rej) => {
jwt.sign(
{ id: id, iat },
Config.get().security.jwtSecret,
{
algorithm
},
(err, token) => {
if (err) return rej(err);
return res(token);
}
);
});
}
/**
* POST /auth/login
* @argument { login: "email@gmail.com", password: "cleartextpassword", undelete: false, captcha_key: null, login_source: null, gift_code_sku_id: null, }

View File

@ -1,10 +1,8 @@
import { Request, Response, Router } from "express";
import { trimSpecial, User, Snowflake, Config, defaultSettings, Member, Invite } from "@fosscord/util";
import { trimSpecial, User, Snowflake, Config, defaultSettings, generateToken, Invite, adjustEmail } from "@fosscord/util";
import bcrypt from "bcrypt";
import { EMAIL_REGEX, FieldErrors, route } from "@fosscord/api";
import { FieldErrors, route, getIpAdress, IPAnalysis, isProxy } from "@fosscord/api";
import "missing-native-js-functions";
import { generateToken } from "./login";
import { getIpAdress, IPAnalysis, isProxy } from "@fosscord/api";
import { HTTPError } from "lambert-server";
const router: Router = Router();
@ -228,24 +226,6 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
return res.json({ token: await generateToken(user.id) });
});
export function adjustEmail(email: string): string | undefined {
if (!email) return email;
// body parser already checked if it is a valid email
const parts = <RegExpMatchArray>email.match(EMAIL_REGEX);
// @ts-ignore
if (!parts || parts.length < 5) return undefined;
const domain = parts[5];
const user = parts[1];
// TODO: check accounts with uncommon email domains
if (domain === "gmail.com" || domain === "googlemail.com") {
// replace .dots and +alternatives -> Gmail Dot Trick https://support.google.com/mail/answer/7436150 and https://generator.email/blog/gmail-generator
return user.replace(/[.]|(\+.*)/g, "") + "@gmail.com";
}
return email;
}
export default router;
/**

View File

@ -1,9 +1,10 @@
import { Request, Response, Router } from "express";
import { Channel, ChannelRecipientAddEvent, ChannelType, DiscordApiErrors, DmChannelDTO, emitEvent, PublicUserProjection, Recipient, User } from "@fosscord/util";
import { route } from "@fosscord/api"
const router: Router = Router();
router.put("/:user_id", async (req: Request, res: Response) => {
router.put("/:user_id", route({}), async (req: Request, res: Response) => {
const { channel_id, user_id } = req.params;
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] });
@ -39,7 +40,7 @@ router.put("/:user_id", async (req: Request, res: Response) => {
}
});
router.delete("/:user_id", async (req: Request, res: Response) => {
router.delete("/:user_id", route({}), async (req: Request, res: Response) => {
const { channel_id, user_id } = req.params;
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] });
if (!(channel.type === ChannelType.GROUP_DM && (channel.owner_id === req.user_id || user_id === req.user_id)))

View File

@ -5,7 +5,7 @@ import { route } from "@fosscord/api";
import { ChannelModifySchema } from "../../channels/#channel_id";
const router = Router();
router.get("/", async (req: Request, res: Response) => {
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params;
const channels = await Channel.find({ guild_id });

View File

@ -4,14 +4,14 @@ import { Request, Response, Router } from "express";
const router = Router();
router.delete("/:member_id/roles/:role_id", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
router.delete("/", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
const { guild_id, role_id, member_id } = req.params;
await Member.removeRole(member_id, guild_id, role_id);
res.sendStatus(204);
});
router.put("/:member_id/roles/:role_id", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
router.put("/", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
const { guild_id, role_id, member_id } = req.params;
await Member.addRole(member_id, guild_id, role_id);

View File

@ -29,7 +29,7 @@ export type RolePositionUpdateSchema = {
position: number;
}[];
router.get("/", async (req: Request, res: Response) => {
router.get("/", route({}), async (req: Request, res: Response) => {
const guild_id = req.params.guild_id;
await Member.IsInGuildOrFail(req.user_id, guild_id);

View File

@ -1,10 +1,11 @@
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
const router: Router = Router();
router.get("/", async (req: Request, res: Response) => {
router.get("/", route({}), async (req: Request, res: Response) => {
//TODO
res.json([]).status(200);
});
export default router;
export default router;

View File

@ -1,8 +1,9 @@
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
const router: Router = Router();
router.get("/", async (req: Request, res: Response) => {
router.get("/", route({}), async (req: Request, res: Response) => {
//TODO
res.json({
id: "",
@ -15,4 +16,4 @@ router.get("/", async (req: Request, res: Response) => {
}).status(200);
});
export default router;
export default router;

View File

@ -1,10 +1,11 @@
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
const router: Router = Router();
router.get("/", async (req: Request, res: Response) => {
router.get("/", route({}), async (req: Request, res: Response) => {
//TODO
res.json({ sticker_packs: [] }).status(200);
});
export default router;
export default router;

View File

@ -1,11 +1,12 @@
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
const router: Router = Router();
router.get("/applications/:id", async (req: Request, res: Response) => {
//TODO
const { id } = req.params;
router.get("/applications/:id", route({}), async (req: Request, res: Response) => {
//TODO
const { id } = req.params;
res.json([]).status(200);
});
export default router;
export default router;

View File

@ -1,11 +1,12 @@
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
const router: Router = Router();
router.get("/skus/:id", async (req: Request, res: Response) => {
router.get("/skus/:id", route({}), async (req: Request, res: Response) => {
//TODO
const { id } = req.params;
const { id } = req.params;
res.json([]).status(200);
});
export default router;
export default router;

View File

@ -11,7 +11,7 @@ export interface UserProfileResponse {
premium_since?: Date;
}
router.get("/", route({ response: { body: "UserProfileResponse" } }), async (req: Request, res: Response) => {
router.get("/", route({ test: { response: { body: "UserProfileResponse" } } }), async (req: Request, res: Response) => {
if (req.params.id === "@me") req.params.id = req.user_id;
const user = await User.getPublicUser(req.params.id, { relations: ["connected_accounts"] });

View File

@ -1,10 +1,11 @@
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
const router: Router = Router();
router.get("/", async (req: Request, res: Response) => {
router.get("/", route({}), async (req: Request, res: Response) => {
//TODO
res.json([]).status(200);
});
export default router;
export default router;

View File

@ -1,10 +1,11 @@
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
const router: Router = Router();
router.get("/", async (req: Request, res: Response) => {
router.get("/", route({}), async (req: Request, res: Response) => {
//TODO
res.json({ "country_code": "US" }).status(200);
res.json({ country_code: "US" }).status(200);
});
export default router;
export default router;

View File

@ -1,10 +1,11 @@
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
const router: Router = Router();
router.get("/", async (req: Request, res: Response) => {
router.get("/", route({}), async (req: Request, res: Response) => {
//TODO
res.json([]).status(200);
});
export default router;
export default router;

View File

@ -22,7 +22,7 @@ export interface UserModifySchema {
code?: string;
}
router.get("/", async (req: Request, res: Response) => {
router.get("/", route({}), async (req: Request, res: Response) => {
res.json(await User.findOne({ select: PrivateUserProjection, where: { id: req.user_id } }));
});

View File

@ -1,8 +1,6 @@
import { Request } from "express";
import { ntob } from "./Base64";
import { FieldErrors } from "./FieldError";
export const EMAIL_REGEX =
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
export function checkLength(str: string, min: number, max: number, key: string, req: Request) {
if (str.length < min || str.length > max) {

View File

@ -1,4 +1,4 @@
import { DiscordApiErrors, Event, EventData, getPermission, PermissionResolvable, Permissions } from "@fosscord/util";
import { DiscordApiErrors, EVENT, Event, EventData, getPermission, PermissionResolvable, Permissions } from "@fosscord/util";
import { NextFunction, Request, Response } from "express";
import fs from "fs";
import path from "path";
@ -29,17 +29,16 @@ declare global {
}
}
export type RouteSchema = string; // typescript interface name
export type RouteResponse = { status?: number; body?: RouteSchema; headers?: Record<string, string> };
export type RouteResponse = { status?: number; body?: `${string}Response`; headers?: Record<string, string> };
export interface RouteOptions {
permission?: PermissionResolvable;
body?: RouteSchema;
response?: RouteResponse;
example?: {
body?: `${string}Schema`; // typescript interface name
test?: {
response?: RouteResponse;
body?: any;
path?: string;
event?: EventData;
event?: EVENT | EVENT[];
headers?: Record<string, string>;
};
}

View File

@ -1,2 +0,0 @@
// TODO: check every route based on route() paramters: https://github.com/fosscord/fosscord-server/issues/308
// TODO: check every route with different database engine

136
api/tests/routes.test.ts Normal file
View File

@ -0,0 +1,136 @@
// TODO: check every route based on route() parameters: https://github.com/fosscord/fosscord-server/issues/308
// TODO: check every route with different database engine
import getRouteDescriptions from "../jest/getRouteDescriptions";
import { join } from "path";
import fs from "fs";
import Ajv from "ajv";
import addFormats from "ajv-formats";
import fetch from "node-fetch";
import { Event, User, events } from "@fosscord/util";
const SchemaPath = join(__dirname, "..", "assets", "schemas.json");
const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" }));
export const ajv = new Ajv({
allErrors: true,
parseDate: true,
allowDate: true,
schemas,
messages: true,
strict: true,
strictRequired: true,
coerceTypes: true
});
addFormats(ajv);
var token: string;
var user: User;
beforeAll(async (done) => {
try {
const response = await fetch("http://localhost:3001/api/auth/register", {
method: "POST",
body: JSON.stringify({
fingerprint: "805826570869932034.wR8vi8lGlFBJerErO9LG5NViJFw",
email: "test@example.com",
username: "tester",
password: "wtp9gep9gw",
invite: null,
consent: true,
date_of_birth: "2000-01-01",
gift_code_sku_id: null,
captcha_key: null
}),
headers: {
"content-type": "application/json"
}
});
const json = await response.json();
token = json.token;
user = await (
await fetch(`http://localhost:3001/api/users/@me`, {
headers: { authorization: token }
})
).json();
done();
} catch (error) {
done(error);
}
});
const emit = events.emit;
events.emit = (event: string | symbol, ...args: any[]) => {
events.emit("event", args[0]);
return emit(event, ...args);
};
describe("Automatic unit tests with route description middleware", () => {
const routes = getRouteDescriptions();
routes.forEach((route, pathAndMethod) => {
const [path, method] = pathAndMethod.split("|");
test(`${method.toUpperCase()} ${path}`, async (done) => {
if (!route.test) {
console.log(`${(route as any).file}\nrouter.${method} is missing the test property`);
return done();
}
const urlPath = path.replace(":id", user.id) || route.test?.path;
var validate: any;
if (route.test.body) {
validate = ajv.getSchema(route.test.body);
if (!validate) return done(new Error(`Response schema ${route.test.body} not found`));
}
var body = "";
let eventEmitted = Promise.resolve();
if (route.test.event) {
if (!Array.isArray(route.test.event)) route.test.event = [route.test.event];
eventEmitted = new Promise((resolve, reject) => {
const timeout = setTimeout(() => reject, 1000);
const received = [];
events.on("event", (event: Event) => {
if (!route.test.event.includes(event.event)) return;
received.push(event.event);
if (received.length === route.test.event.length) resolve();
});
});
}
try {
const response = await fetch(`http://localhost:3001/api${urlPath}`, {
method: method.toUpperCase(),
body: JSON.stringify(route.test.body),
headers: { ...route.test.headers, authorization: token }
});
body = await response.text();
expect(response.status, body).toBe(route.test.response.status || 200);
// TODO: check headers
// TODO: expect event
if (validate) {
body = JSON.parse(body);
const valid = validate(body);
if (!valid) return done(validate.errors);
}
} catch (error) {
return done(error);
}
try {
await eventEmitted;
} catch (error) {
return done(new Error(`Event ${route.test.event} was not emitted`));
}
return done();
});
});
});

View File

@ -66,8 +66,9 @@
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
"baseUrl": ".",
"paths": {
"@fosscord/api": ["src/index.ts"],
"@fosscord/api": ["src/index"],
"@fosscord/api/*": ["src/*"]
}
},
"plugins": [{ "transform": "@zerollup/ts-transform-paths" }]
}
}

555
bundle/package-lock.json generated
View File

@ -38,6 +38,7 @@
"@types/ws": "^7.4.0",
"@zerollup/ts-transform-paths": "^1.7.18",
"ts-node": "^10.2.1",
"ts-patch": "^1.4.4",
"typescript": "^4.3.5"
}
},
@ -63,7 +64,7 @@
"express": "^4.17.1",
"express-validator": "^6.9.2",
"form-data": "^3.0.0",
"i18next": "^19.8.5",
"i18next": "^19.9.2",
"i18next-http-middleware": "^3.1.3",
"i18next-node-fs-backend": "^2.1.3",
"jsonwebtoken": "^8.5.1",
@ -81,11 +82,15 @@
"typeorm": "^0.2.37"
},
"devDependencies": {
"@babel/core": "^7.15.5",
"@babel/preset-env": "^7.15.6",
"@babel/preset-typescript": "^7.15.0",
"@types/amqplib": "^0.8.1",
"@types/bcrypt": "^5.0.0",
"@types/express": "^4.17.9",
"@types/i18next-node-fs-backend": "^2.1.0",
"@types/jest": "^27.0.1",
"@types/jest-expect-message": "^1.0.3",
"@types/jsonwebtoken": "^8.5.0",
"@types/mongodb": "^3.6.9",
"@types/mongoose": "^5.10.5",
@ -94,14 +99,19 @@
"@types/multer": "^1.4.5",
"@types/node": "^14.17.9",
"@types/node-fetch": "^2.5.7",
"@types/supertest": "^2.0.11",
"@zerollup/ts-transform-paths": "^1.7.18",
"0x": "^4.10.2",
"babel-jest": "^27.2.0",
"caxa": "^2.1.0",
"image-size": "^1.0.0",
"jest": "^26.6.3",
"jest-expect-message": "^1.0.2",
"jest-runtime": "^27.2.1",
"saslprep": "^1.0.3",
"ts-node": "^9.1.1",
"ts-node-dev": "^1.1.6",
"ts-patch": "^1.4.4",
"typescript": "^4.4.2",
"typescript-json-schema": "0.50.1"
}
@ -109,6 +119,7 @@
"../cdn": {
"name": "@fosscord/cdn",
"version": "1.0.0",
"hasInstallScript": true,
"license": "ISC",
"dependencies": {
"@fosscord/util": "file:../util",
@ -146,12 +157,15 @@
"@types/multer": "^1.4.7",
"@types/node": "^14.17.0",
"@types/node-fetch": "^2.5.7",
"@types/uuid": "^8.3.0"
"@types/uuid": "^8.3.0",
"@zerollup/ts-transform-paths": "^1.7.18",
"ts-patch": "^1.4.4"
}
},
"../gateway": {
"name": "@fosscord/gateway",
"version": "1.0.0",
"hasInstallScript": true,
"license": "ISC",
"dependencies": {
"@fosscord/util": "file:../util",
@ -177,7 +191,9 @@
"@types/node-fetch": "^2.5.12",
"@types/uuid": "^8.3.0",
"@types/ws": "^7.4.0",
"@zerollup/ts-transform-paths": "^1.7.18",
"ts-node-dev": "^1.1.6",
"ts-patch": "^1.4.4",
"typescript": "^4.2.3"
}
},
@ -195,6 +211,7 @@
"jsonwebtoken": "^8.5.1",
"lambert-server": "^1.2.10",
"missing-native-js-functions": "^1.2.15",
"multer": "^1.4.3",
"node-fetch": "^2.6.1",
"patch-package": "^6.4.7",
"pg": "^8.7.1",
@ -209,6 +226,7 @@
"@types/amqplib": "^0.8.1",
"@types/jsonwebtoken": "^8.5.0",
"@types/mongoose-autopopulate": "^0.10.1",
"@types/multer": "^1.4.7",
"@types/node": "^14.17.9",
"@types/node-fetch": "^2.5.12",
"jest": "^27.0.6"
@ -562,6 +580,30 @@
"node": ">=0.4.0"
}
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
@ -587,6 +629,12 @@
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
"dev": true
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@ -627,6 +675,16 @@
"node": ">= 0.8"
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/bson": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/bson/-/bson-4.5.2.tgz",
@ -671,6 +729,40 @@
"node": ">= 0.8"
}
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@ -683,6 +775,12 @@
"node": ">= 0.8"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"node_modules/content-disposition": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
@ -873,12 +971,52 @@
"node": ">= 0.6"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"node_modules/glob": {
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/global-prefix": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
"integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
"dev": true,
"dependencies": {
"ini": "^1.3.5",
"kind-of": "^6.0.2",
"which": "^1.3.1"
},
"engines": {
"node": ">=6"
}
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@ -891,6 +1029,15 @@
"node": ">= 0.4.0"
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/http-errors": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
@ -946,11 +1093,36 @@
}
]
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"node_modules/ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
"node_modules/interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
"dev": true,
"engines": {
"node": ">= 0.10"
}
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@ -971,6 +1143,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"node_modules/json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
@ -982,6 +1160,15 @@
"json5": "lib/cli.js"
}
},
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@ -1039,6 +1226,18 @@
"node": ">= 0.6"
}
},
"node_modules/minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
@ -1078,6 +1277,15 @@
"node": ">= 0.8"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"dependencies": {
"wrappy": "1"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@ -1086,6 +1294,15 @@
"node": ">= 0.8"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
@ -1139,6 +1356,18 @@
"node": ">= 0.8"
}
},
"node_modules/rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
"dev": true,
"dependencies": {
"resolve": "^1.1.6"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
@ -1215,6 +1444,23 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
"node_modules/shelljs": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
"integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
"dev": true,
"dependencies": {
"glob": "^7.0.0",
"interpret": "^1.0.0",
"rechoir": "^0.6.2"
},
"bin": {
"shjs": "bin/shjs"
},
"engines": {
"node": ">=4"
}
},
"node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
@ -1223,6 +1469,18 @@
"node": ">= 0.6"
}
},
"node_modules/strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
@ -1231,6 +1489,18 @@
"node": ">=4"
}
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
@ -1283,6 +1553,27 @@
}
}
},
"node_modules/ts-patch": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/ts-patch/-/ts-patch-1.4.4.tgz",
"integrity": "sha512-b0CxxrkrCGsD22gl5BtSFlXzyTFP2mbOVffxMOWRrwdSh37sM01wzxSY4wlbBiHHHAJICmaaDgESzJ8lKkVoZA==",
"dev": true,
"dependencies": {
"chalk": "^4.1.0",
"glob": "^7.1.7",
"global-prefix": "^3.0.0",
"minimist": "^1.2.5",
"resolve": "^1.20.0",
"shelljs": "^0.8.4",
"strip-ansi": "^6.0.0"
},
"bin": {
"ts-patch": "bin/cli.js"
},
"peerDependencies": {
"typescript": ">2.7.0"
}
},
"node_modules/tsconfig-paths": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz",
@ -1343,6 +1634,24 @@
"node": ">= 0.8"
}
},
"node_modules/which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dev": true,
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"which": "bin/which"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
@ -1381,12 +1690,16 @@
"@fosscord/api": {
"version": "file:../api",
"requires": {
"@babel/core": "^7.15.5",
"@babel/preset-env": "^7.15.6",
"@babel/preset-typescript": "^7.15.0",
"@fosscord/util": "file:../util",
"@types/amqplib": "^0.8.1",
"@types/bcrypt": "^5.0.0",
"@types/express": "^4.17.9",
"@types/i18next-node-fs-backend": "^2.1.0",
"@types/jest": "^27.0.1",
"@types/jest-expect-message": "^1.0.3",
"@types/jsonwebtoken": "^8.5.0",
"@types/mongodb": "^3.6.9",
"@types/mongoose": "^5.10.5",
@ -1396,6 +1709,7 @@
"@types/multer": "^1.4.5",
"@types/node": "^14.17.9",
"@types/node-fetch": "^2.5.7",
"@types/supertest": "^2.0.11",
"@zerollup/ts-transform-paths": "^1.7.18",
"0x": "^4.10.2",
"ajv": "8.6.2",
@ -1403,6 +1717,7 @@
"amqplib": "^0.8.0",
"assert": "^1.5.0",
"atomically": "^1.7.0",
"babel-jest": "^27.2.0",
"bcrypt": "^5.0.1",
"body-parser": "^1.19.0",
"caxa": "^2.1.0",
@ -1413,11 +1728,13 @@
"express": "^4.17.1",
"express-validator": "^6.9.2",
"form-data": "^3.0.0",
"i18next": "^19.8.5",
"i18next": "^19.9.2",
"i18next-http-middleware": "^3.1.3",
"i18next-node-fs-backend": "^2.1.3",
"image-size": "^1.0.0",
"jest": "^26.6.3",
"jest-expect-message": "^1.0.2",
"jest-runtime": "^27.2.1",
"jsonwebtoken": "^8.5.1",
"lambert-server": "^1.2.10",
"missing-native-js-functions": "^1.2.15",
@ -1432,6 +1749,7 @@
"supertest": "^6.1.6",
"ts-node": "^9.1.1",
"ts-node-dev": "^1.1.6",
"ts-patch": "^1.4.4",
"tsconfig-paths": "^3.11.0",
"typeorm": "^0.2.37",
"typescript": "^4.4.2",
@ -1456,6 +1774,7 @@
"@types/node": "^14.17.0",
"@types/node-fetch": "^2.5.7",
"@types/uuid": "^8.3.0",
"@zerollup/ts-transform-paths": "^1.7.18",
"body-parser": "^1.19.0",
"btoa": "^1.2.1",
"cheerio": "^1.0.0-rc.5",
@ -1473,6 +1792,7 @@
"multer": "^1.4.2",
"node-fetch": "^2.6.1",
"supertest": "^6.1.6",
"ts-patch": "^1.4.4",
"typescript": "^4.1.2",
"uuid": "^8.3.2"
}
@ -1490,6 +1810,7 @@
"@types/node-fetch": "^2.5.12",
"@types/uuid": "^8.3.0",
"@types/ws": "^7.4.0",
"@zerollup/ts-transform-paths": "^1.7.18",
"ajv": "^8.5.0",
"amqplib": "^0.8.0",
"dotenv": "^8.2.0",
@ -1499,6 +1820,7 @@
"mongoose-autopopulate": "^0.12.3",
"node-fetch": "^2.6.1",
"ts-node-dev": "^1.1.6",
"ts-patch": "^1.4.4",
"typeorm": "^0.2.37",
"typescript": "^4.2.3",
"uuid": "^8.3.2",
@ -1511,6 +1833,7 @@
"@types/amqplib": "^0.8.1",
"@types/jsonwebtoken": "^8.5.0",
"@types/mongoose-autopopulate": "^0.10.1",
"@types/multer": "^1.4.7",
"@types/node": "^14.17.9",
"@types/node-fetch": "^2.5.12",
"ajv": "^8.6.2",
@ -1522,6 +1845,7 @@
"jsonwebtoken": "^8.5.1",
"lambert-server": "^1.2.10",
"missing-native-js-functions": "^1.2.15",
"multer": "^1.4.3",
"node-fetch": "^2.6.1",
"patch-package": "^6.4.7",
"pg": "^8.7.1",
@ -1813,6 +2137,21 @@
"integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
"dev": true
},
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
@ -1835,6 +2174,12 @@
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
"dev": true
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@ -1858,6 +2203,16 @@
"type-is": "~1.6.17"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"bson": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/bson/-/bson-4.5.2.tgz",
@ -1882,6 +2237,31 @@
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@ -1891,6 +2271,12 @@
"delayed-stream": "~1.0.0"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"content-disposition": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
@ -2042,12 +2428,43 @@
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"glob": {
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"global-prefix": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
"integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
"dev": true,
"requires": {
"ini": "^1.3.5",
"kind-of": "^6.0.2",
"which": "^1.3.1"
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@ -2057,6 +2474,12 @@
"function-bind": "^1.1.1"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"http-errors": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
@ -2092,11 +2515,33 @@
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"dev": true
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
"interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
"dev": true
},
"ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@ -2111,6 +2556,12 @@
"has": "^1.0.3"
}
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
@ -2119,6 +2570,12 @@
"minimist": "^1.2.0"
}
},
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"dev": true
},
"make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@ -2158,6 +2615,15 @@
"mime-db": "1.49.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
@ -2191,11 +2657,26 @@
"ee-first": "1.1.1"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
@ -2237,6 +2718,15 @@
"unpipe": "1.0.0"
}
},
"rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
"dev": true,
"requires": {
"resolve": "^1.1.6"
}
},
"regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
@ -2306,16 +2796,45 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
"shelljs": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
"integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
"dev": true,
"requires": {
"glob": "^7.0.0",
"interpret": "^1.0.0",
"rechoir": "^0.6.2"
}
},
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.0"
}
},
"strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM="
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
@ -2341,6 +2860,21 @@
"yn": "3.1.1"
}
},
"ts-patch": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/ts-patch/-/ts-patch-1.4.4.tgz",
"integrity": "sha512-b0CxxrkrCGsD22gl5BtSFlXzyTFP2mbOVffxMOWRrwdSh37sM01wzxSY4wlbBiHHHAJICmaaDgESzJ8lKkVoZA==",
"dev": true,
"requires": {
"chalk": "^4.1.0",
"glob": "^7.1.7",
"global-prefix": "^3.0.0",
"minimist": "^1.2.5",
"resolve": "^1.20.0",
"shelljs": "^0.8.4",
"strip-ansi": "^6.0.0"
}
},
"tsconfig-paths": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz",
@ -2382,6 +2916,21 @@
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",

View File

@ -4,15 +4,16 @@
"description": "",
"main": "src/start.js",
"scripts": {
"preinstall": "cd ../util && npm i && cd ../api && npm i && cd ../cdn && npm i && cd ../gateway && npm i",
"setup": "cd ../util && npm --production=false i && cd ../api && npm --production=false i && cd ../cdn && npm --production=false i && cd ../gateway && npm --production=false i && npm install && npm run start",
"build": "npm run build:util && npm run build:api && npm run build:cdn && npm run build:gateway && npm run build:bundle",
"postinstall": "ts-patch install -s",
"build:bundle": "npx tsc -b .",
"build:util": "cd ../util/ && npm run build",
"build:api": "cd ../api/ && npm run build",
"build:cdn": "cd ../cdn/ && npm run build",
"build:gateway": "cd ../gateway/ && npm run build",
"start": "npm run build && npm run start:bundle",
"start:bundle": "node -r ./tsconfig-paths-bootstrap.js dist/start.js",
"start:bundle": "node dist/start.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
@ -44,6 +45,7 @@
"@types/ws": "^7.4.0",
"@zerollup/ts-transform-paths": "^1.7.18",
"ts-node": "^10.2.1",
"ts-patch": "^1.4.4",
"typescript": "^4.3.5"
},
"dependencies": {

View File

@ -1,14 +0,0 @@
const tsConfigPaths = require("tsconfig-paths");
const path = require("path");
const cleanup = tsConfigPaths.register({
baseUrl: path.join(__dirname, "node_modules", "@fosscord"),
paths: {
"@fosscord/api": ["api/dist/index.js"],
"@fosscord/api/*": ["api/dist/*"],
"@fosscord/gateway": ["gateway/dist/index.js"],
"@fosscord/gateway/*": ["gateway/dist/*"],
"@fosscord/cdn": ["cdn/dist/index.js"],
"@fosscord/cdn/*": ["cdn/dist/*"],
},
});

226
cdn/package-lock.json generated
View File

@ -7,6 +7,7 @@
"": {
"name": "@fosscord/cdn",
"version": "1.0.0",
"hasInstallScript": true,
"license": "ISC",
"dependencies": {
"@fosscord/util": "file:../util",
@ -44,7 +45,9 @@
"@types/multer": "^1.4.7",
"@types/node": "^14.17.0",
"@types/node-fetch": "^2.5.7",
"@types/uuid": "^8.3.0"
"@types/uuid": "^8.3.0",
"@zerollup/ts-transform-paths": "^1.7.18",
"ts-patch": "^1.4.4"
}
},
"../util": {
@ -61,6 +64,7 @@
"jsonwebtoken": "^8.5.1",
"lambert-server": "^1.2.10",
"missing-native-js-functions": "^1.2.15",
"multer": "^1.4.3",
"node-fetch": "^2.6.1",
"patch-package": "^6.4.7",
"pg": "^8.7.1",
@ -75,6 +79,7 @@
"@types/amqplib": "^0.8.1",
"@types/jsonwebtoken": "^8.5.0",
"@types/mongoose-autopopulate": "^0.10.1",
"@types/multer": "^1.4.7",
"@types/node": "^14.17.9",
"@types/node-fetch": "^2.5.12",
"jest": "^27.0.6"
@ -1281,6 +1286,30 @@
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz",
"integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw=="
},
"node_modules/@zerollup/ts-helpers": {
"version": "1.7.18",
"resolved": "https://registry.npmjs.org/@zerollup/ts-helpers/-/ts-helpers-1.7.18.tgz",
"integrity": "sha512-S9zN+y+i5yN/evfWquzSO3lubqPXIsPQf6p9OiPMpRxDx/0totPLF39XoRw48Dav5dSvbIE8D2eAPpXXJxvKwg==",
"dev": true,
"dependencies": {
"resolve": "^1.12.0"
},
"peerDependencies": {
"typescript": ">=3.7.2"
}
},
"node_modules/@zerollup/ts-transform-paths": {
"version": "1.7.18",
"resolved": "https://registry.npmjs.org/@zerollup/ts-transform-paths/-/ts-transform-paths-1.7.18.tgz",
"integrity": "sha512-YPVUxvWQVzRx1OBN0Pmkd58+R9FcfUJuwTaPUSoi5rKxuXMtxevTXdfi0w5mEaIH8b0DfL+wg0wFDHiJE+S2zA==",
"dev": true,
"dependencies": {
"@zerollup/ts-helpers": "^1.7.18"
},
"peerDependencies": {
"typescript": ">=3.7.2"
}
},
"node_modules/abab": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
@ -2686,6 +2715,32 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/global-prefix": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
"integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
"dev": true,
"dependencies": {
"ini": "^1.3.5",
"kind-of": "^6.0.2",
"which": "^1.3.1"
},
"engines": {
"node": ">=6"
}
},
"node_modules/global-prefix/node_modules/which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dev": true,
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"which": "bin/which"
}
},
"node_modules/globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@ -2942,6 +2997,21 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"node_modules/ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
"node_modules/interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
"dev": true,
"engines": {
"node": ">= 0.10"
}
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@ -3813,6 +3883,15 @@
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz",
"integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ=="
},
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/kleur": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@ -4704,6 +4783,18 @@
"node": ">= 6"
}
},
"node_modules/rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
"dev": true,
"dependencies": {
"resolve": "^1.1.6"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/regexp-clone": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
@ -4885,6 +4976,23 @@
"node": ">=8"
}
},
"node_modules/shelljs": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
"integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
"dev": true,
"dependencies": {
"glob": "^7.0.0",
"interpret": "^1.0.0",
"rechoir": "^0.6.2"
},
"bin": {
"shjs": "bin/shjs"
},
"engines": {
"node": ">=4"
}
},
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@ -5308,6 +5416,27 @@
"node": ">=8"
}
},
"node_modules/ts-patch": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/ts-patch/-/ts-patch-1.4.4.tgz",
"integrity": "sha512-b0CxxrkrCGsD22gl5BtSFlXzyTFP2mbOVffxMOWRrwdSh37sM01wzxSY4wlbBiHHHAJICmaaDgESzJ8lKkVoZA==",
"dev": true,
"dependencies": {
"chalk": "^4.1.0",
"glob": "^7.1.7",
"global-prefix": "^3.0.0",
"minimist": "^1.2.5",
"resolve": "^1.20.0",
"shelljs": "^0.8.4",
"strip-ansi": "^6.0.0"
},
"bin": {
"ts-patch": "bin/cli.js"
},
"peerDependencies": {
"typescript": ">2.7.0"
}
},
"node_modules/tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
@ -6070,6 +6199,7 @@
"@types/amqplib": "^0.8.1",
"@types/jsonwebtoken": "^8.5.0",
"@types/mongoose-autopopulate": "^0.10.1",
"@types/multer": "^1.4.7",
"@types/node": "^14.17.9",
"@types/node-fetch": "^2.5.12",
"ajv": "^8.6.2",
@ -6081,6 +6211,7 @@
"jsonwebtoken": "^8.5.1",
"lambert-server": "^1.2.10",
"missing-native-js-functions": "^1.2.15",
"multer": "^1.4.3",
"node-fetch": "^2.6.1",
"patch-package": "^6.4.7",
"pg": "^8.7.1",
@ -6639,6 +6770,24 @@
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz",
"integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw=="
},
"@zerollup/ts-helpers": {
"version": "1.7.18",
"resolved": "https://registry.npmjs.org/@zerollup/ts-helpers/-/ts-helpers-1.7.18.tgz",
"integrity": "sha512-S9zN+y+i5yN/evfWquzSO3lubqPXIsPQf6p9OiPMpRxDx/0totPLF39XoRw48Dav5dSvbIE8D2eAPpXXJxvKwg==",
"dev": true,
"requires": {
"resolve": "^1.12.0"
}
},
"@zerollup/ts-transform-paths": {
"version": "1.7.18",
"resolved": "https://registry.npmjs.org/@zerollup/ts-transform-paths/-/ts-transform-paths-1.7.18.tgz",
"integrity": "sha512-YPVUxvWQVzRx1OBN0Pmkd58+R9FcfUJuwTaPUSoi5rKxuXMtxevTXdfi0w5mEaIH8b0DfL+wg0wFDHiJE+S2zA==",
"dev": true,
"requires": {
"@zerollup/ts-helpers": "^1.7.18"
}
},
"abab": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
@ -7682,6 +7831,28 @@
"path-is-absolute": "^1.0.0"
}
},
"global-prefix": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
"integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
"dev": true,
"requires": {
"ini": "^1.3.5",
"kind-of": "^6.0.2",
"which": "^1.3.1"
},
"dependencies": {
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
}
}
},
"globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@ -7854,6 +8025,18 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
"interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
"dev": true
},
"ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@ -8516,6 +8699,12 @@
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz",
"integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ=="
},
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"dev": true
},
"kleur": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@ -9147,6 +9336,15 @@
}
}
},
"rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
"dev": true,
"requires": {
"resolve": "^1.1.6"
}
},
"regexp-clone": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
@ -9285,6 +9483,17 @@
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
},
"shelljs": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
"integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
"dev": true,
"requires": {
"glob": "^7.0.0",
"interpret": "^1.0.0",
"rechoir": "^0.6.2"
}
},
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@ -9597,6 +9806,21 @@
"punycode": "^2.1.1"
}
},
"ts-patch": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/ts-patch/-/ts-patch-1.4.4.tgz",
"integrity": "sha512-b0CxxrkrCGsD22gl5BtSFlXzyTFP2mbOVffxMOWRrwdSh37sM01wzxSY4wlbBiHHHAJICmaaDgESzJ8lKkVoZA==",
"dev": true,
"requires": {
"chalk": "^4.1.0",
"glob": "^7.1.7",
"global-prefix": "^3.0.0",
"minimist": "^1.2.5",
"resolve": "^1.20.0",
"shelljs": "^0.8.4",
"strip-ansi": "^6.0.0"
}
},
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",

View File

@ -1,25 +1,26 @@
{
"name": "@fosscord/cdn",
"version": "1.0.0",
"description": "cdn for discord clone",
"description": "cdn for fosscord",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"postinstall": "ts-patch install -s",
"test": "npm run build && jest --coverage ./tests",
"build": "npx tsc -b .",
"start": "npm run build && node -r ./scripts/tsconfig-paths-bootstrap.js dist/start.js"
"start": "npm run build && node dist/start.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/discord-open-source/discord-cdn.git"
"url": "git+https://github.com/fosscord/fosscord-server.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/discord-open-source/discord-cdn/issues"
"url": "https://github.com/fosscord/fosscord-server/issues"
},
"homepage": "https://github.com/discord-open-source/discord-cdn#readme",
"homepage": "https://github.com/fosscord/fosscord-server#readme",
"devDependencies": {
"@types/amqplib": "^0.8.1",
"@types/body-parser": "^1.19.0",
@ -34,7 +35,9 @@
"@types/multer": "^1.4.7",
"@types/node": "^14.17.0",
"@types/node-fetch": "^2.5.7",
"@types/uuid": "^8.3.0"
"@types/uuid": "^8.3.0",
"@zerollup/ts-transform-paths": "^1.7.18",
"ts-patch": "^1.4.4"
},
"dependencies": {
"@fosscord/util": "file:../util",

View File

@ -1,10 +0,0 @@
const tsConfigPaths = require("tsconfig-paths");
const path = require("path");
const cleanup = tsConfigPaths.register({
baseUrl: path.join(__dirname, ".."),
paths: {
"@fosscord/cdn": ["dist/index.js"],
"@fosscord/cdn/*": ["dist/*"],
},
});

View File

@ -68,8 +68,9 @@
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
"baseUrl": ".",
"paths": {
"@fosscord/cdn/": ["src/index.ts"],
"@fosscord/cdn/": ["src/index"],
"@fosscord/cdn/*": ["src/*"]
}
},
"plugins": [{ "transform": "@zerollup/ts-transform-paths" }]
}
}

12512
gateway/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,9 @@
"description": "",
"main": "dist/index.js",
"scripts": {
"postinstall": "ts-patch install -s",
"test": "echo \"Error: no test specified\" && exit 1",
"start": "npm run build && node -r ./scripts/tsconfig-paths-bootstrap.js dist/start.js",
"start": "npm run build && node dist/start.js",
"build": "npx tsc -b .",
"dev": "tsnd --respawn src/start.ts"
},
@ -22,7 +23,9 @@
"@types/node-fetch": "^2.5.12",
"@types/uuid": "^8.3.0",
"@types/ws": "^7.4.0",
"@zerollup/ts-transform-paths": "^1.7.18",
"ts-node-dev": "^1.1.6",
"ts-patch": "^1.4.4",
"typescript": "^4.2.3"
},
"dependencies": {

View File

@ -1,10 +0,0 @@
const tsConfigPaths = require("tsconfig-paths");
const path = require("path");
const cleanup = tsConfigPaths.register({
baseUrl: path.join(__dirname, ".."),
paths: {
"@fosscord/gateway": ["dist/index.js"],
"@fosscord/gateway/*": ["dist/*"],
},
});

View File

@ -1,4 +1,4 @@
import WebSocket from "@fosscord/gateway/util/WebSocket";
import { WebSocket } from "@fosscord/gateway";
import { Message } from "./Message";
import { Session } from "@fosscord/util";

View File

@ -1,11 +1,14 @@
import WS from "ws";
import WebSocket from "@fosscord/gateway/util/WebSocket";
import {
setHeartbeat,
Send,
CLOSECODES,
OPCODES,
WebSocket,
} from "@fosscord/gateway";
import { IncomingMessage } from "http";
import { Close } from "./Close";
import { Message } from "./Message";
import { setHeartbeat } from "@fosscord/gateway/util/setHeartbeat";
import { Send } from "@fosscord/gateway/util/Send";
import { CLOSECODES, OPCODES } from "@fosscord/gateway/util/Constants";
import { createDeflate } from "zlib";
import { URL } from "url";
import { Session } from "@fosscord/util";

View File

@ -1,10 +1,9 @@
import WebSocket from "@fosscord/gateway/util/WebSocket";
import { WebSocket, Payload, CLOSECODES, OPCODES } from "@fosscord/gateway";
var erlpack: any;
try {
erlpack = require("@yukikaze-bot/erlpack");
} catch (error) {}
import OPCodeHandlers from "../opcodes";
import { Payload, CLOSECODES, OPCODES } from "@fosscord/gateway/util/Constants";
import { instanceOf, Tuple } from "lambert-server";
import { check } from "../opcodes/instanceOf";
import WS from "ws";

View File

@ -9,12 +9,9 @@ import {
ListenEventOpts,
Member,
} from "@fosscord/util";
import { OPCODES } from "@fosscord/gateway/util/Constants";
import { Send } from "@fosscord/gateway/util/Send";
import WebSocket from "@fosscord/gateway/util/WebSocket";
import { OPCODES, WebSocket, Send } from "@fosscord/gateway";
import "missing-native-js-functions";
import { Channel as AMQChannel } from "amqplib";
import { In, Like } from "typeorm";
import { Recipient } from "@fosscord/util";
// TODO: close connection on Invalidated Token
@ -116,7 +113,7 @@ async function consume(this: WebSocket, opts: EventOpts) {
.has("VIEW_CHANNEL")
)
return;
//No break needed here, we need to call the listenEvent function below
//No break needed here, we need to call the listenEvent function below
case "GUILD_CREATE":
this.events[id] = await listenEvent(id, consumer, listenOpts);
break;

View File

@ -1,7 +1,4 @@
import { CLOSECODES, Payload } from "@fosscord/gateway/util/Constants";
import { Send } from "@fosscord/gateway/util/Send";
import { setHeartbeat } from "@fosscord/gateway/util/setHeartbeat";
import WebSocket from "@fosscord/gateway/util/WebSocket";
import { Payload, Send, setHeartbeat, WebSocket } from "@fosscord/gateway";
export async function onHeartbeat(this: WebSocket, data: Payload) {
// TODO: validate payload

View File

@ -1,5 +1,10 @@
import { CLOSECODES, Payload, OPCODES } from "@fosscord/gateway/util/Constants";
import WebSocket from "@fosscord/gateway/util/WebSocket";
import {
WebSocket,
CLOSECODES,
Payload,
OPCODES,
genSessionId,
} from "@fosscord/gateway";
import {
Channel,
checkToken,
@ -24,7 +29,6 @@ import { Send } from "@fosscord/gateway/util/Send";
const experiments: any = [];
import { check } from "./instanceOf";
import { Recipient } from "@fosscord/util";
import { genSessionId } from "@fosscord/gateway/util/SessionUtils";
// TODO: bot sharding
// TODO: check priviliged intents
@ -98,7 +102,9 @@ export async function onIdentify(this: WebSocket, data: Payload) {
//TODO is this needed? check if users in group dm that are not friends are sent in the READY event
//users = users.concat(x.channel.recipients);
if (x.channel.isDm()) {
x.channel.recipients = x.channel.recipients!.filter((x) => x.id !== this.user_id);
x.channel.recipients = x.channel.recipients!.filter(
(x) => x.id !== this.user_id
);
}
return x.channel;
});
@ -109,7 +115,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
if (!user) return this.close(CLOSECODES.Authentication_failed);
for (let relation of user.relationships) {
const related_user = relation.to
const related_user = relation.to;
const public_related_user = {
username: related_user.username,
discriminator: related_user.discriminator,

View File

@ -2,13 +2,10 @@ import {
getPermission,
Member,
PublicMemberProjection,
PublicUserProjection,
Role,
} from "@fosscord/util";
import { LazyRequest } from "../schema/LazyRequest";
import { OPCODES, Payload } from "@fosscord/gateway/util/Constants";
import { Send } from "@fosscord/gateway/util/Send";
import WebSocket from "@fosscord/gateway/util/WebSocket";
import { WebSocket, Send, OPCODES, Payload } from "@fosscord/gateway";
import { check } from "./instanceOf";
import "missing-native-js-functions";

View File

@ -1,5 +1,4 @@
import { CLOSECODES, Payload } from "@fosscord/gateway/util/Constants";
import WebSocket from "@fosscord/gateway/util/WebSocket";
import { WebSocket, Payload } from "@fosscord/gateway";
export function onPresenceUpdate(this: WebSocket, data: Payload) {
// return this.close(CLOSECODES.Unknown_error);

View File

@ -1,6 +1,4 @@
import { CLOSECODES, Payload } from "@fosscord/gateway/util/Constants";
import WebSocket from "@fosscord/gateway/util/WebSocket";
import { Payload, WebSocket } from "@fosscord/gateway";
export function onRequestGuildMembers(this: WebSocket, data: Payload) {
// return this.close(CLOSECODES.Unknown_error);

View File

@ -1,7 +1,4 @@
import { CLOSECODES, Payload } from "@fosscord/gateway/util/Constants";
import { Send } from "@fosscord/gateway/util/Send";
import WebSocket from "@fosscord/gateway/util/WebSocket";
import { WebSocket, Payload, Send } from "@fosscord/gateway";
export async function onResume(this: WebSocket, data: Payload) {
console.log("Got Resume -> cancel not implemented");

View File

@ -1,6 +1,5 @@
import { VoiceStateUpdateSchema } from "../schema/VoiceStateUpdateSchema";
import { Payload } from "@fosscord/gateway/util/Constants";
import WebSocket from "@fosscord/gateway/util/WebSocket";
import { Payload, WebSocket, genVoiceToken } from "@fosscord/gateway";
import { check } from "./instanceOf";
import {
Config,
@ -12,7 +11,6 @@ import {
VoiceState,
VoiceStateUpdateEvent,
} from "@fosscord/util";
import { genVoiceToken } from "@fosscord/gateway/util/SessionUtils";
// TODO: check if a voice server is setup
// Notice: Bot users respect the voice channel's user limit, if set. When the voice channel is full, you will not receive the Voice State Update or Voice Server Update events in response to your own Voice State Update. Having MANAGE_CHANNELS permission bypasses this limit and allows you to join regardless of the channel being full or not.

View File

@ -1,5 +1,4 @@
import { Payload } from "@fosscord/gateway/util/Constants";
import WebSocket from "@fosscord/gateway/util/WebSocket";
import { WebSocket, Payload } from "@fosscord/gateway";
import { onHeartbeat } from "./Heartbeat";
import { onIdentify } from "./Identify";
import { onLazyRequest } from "./LazyRequest";

View File

@ -1,6 +1,5 @@
import { instanceOf } from "lambert-server";
import { CLOSECODES } from "@fosscord/gateway/util/Constants";
import WebSocket from "@fosscord/gateway/util/WebSocket";
import { WebSocket, CLOSECODES } from "@fosscord/gateway";
export function check(this: WebSocket, schema: any, data: any) {
try {

View File

@ -2,9 +2,7 @@ var erlpack: any;
try {
erlpack = require("@yukikaze-bot/erlpack");
} catch (error) {}
import { Payload } from "@fosscord/gateway/util/Constants";
import WebSocket from "./WebSocket";
import { Payload, WebSocket } from "@fosscord/gateway";
export async function Send(socket: WebSocket, data: Payload) {
let buffer: Buffer | string;
@ -20,7 +18,7 @@ export async function Send(socket: WebSocket, data: Payload) {
}
return new Promise((res, rej) => {
socket.send(buffer, (err) => {
socket.send(buffer, (err: any) => {
if (err) return rej(err);
return res(null);
});

View File

@ -3,7 +3,7 @@ import WS from "ws";
import { Deflate } from "zlib";
import { Channel } from "amqplib";
interface WebSocket extends WS {
export interface WebSocket extends WS {
version: number;
user_id: string;
session_id: string;
@ -19,5 +19,3 @@ interface WebSocket extends WS {
permissions: Record<string, Permissions>;
events: Record<string, Function>;
}
export default WebSocket;

View File

@ -1,5 +1,5 @@
import { CLOSECODES } from "./Constants";
import WebSocket from "./WebSocket";
import { WebSocket } from "./WebSocket";
// TODO: make heartbeat timeout configurable
export function setHeartbeat(socket: WebSocket) {

View File

@ -70,8 +70,10 @@
"resolveJsonModule": true,
"baseUrl": ".",
"paths": {
"@fosscord/gateway": ["src/index"],
"@fosscord/gateway/*": ["src/*"],
"@fosscord/util/*": ["../util/src/*"]
}
},
"plugins": [{ "transform": "@zerollup/ts-transform-paths" }]
}
}

View File

@ -12,19 +12,19 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/fosscord/fosscord-server-util.git"
"url": "git+https://github.com/fosscord/fosscord-server.git"
},
"keywords": [
"discord",
"fosscord",
"fosscord-server-util",
"fosscord-server",
"discord open source",
"discord-open-source"
],
"author": "Fosscord",
"license": "GPLV3",
"bugs": {
"url": "https://github.com/fosscord/fosscord-server-util/issues"
"url": "https://github.com/fosscord/fosscord-server/issues"
},
"homepage": "https://docs.fosscord.com/",
"devDependencies": {

View File

@ -77,6 +77,7 @@ export interface ConfigValue {
maxWebhooks: number;
};
rate: {
disabled: boolean;
ip: Omit<RateLimitOptions, "bot_count">;
global: RateLimitOptions;
error: RateLimitOptions;
@ -188,6 +189,7 @@ export const DefaultConfigOptions: ConfigValue = {
maxWebhooks: 10,
},
rate: {
disabled: true,
ip: {
count: 500,
window: 5,

View File

@ -161,15 +161,13 @@ export class User extends BaseClass {
}
static async getPublicUser(user_id: string, opts?: FindOneOptions<User>) {
const user = await User.findOne(
return await User.findOneOrFail(
{ id: user_id },
{
...opts,
select: [...PublicUserProjection, ...(opts?.select || [])],
}
);
if (!user) throw new HTTPError("User not found", 404);
return user;
}
}

View File

@ -14,7 +14,7 @@ export const Config = {
get: function get() {
return config.value as ConfigValue;
},
set: function set(val: any) {
set: function set(val: Partial<ConfigValue>) {
if (!config) return;
config.value = val.merge(config?.value || {});
return config.save();

View File

@ -1,3 +1,4 @@
import path from "path";
import "reflect-metadata";
import { Connection, createConnection, ValueTransformer } from "typeorm";
import * as Models from "../entities";
@ -15,7 +16,7 @@ export function initDatabase() {
// @ts-ignore
promise = createConnection({
type: "sqlite",
database: "database.db",
database: path.join(process.cwd(), "database.db"),
// type: "postgres",
// url: "postgres://fosscord:wb94SmuURM2Syv&@localhost/fosscord",
//

20
util/src/util/Email.ts Normal file
View File

@ -0,0 +1,20 @@
export const EMAIL_REGEX =
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
export function adjustEmail(email: string): string | undefined {
if (!email) return email;
// body parser already checked if it is a valid email
const parts = <RegExpMatchArray>email.match(EMAIL_REGEX);
// @ts-ignore
if (!parts || parts.length < 5) return undefined;
const domain = parts[5];
const user = parts[1];
// TODO: check accounts with uncommon email domains
if (domain === "gmail.com" || domain === "googlemail.com") {
// replace .dots and +alternatives -> Gmail Dot Trick https://support.google.com/mail/answer/7436150 and https://generator.email/blog/gmail-generator
return user.replace(/[.]|(\+.*)/g, "") + "@gmail.com";
}
return email;
}

View File

@ -2,7 +2,7 @@ import { Channel } from "amqplib";
import { RabbitMQ } from "./RabbitMQ";
import EventEmitter from "events";
import { EVENT, Event } from "../interfaces";
const events = new EventEmitter();
export const events = new EventEmitter();
export async function emitEvent(payload: Omit<Event, "created_at">) {
const id = (payload.channel_id || payload.user_id || payload.guild_id) as string;

View File

@ -1,4 +1,5 @@
import jwt, { VerifyOptions } from "jsonwebtoken";
import { Config } from "./Config";
import { User } from "../entities";
export const JWTOptions: VerifyOptions = { algorithms: ["HS256"] };
@ -21,3 +22,22 @@ export function checkToken(token: string, jwtSecret: string): Promise<any> {
});
});
}
export async function generateToken(id: string) {
const iat = Math.floor(Date.now() / 1000);
const algorithm = "HS256";
return new Promise((res, rej) => {
jwt.sign(
{ id: id, iat },
Config.get().security.jwtSecret,
{
algorithm,
},
(err, token) => {
if (err) return rej(err);
return res(token);
}
);
});
}

View File

@ -1,11 +1,12 @@
export * from "./ApiError";
export * from "./BitField";
export * from "./checkToken";
export * from "./Token";
export * from "./cdn";
export * from "./Config";
export * from "./Constants";
export * from "./Database";
export * from "./Event";
export * from "./Email";
export * from "./Intents";
export * from "./MessageFlags";
export * from "./Permissions";

View File

@ -68,12 +68,6 @@
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"plugins": [
{
"transform": "ts-transform-json-schema",
"type": "program"
}
]
"resolveJsonModule": true
}
}