diff --git a/bundle/src/Server.ts b/src/Server.ts
index 71a60d49..4d5d6422 100644
--- a/bundle/src/Server.ts
+++ b/src/Server.ts
@@ -7,9 +7,10 @@ import * as Gateway from "@fosscord/gateway";
import { CDNServer } from "@fosscord/cdn";
import express from "express";
import { green, bold, yellow } from "picocolors";
-import { Config, initDatabase } from "@fosscord/util";
+import { Config, getOrInitialiseDatabase } from "@fosscord/util";
import * as Sentry from "@sentry/node";
import * as Tracing from "@sentry/tracing";
+// import { PluginLoader } from "@fosscord/util";
const app = express();
const server = http.createServer();
@@ -26,6 +27,7 @@ const gateway = new Gateway.Server({ server, port, production });
//this is what has been added for the /stop API route
process.on('SIGTERM', () => {
+ setTimeout(()=>process.exit(0), 3000)
server.close(() => {
console.log("Stop API has been successfully POSTed, SIGTERM sent")
})
@@ -34,7 +36,7 @@ process.on('SIGTERM', () => {
async function main() {
server.listen(port);
- await initDatabase();
+ await getOrInitialiseDatabase();
await Config.init();
// only set endpointPublic, if not already set
await Config.set({
@@ -93,6 +95,7 @@ async function main() {
});
}
console.log(`[Server] ${green(`listening on port ${bold(port)}`)}`);
+ // PluginLoader.loadPlugins();
}
main().catch(console.error);
diff --git a/api/src/Server.ts b/src/api/Server.ts
index 4cf0917d..136f9814 100644
--- a/api/src/Server.ts
+++ b/src/api/Server.ts
@@ -1,7 +1,6 @@
-import "missing-native-js-functions";
import { Server, ServerOptions } from "lambert-server";
import { Authentication, CORS } from "./middlewares/";
-import { Config, initDatabase, initEvent } from "@fosscord/util";
+import { Config, getOrInitialiseDatabase, initEvent, registerRoutes } from "@fosscord/util";
import { ErrorHandler } from "./middlewares/ErrorHandler";
import { BodyParser } from "./middlewares/BodyParser";
import { Router, Request, Response, NextFunction } from "express";
@@ -11,7 +10,6 @@ import TestClient from "./middlewares/TestClient";
import { initTranslation } from "./middlewares/Translation";
import morgan from "morgan";
import { initInstance } from "./util/handlers/Instance";
-import { registerRoutes } from "@fosscord/util";
import { red } from "picocolors"
export interface FosscordServerOptions extends ServerOptions {}
@@ -34,7 +32,7 @@ export class FosscordServer extends Server {
}
async start() {
- await initDatabase();
+ await getOrInitialiseDatabase();
await Config.init();
await initEvent();
await initInstance();
@@ -44,13 +42,13 @@ export class FosscordServer extends Server {
this.app.use(
morgan("combined", {
skip: (req, res) => {
- var skip = !(process.env["LOG_REQUESTS"]?.includes(res.statusCode.toString()) ?? false);
+ let skip = !(process.env["LOG_REQUESTS"]?.includes(res.statusCode.toString()) ?? false);
if (process.env["LOG_REQUESTS"]?.charAt(0) == "-") skip = !skip;
return skip;
}
})
);
- };
+ }
this.app.use(CORS);
this.app.use(BodyParser({ inflate: true, limit: "10mb" }));
@@ -91,4 +89,4 @@ export class FosscordServer extends Server {
return super.start();
}
-};
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/api/src/global.d.ts b/src/api/global.d.ts
index 7751af8f..7751af8f 100644
--- a/api/src/global.d.ts
+++ b/src/api/global.d.ts
diff --git a/api/src/index.ts b/src/api/index.ts
index adc7649c..adc7649c 100644
--- a/api/src/index.ts
+++ b/src/api/index.ts
diff --git a/api/src/middlewares/Authentication.ts b/src/api/middlewares/Authentication.ts
index 1df7911b..2d9ccf57 100644
--- a/api/src/middlewares/Authentication.ts
+++ b/src/api/middlewares/Authentication.ts
@@ -1,5 +1,5 @@
import { NextFunction, Request, Response } from "express";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { checkToken, Config, Rights } from "@fosscord/util";
export const NO_AUTHORIZATION_ROUTES = [
diff --git a/api/src/middlewares/BodyParser.ts b/src/api/middlewares/BodyParser.ts
index 4cb376bc..35db3c6f 100644
--- a/api/src/middlewares/BodyParser.ts
+++ b/src/api/middlewares/BodyParser.ts
@@ -1,6 +1,6 @@
import bodyParser, { OptionsJson } from "body-parser";
import { NextFunction, Request, Response } from "express";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
export function BodyParser(opts?: OptionsJson) {
const jsonParser = bodyParser.json(opts);
diff --git a/api/src/middlewares/CORS.ts b/src/api/middlewares/CORS.ts
index 20260cf9..20260cf9 100644
--- a/api/src/middlewares/CORS.ts
+++ b/src/api/middlewares/CORS.ts
diff --git a/api/src/middlewares/ErrorHandler.ts b/src/api/middlewares/ErrorHandler.ts
index 2012b91c..8a046e06 100644
--- a/api/src/middlewares/ErrorHandler.ts
+++ b/src/api/middlewares/ErrorHandler.ts
@@ -1,5 +1,5 @@
import { NextFunction, Request, Response } from "express";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { ApiError, FieldError } from "@fosscord/util";
const EntityNotFoundErrorRegex = /"(\w+)"/;
diff --git a/api/src/middlewares/RateLimit.ts b/src/api/middlewares/RateLimit.ts
index 13f1602c..47180b62 100644
--- a/api/src/middlewares/RateLimit.ts
+++ b/src/api/middlewares/RateLimit.ts
@@ -28,7 +28,7 @@ type RateLimit = {
expires_at: Date;
};
-var Cache = new Map<string, RateLimit>();
+let Cache = new Map<string, RateLimit>();
const EventRateLimit = "RATELIMIT";
export default function rateLimit(opts: {
@@ -52,10 +52,10 @@ export default function rateLimit(opts: {
}
const bucket_id = opts.bucket || req.originalUrl.replace(API_PREFIX_TRAILING_SLASH, "");
- var executor_id = getIpAdress(req);
+ let executor_id = getIpAdress(req);
if (!opts.onlyIp && req.user_id) executor_id = req.user_id;
- var max_hits = opts.count;
+ let max_hits = opts.count;
if (opts.bot && req.user_bot) max_hits = opts.bot;
if (opts.GET && ["GET", "OPTIONS", "HEAD"].includes(req.method)) max_hits = opts.GET;
else if (opts.MODIFY && ["POST", "DELETE", "PATCH", "PUT"].includes(req.method)) max_hits = opts.MODIFY;
@@ -165,7 +165,7 @@ export async function initRateLimits(app: Router) {
async function hitRoute(opts: { executor_id: string; bucket_id: string; max_hits: number; window: number; }) {
const id = opts.executor_id + opts.bucket_id;
- var limit = Cache.get(id);
+ let limit = Cache.get(id);
if (!limit) {
limit = {
id: opts.bucket_id,
@@ -183,7 +183,7 @@ async function hitRoute(opts: { executor_id: string; bucket_id: string; max_hits
}
/*
- var ratelimit = await RateLimit.findOne({ id: opts.bucket_id, executor_id: opts.executor_id });
+ let ratelimit = await RateLimit.findOne({ where: { id: opts.bucket_id, executor_id: opts.executor_id } });
if (!ratelimit) {
ratelimit = new RateLimit({
id: opts.bucket_id,
diff --git a/api/src/middlewares/TestClient.ts b/src/api/middlewares/TestClient.ts
index 7292868c..c8ea57f6 100644
--- a/api/src/middlewares/TestClient.ts
+++ b/src/api/middlewares/TestClient.ts
@@ -1,17 +1,19 @@
import express, { Request, Response, Application } from "express";
-import fs, { writeFile } from "fs";
+import fs from "fs";
import path from "path";
import fetch, { Response as FetchResponse, Headers } from "node-fetch";
import ProxyAgent from 'proxy-agent';
import { Config } from "@fosscord/util";
import { AssetCacheItem } from "../util/entities/AssetCacheItem"
-import { FileLogger } from "typeorm";
+import { green } from "picocolors";
+
+const AssetsPath = path.join(__dirname, "..", "..", "..", "assets")
export default function TestClient(app: Application) {
const agent = new ProxyAgent();
//build client page
- let html = fs.readFileSync(path.join(__dirname, "..", "..", "client_test", "index.html"), { encoding: "utf8" });
+ let html = fs.readFileSync(path.join(AssetsPath, "index.html"), { encoding: "utf8" });
html = applyEnv(html);
html = applyInlinePlugins(html);
html = applyPlugins(html);
@@ -19,15 +21,20 @@ export default function TestClient(app: Application) {
//load asset cache
let newAssetCache: Map<string, AssetCacheItem> = new Map<string, AssetCacheItem>();
- if(!fs.existsSync(path.join(__dirname, "..", "..", "assets", "cache"))) {
- fs.mkdirSync(path.join(__dirname, "..", "..", "assets", "cache"));
+ let assetCacheDir = path.join(AssetsPath, "cache");
+ if(process.env.ASSET_CACHE_DIR)
+ assetCacheDir = process.env.ASSET_CACHE_DIR
+
+ console.log(`[TestClient] ${green(`Using asset cache path: ${assetCacheDir}`)}`)
+ if(!fs.existsSync(assetCacheDir)) {
+ fs.mkdirSync(assetCacheDir);
}
- if(fs.existsSync(path.join(__dirname, "..", "..", "assets", "cache", "index.json"))) {
- let rawdata = fs.readFileSync(path.join(__dirname, "..", "..", "assets", "cache", "index.json"));
+ if(fs.existsSync(path.join(assetCacheDir, "index.json"))) {
+ let rawdata = fs.readFileSync(path.join(assetCacheDir, "index.json"));
newAssetCache = new Map<string, AssetCacheItem>(Object.entries(JSON.parse(rawdata.toString())));
}
- app.use("/assets", express.static(path.join(__dirname, "..", "..", "assets")));
+ app.use("/assets", express.static(path.join(AssetsPath)));
app.get("/assets/:file", async (req: Request, res: Response) => {
delete req.headers.host;
let response: FetchResponse;
@@ -40,7 +47,7 @@ export default function TestClient(app: Application) {
});
}
else {
- console.log(`CACHE MISS! Asset file: ${req.params.file}`);
+ console.log(`[TestClient] Downloading file not yet cached! Asset file: ${req.params.file}`);
response = await fetch(`https://discord.com/assets/${req.params.file}`, {
agent,
// @ts-ignore
@@ -51,11 +58,11 @@ export default function TestClient(app: Application) {
//set cache info
assetCacheItem.Headers = Object.fromEntries(stripHeaders(response.headers));
- assetCacheItem.FilePath = path.join(__dirname, "..", "..", "assets", "cache", req.params.file);
+ assetCacheItem.FilePath = path.join(assetCacheDir, req.params.file);
assetCacheItem.Key = req.params.file;
//add to cache and save
newAssetCache.set(req.params.file, assetCacheItem);
- fs.writeFileSync(path.join(__dirname, "..", "..", "assets", "cache", "index.json"), JSON.stringify(Object.fromEntries(newAssetCache), null, 4));
+ fs.writeFileSync(path.join(assetCacheDir, "index.json"), JSON.stringify(Object.fromEntries(newAssetCache), null, 4));
//download file
fs.writeFileSync(assetCacheItem.FilePath, await response.buffer());
}
@@ -72,7 +79,7 @@ export default function TestClient(app: Application) {
if(!useTestClient) return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance.")
- res.send(fs.readFileSync(path.join(__dirname, "..", "..", "client_test", "developers.html"), { encoding: "utf8" }));
+ res.send(fs.readFileSync(path.join(__dirname, "..", "..", "..", "assets", "developers.html"), { encoding: "utf8" }));
});
app.get("*", (req: Request, res: Response) => {
const { useTestClient } = Config.get().client;
@@ -108,7 +115,7 @@ function applyEnv(html: string): string {
function applyPlugins(html: string): string {
// plugins
- let files = fs.readdirSync(path.join(__dirname, "..", "..", "assets", "plugins"));
+ let files = fs.readdirSync(path.join(AssetsPath, "plugins"));
let plugins = "";
files.forEach(x =>{if(x.endsWith(".js")) plugins += `<script src='/assets/plugins/${x}'></script>\n`; });
return html.replaceAll("<!-- plugin marker -->", plugins);
@@ -116,7 +123,7 @@ function applyPlugins(html: string): string {
function applyInlinePlugins(html: string): string{
// inline plugins
- let files = fs.readdirSync(path.join(__dirname, "..", "..", "assets", "inline-plugins"));
+ let files = fs.readdirSync(path.join(AssetsPath, "inline-plugins"));
let plugins = "";
files.forEach(x =>{if(x.endsWith(".js")) plugins += `<script src='/assets/inline-plugins/${x}'></script>\n\n`; });
return html.replaceAll("<!-- inline plugin marker -->", plugins);
@@ -124,9 +131,9 @@ function applyInlinePlugins(html: string): string{
function applyPreloadPlugins(html: string): string{
//preload plugins
- let files = fs.readdirSync(path.join(__dirname, "..", "..", "assets", "preload-plugins"));
+ let files = fs.readdirSync(path.join(AssetsPath, "preload-plugins"));
let plugins = "";
- files.forEach(x =>{if(x.endsWith(".js")) plugins += `<script>${fs.readFileSync(path.join(__dirname, "..", "..", "assets", "preload-plugins", x))}</script>\n`; });
+ files.forEach(x =>{if(x.endsWith(".js")) plugins += `<script>${fs.readFileSync(path.join(AssetsPath, "preload-plugins", x))}</script>\n`; });
return html.replaceAll("<!-- preload plugin marker -->", plugins);
}
@@ -144,4 +151,4 @@ function stripHeaders(headers: Headers): Headers {
headers.delete(headerName);
});
return headers;
-}
\ No newline at end of file
+}
diff --git a/api/src/middlewares/Translation.ts b/src/api/middlewares/Translation.ts
index baabf221..64b03bf8 100644
--- a/api/src/middlewares/Translation.ts
+++ b/src/api/middlewares/Translation.ts
@@ -6,8 +6,8 @@ import i18nextBackend from "i18next-node-fs-backend";
import { Router } from "express";
export async function initTranslation(router: Router) {
- const languages = fs.readdirSync(path.join(__dirname, "..", "..", "locales"));
- const namespaces = fs.readdirSync(path.join(__dirname, "..", "..", "locales", "en"));
+ const languages = fs.readdirSync(path.join(__dirname, "..", "..", "..", "assets", "locales"));
+ const namespaces = fs.readdirSync(path.join(__dirname, "..", "..", "..", "assets", "locales", "en"));
const ns = namespaces.filter((x) => x.endsWith(".json")).map((x) => x.slice(0, x.length - 5));
await i18next
@@ -19,7 +19,7 @@ export async function initTranslation(router: Router) {
fallbackLng: "en",
ns,
backend: {
- loadPath: __dirname + "/../../locales/{{lng}}/{{ns}}.json"
+ loadPath: __dirname + "/../../../assets/locales/{{lng}}/{{ns}}.json"
},
load: "all"
});
diff --git a/api/src/middlewares/index.ts b/src/api/middlewares/index.ts
index f0c50dbe..f0c50dbe 100644
--- a/api/src/middlewares/index.ts
+++ b/src/api/middlewares/index.ts
diff --git a/api/src/routes/-/healthz.ts b/src/api/routes/-/healthz.ts
index f7bcfebf..f7bcfebf 100644
--- a/api/src/routes/-/healthz.ts
+++ b/src/api/routes/-/healthz.ts
diff --git a/api/src/routes/-/readyz.ts b/src/api/routes/-/readyz.ts
index f7bcfebf..f7bcfebf 100644
--- a/api/src/routes/-/readyz.ts
+++ b/src/api/routes/-/readyz.ts
diff --git a/src/api/routes/applications/#id/bot/index.ts b/src/api/routes/applications/#id/bot/index.ts
new file mode 100644
index 00000000..5cae5215
--- /dev/null
+++ b/src/api/routes/applications/#id/bot/index.ts
@@ -0,0 +1,83 @@
+import { Request, Response, Router } from "express";
+import { route } from "@fosscord/api";
+import { Application, Config, FieldErrors, generateToken, OrmUtils, Snowflake, trimSpecial, User, handleFile } from "@fosscord/util";
+import { HTTPError } from "lambert-server";
+import { verifyToken } from "node-2fa";
+
+const router: Router = Router();
+
+router.post("/", route({}), async (req: Request, res: Response) => {
+ const app = await Application.findOne({where: {id: req.params.id}});
+ if(!app) return res.status(404);
+ const username = trimSpecial(app.name);
+ const discriminator = await User.generateDiscriminator(username);
+ if (!discriminator) {
+ // We've failed to generate a valid and unused discriminator
+ throw FieldErrors({
+ username: {
+ code: "USERNAME_TOO_MANY_USERS",
+ message: req?.t("auth:register.USERNAME_TOO_MANY_USERS"),
+ },
+ });
+ }
+
+ const user = OrmUtils.mergeDeep(new User(), {
+ created_at: new Date(),
+ username: username,
+ discriminator,
+ id: app.id,
+ bot: true,
+ system: false,
+ premium_since: null,
+ desktop: false,
+ mobile: false,
+ premium: false,
+ premium_type: 0,
+ bio: app.description,
+ mfa_enabled: true,
+ totp_secret: "",
+ totp_backup_codes: [],
+ verified: true,
+ disabled: false,
+ deleted: false,
+ email: null,
+ rights: Config.get().register.defaultRights,
+ nsfw_allowed: true,
+ public_flags: "0",
+ flags: "0",
+ data: {
+ hash: null,
+ valid_tokens_since: new Date(),
+ },
+ settings: {},
+ extended_settings: {},
+ fingerprints: [],
+ notes: {},
+ });
+ await user.save();
+ app.bot = user;
+ await app.save();
+ res.send().status(204)
+});
+
+router.post("/reset", route({}), async (req: Request, res: Response) => {
+ let bot = await User.findOne({where: {id: req.params.id}});
+ let owner = await User.findOne({where: {id: req.user_id}});
+ if(!bot) return res.status(404);
+ if(owner?.totp_secret && (!req.body.code || verifyToken(owner.totp_secret, req.body.code))) {
+ throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+ }
+ bot.data = { hash: undefined, valid_tokens_since: new Date() };
+ await bot.save();
+ let token = await generateToken(bot.id);
+ res.json({token}).status(200);
+});
+
+router.patch("/", route({}), async (req: Request, res: Response) => {
+ if (req.body.avatar) req.body.avatar = await handleFile(`/avatars/${req.params.id}`, req.body.avatar as string);
+ let app = OrmUtils.mergeDeep(await User.findOne({where: {id: req.params.id}}), req.body);
+ await app.save();
+ res.json(app).status(200);
+});
+
+export default router;
\ No newline at end of file
diff --git a/api/src/routes/applications/#id/entitlements.ts b/src/api/routes/applications/#id/entitlements.ts
index cfcfe40f..cfcfe40f 100644
--- a/api/src/routes/applications/#id/entitlements.ts
+++ b/src/api/routes/applications/#id/entitlements.ts
diff --git a/src/api/routes/applications/#id/index.ts b/src/api/routes/applications/#id/index.ts
new file mode 100644
index 00000000..0aced582
--- /dev/null
+++ b/src/api/routes/applications/#id/index.ts
@@ -0,0 +1,30 @@
+import { Request, Response, Router } from "express";
+import { route } from "@fosscord/api";
+import { Application, OrmUtils, Team, trimSpecial, User } from "@fosscord/util";
+
+const router: Router = Router();
+
+router.get("/", route({}), async (req: Request, res: Response) => {
+ let results = await Application.findOne({where: {id: req.params.id}, relations: ["owner", "bot"] });
+ res.json(results).status(200);
+});
+
+router.patch("/", route({}), async (req: Request, res: Response) => {
+ delete req.body.icon;
+ let app = OrmUtils.mergeDeep(await Application.findOne({where: {id: req.params.id}, relations: ["owner", "bot"]}), req.body);
+ if(app.bot) {
+ app.bot.bio = req.body.description
+ app.bot?.save();
+ }
+ if(req.body.tags) app.tags = req.body.tags;
+ await app.save();
+ res.json(app).status(200);
+});
+
+router.post("/delete", route({}), async (req: Request, res: Response) => {
+ await Application.delete(req.params.id);
+ res.send().status(200);
+});
+
+
+export default router;
\ No newline at end of file
diff --git a/api/src/routes/applications/index.ts b/src/api/routes/applications/#id/skus.ts
index 28ce42da..5b667f36 100644
--- a/api/src/routes/applications/index.ts
+++ b/src/api/routes/applications/#id/skus.ts
@@ -1,11 +1,11 @@
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
+import { Application, OrmUtils, Team, trimSpecial, User } from "@fosscord/util";
const router: Router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
- //TODO
- res.send([]).status(200);
+ res.json([]).status(200);
});
-export default router;
+export default router;
\ No newline at end of file
diff --git a/api/src/routes/applications/detectable.ts b/src/api/routes/applications/detectable.ts
index 28ce42da..28ce42da 100644
--- a/api/src/routes/applications/detectable.ts
+++ b/src/api/routes/applications/detectable.ts
diff --git a/src/api/routes/applications/index.ts b/src/api/routes/applications/index.ts
new file mode 100644
index 00000000..033dcc51
--- /dev/null
+++ b/src/api/routes/applications/index.ts
@@ -0,0 +1,34 @@
+import { Request, Response, Router } from "express";
+import { route } from "@fosscord/api";
+import { Application, OrmUtils, Team, trimSpecial, User } from "@fosscord/util";
+
+const router: Router = Router();
+
+export interface ApplicationCreateSchema {
+ name: string;
+ team_id?: string | number;
+}
+
+router.get("/", route({}), async (req: Request, res: Response) => {
+ //TODO
+ let results = await Application.find({where: {owner: {id: req.user_id}}, relations: ["owner", "bot"] });
+ res.json(results).status(200);
+});
+
+router.post("/", route({}), async (req: Request, res: Response) => {
+ const body = req.body as ApplicationCreateSchema;
+ const user = await User.findOne({where: {id: req.user_id}})
+ if(!user) res.status(420);
+ let app = OrmUtils.mergeDeep(new Application(), {
+ name: trimSpecial(body.name),
+ description: "",
+ bot_public: true,
+ owner: user,
+ verify_key: "IMPLEMENTME",
+ flags: 0
+ });
+ await app.save();
+ res.json(app).status(200);
+});
+
+export default router;
\ No newline at end of file
diff --git a/api/src/routes/auth/location-metadata.ts b/src/api/routes/auth/location-metadata.ts
index f4c2bd16..f4c2bd16 100644
--- a/api/src/routes/auth/location-metadata.ts
+++ b/src/api/routes/auth/location-metadata.ts
diff --git a/api/src/routes/auth/login.ts b/src/api/routes/auth/login.ts
index 80e5c4e8..45f5eeb9 100644
--- a/api/src/routes/auth/login.ts
+++ b/src/api/routes/auth/login.ts
@@ -1,25 +1,15 @@
import { Request, Response, Router } from "express";
import { route, getIpAdress, verifyCaptcha } from "@fosscord/api";
import bcrypt from "bcrypt";
-import { Config, User, generateToken, adjustEmail, FieldErrors } from "@fosscord/util";
+import { Config, User, generateToken, adjustEmail, FieldErrors, LoginSchema } from "@fosscord/util";
import crypto from "crypto";
const router: Router = Router();
export default router;
-export interface LoginSchema {
- login: string;
- password: string;
- undelete?: boolean;
- captcha_key?: string;
- login_source?: string;
- gift_code_sku_id?: string;
-}
-
router.post("/", route({ body: "LoginSchema" }), async (req: Request, res: Response) => {
const { login, password, captcha_key, undelete } = req.body as LoginSchema;
const email = adjustEmail(login);
- console.log("login", email);
const config = Config.get();
diff --git a/api/src/routes/auth/mfa/totp.ts b/src/api/routes/auth/mfa/totp.ts
index cec6e5ee..421dbafa 100644
--- a/api/src/routes/auth/mfa/totp.ts
+++ b/src/api/routes/auth/mfa/totp.ts
@@ -1,17 +1,10 @@
import { Router, Request, Response } from "express";
import { route } from "@fosscord/api";
-import { BackupCode, FieldErrors, generateToken, User } from "@fosscord/util";
+import { BackupCode, FieldErrors, generateToken, TotpSchema, User } from "@fosscord/util";
import { verifyToken } from "node-2fa";
import { HTTPError } from "lambert-server";
const router = Router();
-export interface TotpSchema {
- code: string,
- ticket: string,
- gift_code_sku_id?: string | null,
- login_source?: string | null,
-}
-
router.post("/", route({ body: "TotpSchema" }), async (req: Request, res: Response) => {
const { code, ticket, gift_code_sku_id, login_source } = req.body as TotpSchema;
@@ -26,7 +19,7 @@ router.post("/", route({ body: "TotpSchema" }), async (req: Request, res: Respon
],
});
- const backup = await BackupCode.findOne({ code: code, expired: false, consumed: false, user: { id: user.id }});
+ const backup = await BackupCode.findOne({ where: { code: code, expired: false, consumed: false, user: { id: user.id } } });
if (!backup) {
const ret = verifyToken(user.totp_secret!, code);
diff --git a/api/src/routes/auth/register.ts b/src/api/routes/auth/register.ts
index 98c8fd1b..8059e3f1 100644
--- a/api/src/routes/auth/register.ts
+++ b/src/api/routes/auth/register.ts
@@ -1,38 +1,11 @@
import { Request, Response, Router } from "express";
-import { Config, generateToken, Invite, FieldErrors, User, adjustEmail } from "@fosscord/util";
+import { Config, generateToken, Invite, FieldErrors, User, adjustEmail, RegisterSchema } from "@fosscord/util";
import { route, getIpAdress, IPAnalysis, isProxy, verifyCaptcha } from "@fosscord/api";
-import "missing-native-js-functions";
import bcrypt from "bcrypt";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
const router: Router = Router();
-export interface RegisterSchema {
- /**
- * @minLength 2
- * @maxLength 32
- */
- username: string;
- /**
- * @minLength 1
- * @maxLength 72
- */
- password?: string;
- consent: boolean;
- /**
- * @TJS-format email
- */
- email?: string;
- fingerprint?: string;
- invite?: string;
- /**
- * @TJS-type string
- */
- date_of_birth?: Date; // "2000-04-03"
- gift_code_sku_id?: string;
- captcha_key?: string;
-}
-
router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Response) => {
const body = req.body as RegisterSchema;
const { register, security } = Config.get();
@@ -115,7 +88,7 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
}
// check if there is already an account with this email
- const exists = await User.findOne({ email: email });
+ const exists = await User.findOne({ where: { email: email } });
if (exists) {
throw FieldErrors({
@@ -174,8 +147,6 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
await Invite.joinGuild(user.id, body.invite);
}
- console.log("register", body.email, body.username, ip);
-
return res.json({ token: await generateToken(user.id) });
});
diff --git a/api/src/routes/channels/#channel_id/followers.ts b/src/api/routes/channels/#channel_id/followers.ts
index 641af4f8..641af4f8 100644
--- a/api/src/routes/channels/#channel_id/followers.ts
+++ b/src/api/routes/channels/#channel_id/followers.ts
diff --git a/api/src/routes/channels/#channel_id/index.ts b/src/api/routes/channels/#channel_id/index.ts
index 2fca4fdf..bb8b868b 100644
--- a/api/src/routes/channels/#channel_id/index.ts
+++ b/src/api/routes/channels/#channel_id/index.ts
@@ -6,10 +6,12 @@ import {
ChannelUpdateEvent,
emitEvent,
Recipient,
- handleFile
+ handleFile,
+ ChannelModifySchema
} from "@fosscord/util";
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
+import { OrmUtils } from "@fosscord/util";
const router: Router = Router();
// TODO: delete channel
@@ -18,7 +20,7 @@ const router: Router = Router();
router.get("/", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: Response) => {
const { channel_id } = req.params;
- const channel = await Channel.findOneOrFail({ id: channel_id });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
return res.send(channel);
});
@@ -29,7 +31,7 @@ router.delete("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] });
if (channel.type === ChannelType.DM) {
- const recipient = await Recipient.findOneOrFail({ where: { channel_id: channel_id, user_id: req.user_id } });
+ const recipient = await Recipient.findOneOrFail({ where: { channel_id, user_id: req.user_id } });
recipient.closed = true;
await Promise.all([
recipient.save(),
@@ -47,38 +49,13 @@ router.delete("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request
res.send(channel);
});
-export interface ChannelModifySchema {
- /**
- * @maxLength 100
- */
- name?: string;
- type?: ChannelType;
- topic?: string;
- icon?: string | null;
- bitrate?: number;
- user_limit?: number;
- rate_limit_per_user?: number;
- position?: number;
- permission_overwrites?: {
- id: string;
- type: ChannelPermissionOverwriteType;
- allow: string;
- deny: string;
- }[];
- parent_id?: string;
- id?: string; // is not used (only for guild create)
- nsfw?: boolean;
- rtc_region?: string;
- default_auto_archive_duration?: number;
-}
-
router.patch("/", route({ body: "ChannelModifySchema", permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => {
- var payload = req.body as ChannelModifySchema;
+ let payload = req.body as ChannelModifySchema;
const { channel_id } = req.params;
if (payload.icon) payload.icon = await handleFile(`/channel-icons/${channel_id}`, payload.icon);
- const channel = await Channel.findOneOrFail({ id: channel_id });
- channel.assign(payload);
+ let channel = await Channel.findOneOrFail({ where: { id: channel_id } });
+ channel = OrmUtils.mergeDeep(channel, payload);
await Promise.all([
channel.save(),
diff --git a/api/src/routes/channels/#channel_id/invites.ts b/src/api/routes/channels/#channel_id/invites.ts
index 9c361164..b5c65c0d 100644
--- a/api/src/routes/channels/#channel_id/invites.ts
+++ b/src/api/routes/channels/#channel_id/invites.ts
@@ -1,24 +1,13 @@
import { Router, Request, Response } from "express";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
import { random } from "@fosscord/api";
import { Channel, Invite, InviteCreateEvent, emitEvent, User, Guild, PublicInviteRelation } from "@fosscord/util";
import { isTextChannel } from "./messages";
+import { OrmUtils } from "@fosscord/util";
const router: Router = Router();
-export interface InviteCreateSchema {
- target_user_id?: string;
- target_type?: string;
- validate?: string; // ? what is this
- max_age?: number;
- max_uses?: number;
- temporary?: boolean;
- unique?: boolean;
- target_user?: string;
- target_user_type?: number;
-}
-
router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE", right: "CREATE_INVITES" }),
async (req: Request, res: Response) => {
const { user_id } = req;
@@ -33,21 +22,19 @@ router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT
const expires_at = new Date(req.body.max_age * 1000 + Date.now());
- const invite = await new Invite({
- code: random(),
- temporary: req.body.temporary,
- uses: 0,
+ const invite = await OrmUtils.mergeDeep(new Invite(),{
+ temporary: req.body.temporary || true,
max_uses: req.body.max_uses,
max_age: req.body.max_age,
expires_at,
- created_at: new Date(),
guild_id,
- channel_id: channel_id,
+ channel_id,
inviter_id: user_id
}).save();
- const data = invite.toJSON();
+ //TODO: check this, removed toJSON call
+ const data = JSON.parse(JSON.stringify(invite));
data.inviter = await User.getPublicUser(req.user_id);
- data.guild = await Guild.findOne({ id: guild_id });
+ data.guild = await Guild.findOne({ where: { id: guild_id } });
data.channel = channel;
await emitEvent({ event: "INVITE_CREATE", data, guild_id } as InviteCreateEvent);
@@ -55,9 +42,8 @@ router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT
});
router.get("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => {
- const { user_id } = req;
const { channel_id } = req.params;
- const channel = await Channel.findOneOrFail({ id: channel_id });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
if (!channel.guild_id) {
throw new HTTPError("This channel doesn't exist", 404);
diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts b/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts
index 885c5eca..041f4d5e 100644
--- a/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts
+++ b/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts
@@ -1,26 +1,18 @@
import { emitEvent, getPermission, MessageAckEvent, ReadState, Snowflake } from "@fosscord/util";
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
+import { OrmUtils } from "@fosscord/util";
const router = Router();
-// TODO: public read receipts & privacy scoping
-// TODO: send read state event to all channel members
-// TODO: advance-only notification cursor
-
-export interface MessageAcknowledgeSchema {
- manual?: boolean;
- mention_count?: number;
-}
-
router.post("/", route({ body: "MessageAcknowledgeSchema" }), async (req: Request, res: Response) => {
const { channel_id, message_id } = req.params;
const permission = await getPermission(req.user_id, undefined, channel_id);
permission.hasThrow("VIEW_CHANNEL");
- let read_state = await ReadState.findOne({ user_id: req.user_id, channel_id });
- if (!read_state) read_state = new ReadState({ user_id: req.user_id, channel_id });
+ let read_state = await ReadState.findOne({ where: { user_id: req.user_id, channel_id } });
+ if (!read_state) read_state = OrmUtils.mergeDeep(new ReadState(), { user_id: req.user_id, channel_id }) as ReadState;
read_state.last_message_id = message_id;
await read_state.save();
diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/crosspost.ts b/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts
index b2cb6763..b2cb6763 100644
--- a/api/src/routes/channels/#channel_id/messages/#message_id/crosspost.ts
+++ b/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts
diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
index 63fee9b9..d7e27062 100644
--- a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts
+++ b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
@@ -12,14 +12,14 @@ import {
MessageDeleteEvent,
MessageUpdateEvent,
Snowflake,
- uploadFile
+ uploadFile,
+ MessageCreateSchema
} from "@fosscord/util";
import { Router, Response, Request } from "express";
import multer from "multer";
import { route } from "@fosscord/api";
import { handleMessage, postHandleMessage } from "@fosscord/api";
-import { MessageCreateSchema } from "../index";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
const router = Router();
// TODO: message content/embed string length limit
@@ -35,7 +35,7 @@ const messageUpload = multer({
router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_MESSAGES" }), async (req: Request, res: Response) => {
const { message_id, channel_id } = req.params;
- var body = req.body as MessageCreateSchema;
+ let body = req.body as MessageCreateSchema;
const message = await Message.findOneOrFail({ where: { id: message_id, channel_id }, relations: ["attachments"] });
@@ -92,7 +92,7 @@ router.put(
route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_BACKDATED_EVENTS" }),
async (req: Request, res: Response) => {
const { channel_id, message_id } = req.params;
- var body = req.body as MessageCreateSchema;
+ let body = req.body as MessageCreateSchema;
const attachments: Attachment[] = [];
const rights = await getRights(req.user_id);
@@ -116,7 +116,7 @@ router.put(
if (req.file) {
try {
- const file = await uploadFile(`/attachments/${req.params.channel_id}`, req.file);
+ const file: any = await uploadFile(`/attachments/${req.params.channel_id}`, req.file);
attachments.push({ ...file, proxy_url: file.url });
} catch (error) {
return res.status(400).json(error);
@@ -169,8 +169,8 @@ router.get("/", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res:
router.delete("/", route({}), async (req: Request, res: Response) => {
const { message_id, channel_id } = req.params;
- const channel = await Channel.findOneOrFail({ id: channel_id });
- const message = await Message.findOneOrFail({ id: message_id });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
+ const message = await Message.findOneOrFail({ where: { id: message_id } });
const rights = await getRights(req.user_id);
diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts b/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts
index d93cf70f..d0ab35bb 100644
--- a/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts
+++ b/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts
@@ -15,7 +15,7 @@ import {
} from "@fosscord/util";
import { route } from "@fosscord/api";
import { Router, Response, Request } from "express";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { In } from "typeorm";
const router = Router();
@@ -39,7 +39,7 @@ function getEmoji(emoji: string): PartialEmoji {
router.delete("/", route({ permission: "MANAGE_MESSAGES" }), async (req: Request, res: Response) => {
const { message_id, channel_id } = req.params;
- const channel = await Channel.findOneOrFail({ id: channel_id });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
await Message.update({ id: message_id, channel_id }, { reactions: [] });
@@ -60,7 +60,7 @@ router.delete("/:emoji", route({ permission: "MANAGE_MESSAGES" }), async (req: R
const { message_id, channel_id } = req.params;
const emoji = getEmoji(req.params.emoji);
- const message = await Message.findOneOrFail({ id: message_id, channel_id });
+ const message = await Message.findOneOrFail({ where: { id: message_id, channel_id } });
const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
if (!already_added) throw new HTTPError("Reaction not found", 404);
@@ -87,7 +87,7 @@ router.get("/:emoji", route({ permission: "VIEW_CHANNEL" }), async (req: Request
const { message_id, channel_id } = req.params;
const emoji = getEmoji(req.params.emoji);
- const message = await Message.findOneOrFail({ id: message_id, channel_id });
+ const message = await Message.findOneOrFail({ where: { id: message_id, channel_id } });
const reaction = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
if (!reaction) throw new HTTPError("Reaction not found", 404);
@@ -106,14 +106,14 @@ router.put("/:emoji/:user_id", route({ permission: "READ_MESSAGE_HISTORY", right
if (user_id !== "@me") throw new HTTPError("Invalid user");
const emoji = getEmoji(req.params.emoji);
- const channel = await Channel.findOneOrFail({ id: channel_id });
- const message = await Message.findOneOrFail({ id: message_id, channel_id });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
+ const message = await Message.findOneOrFail({ where: { id: message_id, channel_id } });
const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
if (!already_added) req.permission!.hasThrow("ADD_REACTIONS");
if (emoji.id) {
- const external_emoji = await Emoji.findOneOrFail({ id: emoji.id });
+ const external_emoji = await Emoji.findOneOrFail({ where: { id: emoji.id } });
if (!already_added) req.permission!.hasThrow("USE_EXTERNAL_EMOJIS");
emoji.animated = external_emoji.animated;
emoji.name = external_emoji.name;
@@ -126,7 +126,7 @@ router.put("/:emoji/:user_id", route({ permission: "READ_MESSAGE_HISTORY", right
await message.save();
- const member = channel.guild_id && (await Member.findOneOrFail({ id: req.user_id }));
+ const member = channel.guild_id && (await Member.findOneOrFail({ where: { id: req.user_id } }));
await emitEvent({
event: "MESSAGE_REACTION_ADD",
@@ -145,12 +145,12 @@ router.put("/:emoji/:user_id", route({ permission: "READ_MESSAGE_HISTORY", right
});
router.delete("/:emoji/:user_id", route({}), async (req: Request, res: Response) => {
- var { message_id, channel_id, user_id } = req.params;
+ let { message_id, channel_id, user_id } = req.params;
const emoji = getEmoji(req.params.emoji);
- const channel = await Channel.findOneOrFail({ id: channel_id });
- const message = await Message.findOneOrFail({ id: message_id, channel_id });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
+ const message = await Message.findOneOrFail({ where: { id: message_id, channel_id } });
if (user_id === "@me") user_id = req.user_id;
else {
diff --git a/api/src/routes/channels/#channel_id/messages/bulk-delete.ts b/src/api/routes/channels/#channel_id/messages/bulk-delete.ts
index 6eacf249..af44b522 100644
--- a/api/src/routes/channels/#channel_id/messages/bulk-delete.ts
+++ b/src/api/routes/channels/#channel_id/messages/bulk-delete.ts
@@ -1,6 +1,6 @@
import { Router, Response, Request } from "express";
import { Channel, Config, emitEvent, getPermission, getRights, MessageDeleteBulkEvent, Message } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
import { In } from "typeorm";
@@ -8,24 +8,20 @@ const router: Router = Router();
export default router;
-export interface BulkDeleteSchema {
- messages: string[];
-}
-
// should users be able to bulk delete messages or only bots? ANSWER: all users
// should this request fail, if you provide messages older than 14 days/invalid ids? ANSWER: NO
// https://discord.com/developers/docs/resources/channel#bulk-delete-messages
router.post("/", route({ body: "BulkDeleteSchema" }), async (req: Request, res: Response) => {
const { channel_id } = req.params;
- const channel = await Channel.findOneOrFail({ id: channel_id });
+ const channel = await Channel.findOneOrFail({where:{ id: channel_id} });
if (!channel.guild_id) throw new HTTPError("Can't bulk delete dm channel messages", 400);
const rights = await getRights(req.user_id);
rights.hasThrow("SELF_DELETE_MESSAGES");
-
+
let superuser = rights.has("MANAGE_MESSAGES");
const permission = await getPermission(req.user_id, channel?.guild_id, channel_id);
-
+
const { maxBulkDelete } = Config.get().limits.message;
const { messages } = req.body as { messages: string[] };
@@ -35,7 +31,7 @@ router.post("/", route({ body: "BulkDeleteSchema" }), async (req: Request, res:
if (messages.length > maxBulkDelete) throw new HTTPError(`You cannot delete more than ${maxBulkDelete} messages`);
}
- await Message.delete(messages.map((x) => ({ id: x })));
+ await Message.delete({ id: In(messages) });
await emitEvent({
event: "MESSAGE_DELETE_BULK",
diff --git a/api/src/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts
index 54e6edcc..9ab0d97d 100644
--- a/api/src/routes/channels/#channel_id/messages/index.ts
+++ b/src/api/routes/channels/#channel_id/messages/index.ts
@@ -5,7 +5,6 @@ import {
ChannelType,
Config,
DmChannelDTO,
- Embed,
emitEvent,
getPermission,
getRights,
@@ -13,9 +12,10 @@ import {
MessageCreateEvent,
Snowflake,
uploadFile,
- Member
+ Member,
+ MessageCreateSchema
} from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { handleMessage, postHandleMessage, route } from "@fosscord/api";
import multer from "multer";
import { FindManyOptions, LessThan, MoreThan } from "typeorm";
@@ -49,43 +49,11 @@ export function isTextChannel(type: ChannelType): boolean {
}
}
-export interface MessageCreateSchema {
- type?: number;
- content?: string;
- nonce?: string;
- channel_id?: string;
- tts?: boolean;
- flags?: string;
- embeds?: Embed[];
- embed?: Embed;
- // TODO: ^ embed is deprecated in favor of embeds (https://discord.com/developers/docs/resources/channel#message-object)
- allowed_mentions?: {
- parse?: string[];
- roles?: string[];
- users?: string[];
- replied_user?: boolean;
- };
- message_reference?: {
- message_id: string;
- channel_id: string;
- guild_id?: string;
- fail_if_not_exists?: boolean;
- };
- payload_json?: string;
- file?: any;
- /**
- TODO: we should create an interface for attachments
- TODO: OpenWAAO<-->attachment-style metadata conversion
- **/
- attachments?: any[];
- sticker_ids?: string[];
-}
-
// https://discord.com/developers/docs/resources/channel#create-message
// get messages
router.get("/", async (req: Request, res: Response) => {
const channel_id = req.params.channel_id;
- const channel = await Channel.findOneOrFail({ id: channel_id });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
if (!channel) throw new HTTPError("Channel not found", 404);
isTextChannel(channel.type);
@@ -95,13 +63,13 @@ router.get("/", async (req: Request, res: Response) => {
const limit = Number(req.query.limit) || 50;
if (limit < 1 || limit > 100) throw new HTTPError("limit must be between 1 and 100", 422);
- var halfLimit = Math.floor(limit / 2);
+ let halfLimit = Math.floor(limit / 2);
const permissions = await getPermission(req.user_id, channel.guild_id, channel_id);
permissions.hasThrow("VIEW_CHANNEL");
if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]);
- var query: FindManyOptions<Message> & { where: { id?: any; }; } = {
+ let query: FindManyOptions<Message> & { where: { id?: any; }; } = {
order: { id: "DESC" },
take: limit,
where: { channel_id },
@@ -148,7 +116,7 @@ router.get("/", async (req: Request, res: Response) => {
which causes erorrs when, say, the `application` property is `null`.
**/
- for (var curr in x) {
+ for (let curr in x) {
if (x[curr] === null)
delete x[curr];
}
@@ -189,7 +157,7 @@ router.post(
route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_MESSAGES" }),
async (req: Request, res: Response) => {
const { channel_id } = req.params;
- var body = req.body as MessageCreateSchema;
+ let body = req.body as MessageCreateSchema;
const attachments: Attachment[] = [];
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients", "recipients.user"] });
@@ -198,9 +166,9 @@ router.post(
}
const files = req.files as Express.Multer.File[] ?? [];
- for (var currFile of files) {
+ for (let currFile of files) {
try {
- const file = await uploadFile(`/attachments/${channel.id}`, currFile);
+ const file: any = await uploadFile(`/attachments/${channel.id}`, currFile);
attachments.push({ ...file, proxy_url: file.url });
}
catch (error) {
@@ -245,8 +213,18 @@ router.post(
);
}
- //Fix for the client bug
- delete message.member
+ //Defining member fields
+ var member = await Member.findOneOrFail({ where: { id: req.user_id }, relations: ["roles"] });
+ // TODO: This doesn't work either
+ // member.roles = member.roles.filter((role) => {
+ // return role.id !== role.guild_id;
+ // }).map((role) => {
+ // return role.id;
+ // });
+ message.member = member;
+ // TODO: Figure this out
+ // delete message.member.last_message_id;
+ // delete message.member.index;
await Promise.all([
message.save(),
diff --git a/api/src/routes/channels/#channel_id/permissions.ts b/src/api/routes/channels/#channel_id/permissions.ts
index 2eded853..34052fe5 100644
--- a/api/src/routes/channels/#channel_id/permissions.ts
+++ b/src/api/routes/channels/#channel_id/permissions.ts
@@ -1,6 +1,7 @@
import {
Channel,
ChannelPermissionOverwrite,
+ ChannelPermissionOverwriteSchema,
ChannelPermissionOverwriteType,
ChannelUpdateEvent,
emitEvent,
@@ -9,14 +10,10 @@ import {
Role
} from "@fosscord/util";
import { Router, Response, Request } from "express";
-import { HTTPError } from "lambert-server";
-
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
-const router: Router = Router();
-// TODO: Only permissions your bot has in the guild or channel can be allowed/denied (unless your bot has a MANAGE_ROLES overwrite in the channel)
-
-export interface ChannelPermissionOverwriteSchema extends ChannelPermissionOverwrite {}
+const router: Router = Router();
router.put(
"/:overwrite_id",
@@ -25,17 +22,17 @@ router.put(
const { channel_id, overwrite_id } = req.params;
const body = req.body as ChannelPermissionOverwriteSchema;
- var channel = await Channel.findOneOrFail({ id: channel_id });
+ let channel = await Channel.findOneOrFail({ where: {id: channel_id} });
if (!channel.guild_id) throw new HTTPError("Channel not found", 404);
if (body.type === 0) {
- if (!(await Role.count({ id: overwrite_id }))) throw new HTTPError("role not found", 404);
+ if (!(await Role.count({ where: { id: overwrite_id } }))) throw new HTTPError("role not found", 404);
} else if (body.type === 1) {
- if (!(await Member.count({ id: overwrite_id }))) throw new HTTPError("user not found", 404);
+ if (!(await Member.count({ where: { id: overwrite_id } }))) throw new HTTPError("user not found", 404);
} else throw new HTTPError("type not supported", 501);
// @ts-ignore
- var overwrite: ChannelPermissionOverwrite = channel.permission_overwrites.find((x) => x.id === overwrite_id);
+ let overwrite: ChannelPermissionOverwrite = channel.permission_overwrites.find((x) => x.id === overwrite_id);
if (!overwrite) {
// @ts-ignore
overwrite = {
@@ -64,7 +61,7 @@ router.put(
router.delete("/:overwrite_id", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
const { channel_id, overwrite_id } = req.params;
- const channel = await Channel.findOneOrFail({ id: channel_id });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
if (!channel.guild_id) throw new HTTPError("Channel not found", 404);
channel.permission_overwrites = channel.permission_overwrites!.filter((x) => x.id === overwrite_id);
diff --git a/api/src/routes/channels/#channel_id/pins.ts b/src/api/routes/channels/#channel_id/pins.ts
index e71e659f..003638c5 100644
--- a/api/src/routes/channels/#channel_id/pins.ts
+++ b/src/api/routes/channels/#channel_id/pins.ts
@@ -9,7 +9,7 @@ import {
DiscordApiErrors
} from "@fosscord/util";
import { Router, Request, Response } from "express";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
const router: Router = Router();
@@ -17,12 +17,12 @@ const router: Router = Router();
router.put("/:message_id", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: Response) => {
const { channel_id, message_id } = req.params;
- const message = await Message.findOneOrFail({ id: message_id });
+ const message = await Message.findOneOrFail({ where: { id: message_id } });
// * in dm channels anyone can pin messages -> only check for guilds
if (message.guild_id) req.permission!.hasThrow("MANAGE_MESSAGES");
- const pinned_count = await Message.count({ channel: { id: channel_id }, pinned: true });
+ const pinned_count = await Message.count({ where: { channel: { id: channel_id }, pinned: true } });
const { maxPins } = Config.get().limits.channel;
if (pinned_count >= maxPins) throw DiscordApiErrors.MAXIMUM_PINS.withParams(maxPins);
@@ -50,10 +50,10 @@ router.put("/:message_id", route({ permission: "VIEW_CHANNEL" }), async (req: Re
router.delete("/:message_id", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: Response) => {
const { channel_id, message_id } = req.params;
- const channel = await Channel.findOneOrFail({ id: channel_id });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
if (channel.guild_id) req.permission!.hasThrow("MANAGE_MESSAGES");
- const message = await Message.findOneOrFail({ id: message_id });
+ const message = await Message.findOneOrFail({ where: { id: message_id } });
message.pinned = false;
await Promise.all([
@@ -82,7 +82,7 @@ router.delete("/:message_id", route({ permission: "VIEW_CHANNEL" }), async (req:
router.get("/", route({ permission: ["READ_MESSAGE_HISTORY"] }), async (req: Request, res: Response) => {
const { channel_id } = req.params;
- let pins = await Message.find({ channel_id: channel_id, pinned: true });
+ let pins = await Message.find({ where: { channel_id, pinned: true } });
res.send(pins);
});
diff --git a/src/api/routes/channels/#channel_id/purge.ts b/src/api/routes/channels/#channel_id/purge.ts
new file mode 100644
index 00000000..1ef6e1d7
--- /dev/null
+++ b/src/api/routes/channels/#channel_id/purge.ts
@@ -0,0 +1,64 @@
+import { HTTPError, PurgeSchema } from "@fosscord/util";
+import { route } from "@fosscord/api";
+import { isTextChannel } from "./messages";
+import { FindManyOptions, Between, Not } from "typeorm";
+import { Channel, Config, emitEvent, getPermission, getRights, Message, MessageDeleteBulkEvent } from "@fosscord/util";
+import { Router, Response, Request } from "express";
+import { In } from "typeorm";
+
+const router: Router = Router();
+
+export default router;
+
+/**
+TODO: apply the delete bit by bit to prevent client and database stress
+**/
+router.post("/",route({ /*body: "PurgeSchema",*/ }), async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
+
+ if (!channel.guild_id) throw new HTTPError("Can't purge dm channels", 400);
+ isTextChannel(channel.type);
+
+ const rights = await getRights(req.user_id);
+ if (!rights.has("MANAGE_MESSAGES")) {
+ const permissions = await getPermission(req.user_id, channel.guild_id, channel_id);
+ permissions.hasThrow("MANAGE_MESSAGES");
+ permissions.hasThrow("MANAGE_CHANNELS");
+ }
+
+ const { before, after } = req.body as PurgeSchema;
+
+ // TODO: send the deletion event bite-by-bite to prevent client stress
+
+ let query: FindManyOptions<Message> & { where: { id?: any } } = {
+ order: { id: "ASC" },
+ // take: limit,
+ where: {
+ channel_id,
+ id: Between(after, before), // the right way around
+ author_id: rights.has("SELF_DELETE_MESSAGES") ? undefined : Not(req.user_id)
+ // if you lack the right of self-deletion, you can't delete your own messages, even in purges
+ },
+ relations: ["author", "webhook", "application", "mentions", "mention_roles", "mention_channels", "sticker_items", "attachments"]
+ };
+
+ const messages = await Message.find(query);
+ const endpoint = Config.get().cdn.endpointPublic;
+
+ if (messages.length == 0) {
+ res.sendStatus(304);
+ return;
+ }
+
+ await Message.delete({ id: In(messages) });
+
+ await emitEvent({
+ event: "MESSAGE_DELETE_BULK",
+ channel_id,
+ data: { ids: messages.map((x) => x.id), channel_id, guild_id: channel.guild_id }
+ } as MessageDeleteBulkEvent);
+
+ res.sendStatus(204);
+ }
+);
diff --git a/api/src/routes/channels/#channel_id/recipients.ts b/src/api/routes/channels/#channel_id/recipients.ts
index e6466211..069212e2 100644
--- a/api/src/routes/channels/#channel_id/recipients.ts
+++ b/src/api/routes/channels/#channel_id/recipients.ts
@@ -11,6 +11,7 @@ import {
User
} from "@fosscord/util";
import { route } from "@fosscord/api";
+import { OrmUtils } from "@fosscord/util";
const router: Router = Router();
@@ -28,7 +29,7 @@ router.put("/:user_id", route({}), async (req: Request, res: Response) => {
throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
}
- channel.recipients!.push(new Recipient({ channel_id: channel_id, user_id: user_id }));
+ channel.recipients!.push(OrmUtils.mergeDeep(new Recipient(), { channel_id, user_id: user_id }));
await channel.save();
await emitEvent({
diff --git a/api/src/routes/channels/#channel_id/typing.ts b/src/api/routes/channels/#channel_id/typing.ts
index 56652368..99460f6e 100644
--- a/api/src/routes/channels/#channel_id/typing.ts
+++ b/src/api/routes/channels/#channel_id/typing.ts
@@ -8,7 +8,7 @@ router.post("/", route({ permission: "SEND_MESSAGES" }), async (req: Request, re
const { channel_id } = req.params;
const user_id = req.user_id;
const timestamp = Date.now();
- const channel = await Channel.findOneOrFail({ id: channel_id });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
const member = await Member.findOne({ where: { id: user_id, guild_id: channel.guild_id }, relations: ["roles", "user"] });
await emitEvent({
diff --git a/api/src/routes/channels/#channel_id/webhooks.ts b/src/api/routes/channels/#channel_id/webhooks.ts
index 92895da6..b11c8eb9 100644
--- a/api/src/routes/channels/#channel_id/webhooks.ts
+++ b/src/api/routes/channels/#channel_id/webhooks.ts
@@ -1,19 +1,11 @@
import { Router, Response, Request } from "express";
import { route } from "@fosscord/api";
import { Channel, Config, getPermission, trimSpecial, Webhook } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { isTextChannel } from "./messages/index";
import { DiscordApiErrors } from "@fosscord/util";
const router: Router = Router();
-// TODO: webhooks
-export interface WebhookCreateSchema {
- /**
- * @maxLength 80
- */
- name: string;
- avatar: string;
-}
//TODO: implement webhooks
router.get("/", route({}), async (req: Request, res: Response) => {
res.json([]);
@@ -22,20 +14,21 @@ router.get("/", route({}), async (req: Request, res: Response) => {
// TODO: use Image Data Type for avatar instead of String
router.post("/", route({ body: "WebhookCreateSchema", permission: "MANAGE_WEBHOOKS" }), async (req: Request, res: Response) => {
const channel_id = req.params.channel_id;
- const channel = await Channel.findOneOrFail({ id: channel_id });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
isTextChannel(channel.type);
if (!channel.guild_id) throw new HTTPError("Not a guild channel", 400);
- const webhook_count = await Webhook.count({ channel_id });
+ const webhook_count = await Webhook.count({ where: { channel_id } });
const { maxWebhooks } = Config.get().limits.channel;
if (webhook_count > maxWebhooks) throw DiscordApiErrors.MAXIMUM_WEBHOOKS.withParams(maxWebhooks);
- var { avatar, name } = req.body as { name: string; avatar?: string };
+ let { avatar, name } = req.body as { name: string; avatar?: string };
name = trimSpecial(name);
if (name === "clyde") throw new HTTPError("Invalid name", 400);
// TODO: save webhook in database and send response
+ res.json(new Webhook());
});
export default router;
diff --git a/src/api/routes/discoverable-guilds.ts b/src/api/routes/discoverable-guilds.ts
new file mode 100644
index 00000000..35ecf28c
--- /dev/null
+++ b/src/api/routes/discoverable-guilds.ts
@@ -0,0 +1,39 @@
+import { Guild, Config } from "@fosscord/util";
+
+import { Router, Request, Response } from "express";
+import { route } from "..";
+import { Like } from "typeorm";
+
+const router = Router();
+
+router.get("/", route({}), async (req: Request, res: Response) => {
+ const { offset, limit, categories } = req.query;
+ let showAllGuilds = Config.get().guild.discovery.showAllGuilds;
+ let configLimit = Config.get().guild.discovery.limit;
+ // ! this only works using SQL querys
+ // const guilds = await Guild.find({ where: { features: "DISCOVERABLE" } }); //, take: Math.abs(Number(limit)) });
+ let guilds;
+ if (categories == undefined) {
+ guilds = showAllGuilds
+ ? await Guild.find({ take: Math.abs(Number(limit || configLimit)) })
+ : await Guild.find({ where: { features: Like("%DISCOVERABLE%") }, take: Math.abs(Number(limit || configLimit)) });
+ } else {
+ guilds = showAllGuilds
+ ? await Guild.find({ where: { primary_category_id: Number(categories) }, take: Math.abs(Number(limit || configLimit)) })
+ : await Guild.find({
+ where: { primary_category_id: Number(categories), features: Like("%DISCOVERABLE%") },
+ take: Math.abs(Number(limit || configLimit))
+ });
+ }
+
+ const total = guilds ? guilds.length : undefined;
+
+ res.send({
+ total: total,
+ guilds: guilds,
+ offset: Number(offset || Config.get().guild.discovery.offset),
+ limit: Number(limit || configLimit)
+ });
+});
+
+export default router;
diff --git a/api/src/routes/discovery.ts b/src/api/routes/discovery.ts
index 1991400e..30c418c6 100644
--- a/api/src/routes/discovery.ts
+++ b/src/api/routes/discovery.ts
@@ -1,6 +1,6 @@
import { Categories } from "@fosscord/util";
import { Router, Response, Request } from "express";
-import { route } from "@fosscord/api";
+import { route } from "..";
const router = Router();
@@ -10,7 +10,7 @@ router.get("/categories", route({}), async (req: Request, res: Response) => {
const { locale, primary_only } = req.query;
- const out = primary_only ? await Categories.find() : await Categories.find({ where: `"is_primary" = "true"` });
+ const out = primary_only ? await Categories.find() : await Categories.find({ where: {is_primary: true} });
res.send(out);
});
diff --git a/api/src/routes/downloads.ts b/src/api/routes/downloads.ts
index ddfc080c..44530353 100644
--- a/api/src/routes/downloads.ts
+++ b/src/api/routes/downloads.ts
@@ -1,5 +1,5 @@
import { Router, Response, Request } from "express";
-import { route } from "@fosscord/api";
+import { route } from "..";
import { Release, Config } from "@fosscord/util";
const router = Router();
@@ -12,7 +12,7 @@ router.get("/:branch", route({}), async (req: Request, res: Response) => {
if(!platform || !["linux", "osx", "win"].includes(platform.toString())) return res.status(404)
- const release = await Release.findOneOrFail({ name: client.releases.upstreamVersion });
+ const release = await Release.findOneOrFail({ where: { name: client.releases.upstreamVersion } });
res.redirect(release[`win_url`]);
});
diff --git a/api/src/routes/experiments.ts b/src/api/routes/experiments.ts
index 7be86fb8..fcbd9271 100644
--- a/api/src/routes/experiments.ts
+++ b/src/api/routes/experiments.ts
@@ -1,5 +1,5 @@
import { Router, Response, Request } from "express";
-import { route } from "@fosscord/api";
+import { route } from "..";
const router = Router();
diff --git a/api/src/routes/gateway/bot.ts b/src/api/routes/gateway/bot.ts
index f1dbb9df..f1dbb9df 100644
--- a/api/src/routes/gateway/bot.ts
+++ b/src/api/routes/gateway/bot.ts
diff --git a/api/src/routes/gateway/index.ts b/src/api/routes/gateway/index.ts
index 9bad7478..9bad7478 100644
--- a/api/src/routes/gateway/index.ts
+++ b/src/api/routes/gateway/index.ts
diff --git a/api/src/routes/gifs/search.ts b/src/api/routes/gifs/search.ts
index 9ad7a592..1099dc4a 100644
--- a/api/src/routes/gifs/search.ts
+++ b/src/api/routes/gifs/search.ts
@@ -20,7 +20,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
headers: { "Content-Type": "application/json" }
});
- const { results } = await response.json();
+ const { results } = await response.json() as any;
res.json(results.map(parseGifResult)).status(200);
});
diff --git a/api/src/routes/gifs/trending-gifs.ts b/src/api/routes/gifs/trending-gifs.ts
index 6d97bf7c..2b28d9d2 100644
--- a/api/src/routes/gifs/trending-gifs.ts
+++ b/src/api/routes/gifs/trending-gifs.ts
@@ -20,7 +20,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
headers: { "Content-Type": "application/json" }
});
- const { results } = await response.json();
+ const { results } = await response.json() as any;
res.json(results.map(parseGifResult)).status(200);
});
diff --git a/api/src/routes/gifs/trending.ts b/src/api/routes/gifs/trending.ts
index c81b4c08..61eb76c4 100644
--- a/api/src/routes/gifs/trending.ts
+++ b/src/api/routes/gifs/trending.ts
@@ -3,7 +3,7 @@ import fetch from "node-fetch";
import ProxyAgent from 'proxy-agent';
import { route } from "@fosscord/api";
import { Config } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
const router = Router();
@@ -50,8 +50,8 @@ router.get("/", route({}), async (req: Request, res: Response) => {
})
]);
- const { tags } = await responseSource.json();
- const { results } = await trendGifSource.json();
+ const { tags } = await responseSource.json() as any;
+ const { results } = await trendGifSource.json() as any;
res.json({
categories: tags.map((x: any) => ({ name: x.searchterm, src: x.image })),
diff --git a/api/src/routes/guild-recommendations.ts b/src/api/routes/guild-recommendations.ts
index 1432f39c..bd0140d6 100644
--- a/api/src/routes/guild-recommendations.ts
+++ b/src/api/routes/guild-recommendations.ts
@@ -1,13 +1,14 @@
import { Guild, Config } from "@fosscord/util";
import { Router, Request, Response } from "express";
-import { route } from "@fosscord/api";
+import { route } from "..";
+import {Like} from "typeorm"
const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
const { limit, personalization_disabled } = req.query;
- var showAllGuilds = Config.get().guild.discovery.showAllGuilds;
+ let showAllGuilds = Config.get().guild.discovery.showAllGuilds;
// ! this only works using SQL querys
// TODO: implement this with default typeorm query
// const guilds = await Guild.find({ where: { features: "DISCOVERABLE" } }); //, take: Math.abs(Number(limit)) });
@@ -16,7 +17,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
const guilds = showAllGuilds
? await Guild.find({ take: Math.abs(Number(limit || 24)) })
- : await Guild.find({ where: `"features" LIKE '%DISCOVERABLE%'`, take: Math.abs(Number(limit || 24)) });
+ : await Guild.find({ where: { features: Like('%DISCOVERABLE%') }, take: Math.abs(Number(limit || 24)) });
res.send({ recommended_guilds: guilds, load_id: `server_recs/${genLoadId(32)}`}).status(200);
});
diff --git a/api/src/routes/guilds/#guild_id/audit-logs.ts b/src/api/routes/guilds/#guild_id/audit-logs.ts
index a4f2f800..b54835fc 100644
--- a/api/src/routes/guilds/#guild_id/audit-logs.ts
+++ b/src/api/routes/guilds/#guild_id/audit-logs.ts
@@ -1,8 +1,5 @@
import { Router, Response, Request } from "express";
-import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
const router = Router();
//TODO: implement audit logs
diff --git a/api/src/routes/guilds/#guild_id/bans.ts b/src/api/routes/guilds/#guild_id/bans.ts
index 1ce41936..3d405344 100644
--- a/api/src/routes/guilds/#guild_id/bans.ts
+++ b/src/api/routes/guilds/#guild_id/bans.ts
@@ -1,29 +1,8 @@
import { Request, Response, Router } from "express";
-import { DiscordApiErrors, emitEvent, getPermission, GuildBanAddEvent, GuildBanRemoveEvent, Guild, Ban, User, Member } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { DiscordApiErrors, emitEvent, getPermission, GuildBanAddEvent, GuildBanRemoveEvent, Guild, Ban, User, Member, BanRegistrySchema, BanModeratorSchema } from "@fosscord/util";
+import { HTTPError } from "@fosscord/util";
import { getIpAdress, route } from "@fosscord/api";
-
-export interface BanCreateSchema {
- delete_message_days?: string;
- reason?: string;
-};
-
-export interface BanRegistrySchema {
- id: string;
- user_id: string;
- guild_id: string;
- executor_id: string;
- ip?: string;
- reason?: string | undefined;
-};
-
-export interface BanModeratorSchema {
- id: string;
- user_id: string;
- guild_id: string;
- executor_id: string;
- reason?: string | undefined;
-};
+import { OrmUtils } from "@fosscord/util";
const router: Router = Router();
@@ -32,7 +11,7 @@ const router: Router = Router();
router.get("/", route({ permission: "BAN_MEMBERS" }), async (req: Request, res: Response) => {
const { guild_id } = req.params;
- let bans = await Ban.find({ guild_id: guild_id });
+ let bans = await Ban.find({ where: { guild_id } });
let promisesToAwait: object[] = [];
const bansObj: object[] = [];
@@ -65,7 +44,7 @@ router.get("/:user", route({ permission: "BAN_MEMBERS" }), async (req: Request,
const { guild_id } = req.params;
const user_id = req.params.ban;
- let ban = await Ban.findOneOrFail({ guild_id: guild_id, user_id: user_id }) as BanRegistrySchema;
+ let ban = await Ban.findOneOrFail({ where: { guild_id, user_id } }) as BanRegistrySchema;
if (ban.user_id === ban.executor_id) throw DiscordApiErrors.UNKNOWN_BAN;
// pretend self-bans don't exist to prevent victim chasing
@@ -90,7 +69,7 @@ router.put("/:user_id", route({ body: "BanCreateSchema", permission: "BAN_MEMBER
const banned_user = await User.getPublicUser(banned_user_id);
- const ban = new Ban({
+ const ban = OrmUtils.mergeDeep(new Ban(),{
user_id: banned_user_id,
guild_id: guild_id,
ip: getIpAdress(req),
@@ -122,7 +101,7 @@ router.put("/@me", route({ body: "BanCreateSchema"}), async (req: Request, res:
if (req.permission!.cache.guild?.owner_id === req.params.user_id)
throw new HTTPError("You are the guild owner, hence can't ban yourself", 403);
- const ban = new Ban({
+ const ban = OrmUtils.mergeDeep(new Ban(), {
user_id: req.params.user_id,
guild_id: guild_id,
ip: getIpAdress(req),
@@ -149,7 +128,7 @@ router.put("/@me", route({ body: "BanCreateSchema"}), async (req: Request, res:
router.delete("/:user_id", route({ permission: "BAN_MEMBERS" }), async (req: Request, res: Response) => {
const { guild_id, user_id } = req.params;
- let ban = await Ban.findOneOrFail({ guild_id: guild_id, user_id: user_id });
+ let ban = await Ban.findOneOrFail({ where: { guild_id, user_id } });
if (ban.user_id === ban.executor_id) throw DiscordApiErrors.UNKNOWN_BAN;
// make self-bans irreversible and hide them from view to avoid victim chasing
diff --git a/api/src/routes/guilds/#guild_id/channels.ts b/src/api/routes/guilds/#guild_id/channels.ts
index a921fa21..8f2d3643 100644
--- a/api/src/routes/guilds/#guild_id/channels.ts
+++ b/src/api/routes/guilds/#guild_id/channels.ts
@@ -1,13 +1,12 @@
import { Router, Response, Request } from "express";
-import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { Channel, ChannelUpdateEvent, getPermission, emitEvent, ChannelModifySchema, ChannelReorderSchema } from "@fosscord/util";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params;
- const channels = await Channel.find({ guild_id });
+ const channels = await Channel.find({ where: { guild_id } });
res.json(channels);
});
@@ -22,8 +21,6 @@ router.post("/", route({ body: "ChannelModifySchema", permission: "MANAGE_CHANNE
res.status(201).json(channel);
});
-export type ChannelReorderSchema = { id: string; position?: number; lock_permissions?: boolean; parent_id?: string }[];
-
router.patch("/", route({ body: "ChannelReorderSchema", permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => {
// changes guild channel position
const { guild_id } = req.params;
@@ -48,7 +45,7 @@ router.patch("/", route({ body: "ChannelReorderSchema", permission: "MANAGE_CHAN
}
await Channel.update({ guild_id, id: x.id }, opts);
- const channel = await Channel.findOneOrFail({ guild_id, id: x.id });
+ const channel = await Channel.findOneOrFail({ where: { guild_id, id: x.id } });
await emitEvent({ event: "CHANNEL_UPDATE", data: channel, channel_id: x.id, guild_id } as ChannelUpdateEvent);
})
diff --git a/api/src/routes/guilds/#guild_id/delete.ts b/src/api/routes/guilds/#guild_id/delete.ts
index bd158c56..e2624651 100644
--- a/api/src/routes/guilds/#guild_id/delete.ts
+++ b/src/api/routes/guilds/#guild_id/delete.ts
@@ -1,6 +1,6 @@
import { Channel, emitEvent, GuildDeleteEvent, Guild, Member, Message, Role, Invite, Emoji } from "@fosscord/util";
import { Router, Request, Response } from "express";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
const router = Router();
@@ -8,7 +8,7 @@ const router = Router();
// discord prefixes this route with /delete instead of using the delete method
// docs are wrong https://discord.com/developers/docs/resources/guild#delete-guild
router.post("/", route({}), async (req: Request, res: Response) => {
- var { guild_id } = req.params;
+ let { guild_id } = req.params;
const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: ["owner_id"] });
if (guild.owner_id !== req.user_id) throw new HTTPError("You are not the owner of this guild", 401);
diff --git a/api/src/routes/guilds/#guild_id/discovery-requirements.ts b/src/api/routes/guilds/#guild_id/discovery-requirements.ts
index ad20633f..ad20633f 100644
--- a/api/src/routes/guilds/#guild_id/discovery-requirements.ts
+++ b/src/api/routes/guilds/#guild_id/discovery-requirements.ts
diff --git a/api/src/routes/guilds/#guild_id/emojis.ts b/src/api/routes/guilds/#guild_id/emojis.ts
index 85d7ac05..4bf4bdcd 100644
--- a/api/src/routes/guilds/#guild_id/emojis.ts
+++ b/src/api/routes/guilds/#guild_id/emojis.ts
@@ -1,21 +1,10 @@
import { Router, Request, Response } from "express";
-import { Config, DiscordApiErrors, emitEvent, Emoji, GuildEmojisUpdateEvent, handleFile, Member, Snowflake, User } from "@fosscord/util";
+import { Config, DiscordApiErrors, emitEvent, Emoji, EmojiCreateSchema, EmojiModifySchema, GuildEmojisUpdateEvent, handleFile, Member, Snowflake, User } from "@fosscord/util";
import { route } from "@fosscord/api";
+import { OrmUtils } from "@fosscord/util";
const router = Router();
-export interface EmojiCreateSchema {
- name?: string;
- image: string;
- require_colons?: boolean | null;
- roles?: string[];
-}
-
-export interface EmojiModifySchema {
- name?: string;
- roles?: string[];
-}
-
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params;
@@ -41,16 +30,16 @@ router.post("/", route({ body: "EmojiCreateSchema", permission: "MANAGE_EMOJIS_A
const body = req.body as EmojiCreateSchema;
const id = Snowflake.generate();
- const emoji_count = await Emoji.count({ guild_id: guild_id });
+ const emoji_count = await Emoji.count({ where: { guild_id } });
const { maxEmojis } = Config.get().limits.guild;
if (emoji_count >= maxEmojis) throw DiscordApiErrors.MAXIMUM_NUMBER_OF_EMOJIS_REACHED.withParams(maxEmojis);
if (body.require_colons == null) body.require_colons = true;
- const user = await User.findOneOrFail({ id: req.user_id });
+ const user = await User.findOneOrFail({ where: { id: req.user_id } });
body.image = (await handleFile(`/emojis/${id}`, body.image)) as string;
- const emoji = await new Emoji({
+ const emoji = await OrmUtils.mergeDeep(new Emoji(), {
id: id,
guild_id: guild_id,
...body,
@@ -66,7 +55,7 @@ router.post("/", route({ body: "EmojiCreateSchema", permission: "MANAGE_EMOJIS_A
guild_id: guild_id,
data: {
guild_id: guild_id,
- emojis: await Emoji.find({ guild_id: guild_id })
+ emojis: await Emoji.find({ where: { guild_id } })
}
} as GuildEmojisUpdateEvent);
@@ -80,14 +69,14 @@ router.patch(
const { emoji_id, guild_id } = req.params;
const body = req.body as EmojiModifySchema;
- const emoji = await new Emoji({ ...body, id: emoji_id, guild_id: guild_id }).save();
+ const emoji = await OrmUtils.mergeDeep(new Emoji(), { ...body, id: emoji_id, guild_id: guild_id }).save();
await emitEvent({
event: "GUILD_EMOJIS_UPDATE",
guild_id: guild_id,
data: {
guild_id: guild_id,
- emojis: await Emoji.find({ guild_id: guild_id })
+ emojis: await Emoji.find({ where: { guild_id } })
}
} as GuildEmojisUpdateEvent);
@@ -108,7 +97,7 @@ router.delete("/:emoji_id", route({ permission: "MANAGE_EMOJIS_AND_STICKERS" }),
guild_id: guild_id,
data: {
guild_id: guild_id,
- emojis: await Emoji.find({ guild_id: guild_id })
+ emojis: await Emoji.find({ where: { guild_id } })
}
} as GuildEmojisUpdateEvent);
diff --git a/api/src/routes/guilds/#guild_id/index.ts b/src/api/routes/guilds/#guild_id/index.ts
index be556fb2..a9712c71 100644
--- a/api/src/routes/guilds/#guild_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/index.ts
@@ -1,34 +1,17 @@
import { Request, Response, Router } from "express";
-import { DiscordApiErrors, emitEvent, getPermission, getRights, Guild, GuildUpdateEvent, handleFile, Member } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { DiscordApiErrors, emitEvent, getPermission, getRights, Guild, GuildUpdateEvent, GuildUpdateSchema, handleFile, Member } from "@fosscord/util";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
-import "missing-native-js-functions";
-import { GuildCreateSchema } from "../index";
+import { OrmUtils } from "@fosscord/util";
const router = Router();
-export interface GuildUpdateSchema extends Omit<GuildCreateSchema, "channels" | "name"> {
- name?: string;
- banner?: string | null;
- splash?: string | null;
- description?: string;
- features?: string[];
- verification_level?: number;
- default_message_notifications?: number;
- system_channel_flags?: number;
- explicit_content_filter?: number;
- public_updates_channel_id?: string;
- afk_timeout?: number;
- afk_channel_id?: string;
- preferred_locale?: string;
-}
-
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params;
const [guild, member] = await Promise.all([
- Guild.findOneOrFail({ id: guild_id }),
- Member.findOne({ guild_id: guild_id, id: req.user_id })
+ Guild.findOneOrFail({ where: { id: guild_id } }),
+ Member.findOne({ where: { guild_id, id: req.user_id } })
]);
if (!member) throw new HTTPError("You are not a member of the guild you are trying to access", 401);
@@ -55,14 +38,15 @@ router.patch("/", route({ body: "GuildUpdateSchema"}), async (req: Request, res:
if (body.banner) body.banner = await handleFile(`/banners/${guild_id}`, body.banner);
if (body.splash) body.splash = await handleFile(`/splashes/${guild_id}`, body.splash);
- var guild = await Guild.findOneOrFail({
+ let guild = await Guild.findOneOrFail({
where: { id: guild_id },
relations: ["emojis", "roles", "stickers"]
});
// TODO: check if body ids are valid
- guild.assign(body);
+ guild = OrmUtils.mergeDeep(guild, body);
- const data = guild.toJSON();
+ //TODO: check this, removed toJSON call
+ const data = JSON.parse(JSON.stringify(guild));
// TODO: guild hashes
// TODO: fix vanity_url_code, template_id
delete data.vanity_url_code;
diff --git a/api/src/routes/guilds/#guild_id/integrations.ts b/src/api/routes/guilds/#guild_id/integrations.ts
index abf997c9..90650111 100644
--- a/api/src/routes/guilds/#guild_id/integrations.ts
+++ b/src/api/routes/guilds/#guild_id/integrations.ts
@@ -1,8 +1,7 @@
import { Router, Response, Request } from "express";
import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
const router = Router();
//TODO: implement integrations list
diff --git a/api/src/routes/guilds/#guild_id/invites.ts b/src/api/routes/guilds/#guild_id/invites.ts
index b7534e31..b7534e31 100644
--- a/api/src/routes/guilds/#guild_id/invites.ts
+++ b/src/api/routes/guilds/#guild_id/invites.ts
diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/index.ts b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts
index c285abb3..794369d8 100644
--- a/api/src/routes/guilds/#guild_id/members/#member_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts
@@ -1,19 +1,16 @@
import { Request, Response, Router } from "express";
-import { Member, getPermission, getRights, Role, GuildMemberUpdateEvent, emitEvent, Sticker, Emoji, Rights, Guild } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { Member, getPermission, getRights, Role, GuildMemberUpdateEvent, emitEvent, Sticker, Emoji, Rights, Guild, MemberChangeSchema } from "@fosscord/util";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
+import { OrmUtils } from "@fosscord/util";
const router = Router();
-export interface MemberChangeSchema {
- roles?: string[];
-}
-
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id, member_id } = req.params;
await Member.IsInGuildOrFail(req.user_id, guild_id);
- const member = await Member.findOneOrFail({ id: member_id, guild_id });
+ const member = await Member.findOneOrFail({ where: { id: member_id, guild_id } });
return res.json(member);
});
@@ -25,13 +22,13 @@ router.patch("/", route({ body: "MemberChangeSchema" }), async (req: Request, re
const member = await Member.findOneOrFail({ where: { id: member_id, guild_id }, relations: ["roles", "user"] });
const permission = await getPermission(req.user_id, guild_id);
- const everyone = await Role.findOneOrFail({ guild_id: guild_id, name: "@everyone", position: 0 });
+ const everyone = await Role.findOneOrFail({ where: { guild_id: guild_id, name: "@everyone", position: 0 } });
if (body.roles) {
permission.hasThrow("MANAGE_ROLES");
if (body.roles.indexOf(everyone.id) === -1) body.roles.push(everyone.id);
- member.roles = body.roles.map((x) => new Role({ id: x })); // foreign key constraint will fail if role doesn't exist
+ member.roles = body.roles.map((x) => OrmUtils.mergeDeep(new Role(), { id: x })); // foreign key constraint will fail if role doesn't exist
}
await member.save();
@@ -62,19 +59,19 @@ router.put("/", route({}), async (req: Request, res: Response) => {
// TODO: join others by controller
}
- var guild = await Guild.findOneOrFail({
+ let guild = await Guild.findOneOrFail({
where: { id: guild_id }
});
- var emoji = await Emoji.find({
+ let emoji = await Emoji.find({
where: { guild_id: guild_id }
});
- var roles = await Role.find({
+ let roles = await Role.find({
where: { guild_id: guild_id }
});
- var stickers = await Sticker.find({
+ let stickers = await Sticker.find({
where: { guild_id: guild_id }
});
diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts b/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts
index 27f7f65d..a6c71333 100644
--- a/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts
+++ b/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts
@@ -4,13 +4,9 @@ import { Request, Response, Router } from "express";
const router = Router();
-export interface MemberNickChangeSchema {
- nick: string;
-}
-
router.patch("/", route({ body: "MemberNickChangeSchema" }), async (req: Request, res: Response) => {
- var { guild_id, member_id } = req.params;
- var permissionString: PermissionResolvable = "MANAGE_NICKNAMES";
+ let { guild_id, member_id } = req.params;
+ let permissionString: PermissionResolvable = "MANAGE_NICKNAMES";
if (member_id === "@me") {
member_id = req.user_id;
permissionString = "CHANGE_NICKNAME";
diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts b/src/api/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts
index 8f5ca7ba..8f5ca7ba 100644
--- a/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts
diff --git a/api/src/routes/guilds/#guild_id/members/index.ts b/src/api/routes/guilds/#guild_id/members/index.ts
index b730a4e7..2ed28bda 100644
--- a/api/src/routes/guilds/#guild_id/members/index.ts
+++ b/src/api/routes/guilds/#guild_id/members/index.ts
@@ -2,7 +2,7 @@ import { Request, Response, Router } from "express";
import { Guild, Member, PublicMemberProjection } from "@fosscord/util";
import { route } from "@fosscord/api";
import { MoreThan } from "typeorm";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
const router = Router();
diff --git a/api/src/routes/guilds/#guild_id/premium.ts b/src/api/routes/guilds/#guild_id/premium.ts
index 75361ac6..75361ac6 100644
--- a/api/src/routes/guilds/#guild_id/premium.ts
+++ b/src/api/routes/guilds/#guild_id/premium.ts
diff --git a/api/src/routes/guilds/#guild_id/prune.ts b/src/api/routes/guilds/#guild_id/prune.ts
index 0e587d22..673f022f 100644
--- a/api/src/routes/guilds/#guild_id/prune.ts
+++ b/src/api/routes/guilds/#guild_id/prune.ts
@@ -6,16 +6,16 @@ const router = Router();
//Returns all inactive members, respecting role hierarchy
export const inactiveMembers = async (guild_id: string, user_id: string, days: number, roles: string[] = []) => {
- var date = new Date();
+ let date = new Date();
date.setDate(date.getDate() - days);
//Snowflake should have `generateFromTime` method? Or similar?
- var minId = BigInt(date.valueOf() - Snowflake.EPOCH) << BigInt(22);
+ let minId = BigInt(date.valueOf() - Snowflake.EPOCH) << BigInt(22);
/**
idea: ability to customise the cutoff variable
possible candidates: public read receipt, last presence, last VC leave
**/
- var members = await Member.find({
+ let members = await Member.find({
where: [
{
guild_id,
@@ -33,7 +33,7 @@ export const inactiveMembers = async (guild_id: string, user_id: string, days: n
//I'm sure I can do this in the above db query ( and it would probably be better to do so ), but oh well.
if (roles.length && members.length) members = members.filter((user) => user.roles?.some((role) => roles.includes(role.id)));
- const me = await Member.findOneOrFail({ id: user_id, guild_id }, { relations: ["roles"] });
+ const me = await Member.findOneOrFail({ where: { id: user_id, guild_id }, relations: ["roles"] });
const myHighestRole = Math.max(...(me.roles?.map((x) => x.position) || []));
const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
@@ -54,7 +54,7 @@ export const inactiveMembers = async (guild_id: string, user_id: string, days: n
router.get("/", route({}), async (req: Request, res: Response) => {
const days = parseInt(req.query.days as string);
- var roles = req.query.include_roles;
+ let roles = req.query.include_roles;
if (typeof roles === "string") roles = [roles]; //express will return array otherwise
const members = await inactiveMembers(req.params.guild_id, req.user_id, days, roles as string[]);
@@ -62,17 +62,10 @@ router.get("/", route({}), async (req: Request, res: Response) => {
res.send({ pruned: members.length });
});
-export interface PruneSchema {
- /**
- * @min 0
- */
- days: number;
-}
-
router.post("/", route({ permission: "KICK_MEMBERS", right: "KICK_BAN_MEMBERS" }), async (req: Request, res: Response) => {
const days = parseInt(req.body.days);
- var roles = req.query.include_roles;
+ let roles = req.query.include_roles;
if (typeof roles === "string") roles = [roles];
const { guild_id } = req.params;
diff --git a/api/src/routes/guilds/#guild_id/regions.ts b/src/api/routes/guilds/#guild_id/regions.ts
index 75d24fd1..308d5ee5 100644
--- a/api/src/routes/guilds/#guild_id/regions.ts
+++ b/src/api/routes/guilds/#guild_id/regions.ts
@@ -7,7 +7,7 @@ const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ id: guild_id });
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
//TODO we should use an enum for guild's features and not hardcoded strings
return res.json(await getVoiceRegions(getIpAdress(req), guild.features.includes("VIP_REGIONS")));
});
diff --git a/api/src/routes/guilds/#guild_id/roles/#role_id/index.ts b/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts
index 2ad01682..d4422a9c 100644
--- a/api/src/routes/guilds/#guild_id/roles/#role_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts
@@ -1,15 +1,15 @@
import { Router, Request, Response } from "express";
-import { Role, Member, GuildRoleUpdateEvent, GuildRoleDeleteEvent, emitEvent, handleFile } from "@fosscord/util";
+import { Role, Member, GuildRoleUpdateEvent, GuildRoleDeleteEvent, emitEvent, handleFile, RoleModifySchema } from "@fosscord/util";
import { route } from "@fosscord/api";
-import { HTTPError } from "lambert-server";
-import { RoleModifySchema } from "../";
+import { HTTPError } from "@fosscord/util";
+import { OrmUtils } from "@fosscord/util";
const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id, role_id } = req.params;
await Member.IsInGuildOrFail(req.user_id, guild_id);
- const role = await Role.findOneOrFail({ guild_id, id: role_id });
+ const role = await Role.findOneOrFail({ where: { guild_id, id: role_id } });
return res.json(role);
});
@@ -43,7 +43,7 @@ router.patch("/", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" }
if (body.icon) body.icon = await handleFile(`/role-icons/${role_id}`, body.icon as string);
- const role = new Role({
+ const role = OrmUtils.mergeDeep(new Role(), {
...body,
id: role_id,
guild_id,
diff --git a/api/src/routes/guilds/#guild_id/roles/index.ts b/src/api/routes/guilds/#guild_id/roles/index.ts
index 53465105..17f0b5e9 100644
--- a/api/src/routes/guilds/#guild_id/roles/index.ts
+++ b/src/api/routes/guilds/#guild_id/roles/index.ts
@@ -9,35 +9,22 @@ import {
emitEvent,
Config,
DiscordApiErrors,
- handleFile
+ handleFile,
+ RoleModifySchema,
+ RolePositionUpdateSchema
} from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
+import { OrmUtils } from "@fosscord/util";
const router: Router = Router();
-export interface RoleModifySchema {
- name?: string;
- permissions?: string;
- color?: number;
- hoist?: boolean; // whether the role should be displayed separately in the sidebar
- mentionable?: boolean; // whether the role should be mentionable
- position?: number;
- icon?: string;
- unicode_emoji?: string;
-}
-
-export type RolePositionUpdateSchema = {
- id: string;
- position: number;
-}[];
-
router.get("/", route({}), async (req: Request, res: Response) => {
const guild_id = req.params.guild_id;
await Member.IsInGuildOrFail(req.user_id, guild_id);
- const roles = await Role.find({ guild_id: guild_id });
+ const roles = await Role.find({ where: { guild_id } });
return res.json(roles);
});
@@ -46,12 +33,12 @@ router.post("/", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" })
const guild_id = req.params.guild_id;
const body = req.body as RoleModifySchema;
- const role_count = await Role.count({ guild_id });
+ const role_count = await Role.count({ where: { guild_id } });
const { maxRoles } = Config.get().limits.guild;
if (role_count > maxRoles) throw DiscordApiErrors.MAXIMUM_ROLES.withParams(maxRoles);
- const role = new Role({
+ let role: Role = OrmUtils.mergeDeep(new Role(),{
// values before ...body are default and can be overriden
position: 0,
hoist: false,
diff --git a/api/src/routes/guilds/#guild_id/stickers.ts b/src/api/routes/guilds/#guild_id/stickers.ts
index 4ea1dce1..71c9dfcd 100644
--- a/api/src/routes/guilds/#guild_id/stickers.ts
+++ b/src/api/routes/guilds/#guild_id/stickers.ts
@@ -3,6 +3,7 @@ import {
GuildStickersUpdateEvent,
handleFile,
Member,
+ ModifyGuildStickerSchema,
Snowflake,
Sticker,
StickerFormatType,
@@ -12,14 +13,15 @@ import {
import { Router, Request, Response } from "express";
import { route } from "@fosscord/api";
import multer from "multer";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
+import { OrmUtils } from "@fosscord/util";
const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params;
await Member.IsInGuildOrFail(req.user_id, guild_id);
- res.json(await Sticker.find({ guild_id }));
+ res.json(await Sticker.find({ where: { guild_id } }));
});
const bodyParser = multer({
@@ -43,7 +45,7 @@ router.post(
const id = Snowflake.generate();
const [sticker] = await Promise.all([
- new Sticker({
+ OrmUtils.mergeDeep(new Sticker(), {
...body,
guild_id,
id,
@@ -79,25 +81,9 @@ router.get("/:sticker_id", route({}), async (req: Request, res: Response) => {
const { guild_id, sticker_id } = req.params;
await Member.IsInGuildOrFail(req.user_id, guild_id);
- res.json(await Sticker.findOneOrFail({ guild_id, id: sticker_id }));
+ res.json(await Sticker.findOneOrFail({ where: { guild_id, id: sticker_id } }));
});
-export interface ModifyGuildStickerSchema {
- /**
- * @minLength 2
- * @maxLength 30
- */
- name: string;
- /**
- * @maxLength 100
- */
- description?: string;
- /**
- * @maxLength 200
- */
- tags: string;
-}
-
router.patch(
"/:sticker_id",
route({ body: "ModifyGuildStickerSchema", permission: "MANAGE_EMOJIS_AND_STICKERS" }),
@@ -105,7 +91,7 @@ router.patch(
const { guild_id, sticker_id } = req.params;
const body = req.body as ModifyGuildStickerSchema;
- const sticker = await new Sticker({ ...body, guild_id, id: sticker_id }).save();
+ const sticker = await OrmUtils.mergeDeep(new Sticker(), { ...body, guild_id, id: sticker_id }).save();
await sendStickerUpdateEvent(guild_id);
return res.json(sticker);
@@ -118,7 +104,7 @@ async function sendStickerUpdateEvent(guild_id: string) {
guild_id: guild_id,
data: {
guild_id: guild_id,
- stickers: await Sticker.find({ guild_id: guild_id })
+ stickers: await Sticker.find({ where: { guild_id } })
}
} as GuildStickersUpdateEvent);
}
diff --git a/api/src/routes/guilds/#guild_id/templates.ts b/src/api/routes/guilds/#guild_id/templates.ts
index 5179e761..9c79692d 100644
--- a/api/src/routes/guilds/#guild_id/templates.ts
+++ b/src/api/routes/guilds/#guild_id/templates.ts
@@ -1,8 +1,9 @@
import { Request, Response, Router } from "express";
import { Guild, Template } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
import { generateCode } from "@fosscord/api";
+import { OrmUtils } from "@fosscord/util";
const router: Router = Router();
@@ -23,20 +24,10 @@ const TemplateGuildProjection: (keyof Guild)[] = [
"icon"
];
-export interface TemplateCreateSchema {
- name: string;
- description?: string;
-}
-
-export interface TemplateModifySchema {
- name: string;
- description?: string;
-}
-
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params;
- var templates = await Template.find({ source_guild_id: guild_id });
+ let templates = await Template.find({ where: { source_guild_id: guild_id } });
return res.json(templates);
});
@@ -44,10 +35,10 @@ router.get("/", route({}), async (req: Request, res: Response) => {
router.post("/", route({ body: "TemplateCreateSchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => {
const { guild_id } = req.params;
const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: TemplateGuildProjection });
- const exists = await Template.findOneOrFail({ id: guild_id }).catch((e) => {});
+ const exists = await Template.findOneOrFail({ where: { id: guild_id } }).catch((e) => {});
if (exists) throw new HTTPError("Template already exists", 400);
- const template = await new Template({
+ const template = await OrmUtils.mergeDeep(new Template(), {
...req.body,
code: generateCode(),
creator_id: req.user_id,
@@ -75,7 +66,7 @@ router.put("/:code", route({ permission: "MANAGE_GUILD" }), async (req: Request,
const { code, guild_id } = req.params;
const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: TemplateGuildProjection });
- const template = await new Template({ code, serialized_source_guild: guild }).save();
+ const template = await OrmUtils.mergeDeep(new Template(), { code, serialized_source_guild: guild }).save();
res.json(template);
});
@@ -84,7 +75,7 @@ router.patch("/:code", route({ body: "TemplateModifySchema", permission: "MANAGE
const { code, guild_id } = req.params;
const { name, description } = req.body;
- const template = await new Template({ code, name: name, description: description, source_guild_id: guild_id }).save();
+ const template = await OrmUtils.mergeDeep(new Template(), { code, name: name, description: description, source_guild_id: guild_id }).save();
res.json(template);
});
diff --git a/api/src/routes/guilds/#guild_id/vanity-url.ts b/src/api/routes/guilds/#guild_id/vanity-url.ts
index 29cd25e2..ff92ce8d 100644
--- a/api/src/routes/guilds/#guild_id/vanity-url.ts
+++ b/src/api/routes/guilds/#guild_id/vanity-url.ts
@@ -1,7 +1,8 @@
-import { Channel, ChannelType, getPermission, Guild, Invite, trimSpecial } from "@fosscord/util";
+import { Channel, ChannelType, getPermission, Guild, Invite, trimSpecial, VanityUrlSchema } from "@fosscord/util";
import { Router, Request, Response } from "express";
import { route } from "@fosscord/api";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
+import { OrmUtils } from "@fosscord/util";
const router = Router();
@@ -9,7 +10,7 @@ const InviteRegex = /\W/g;
router.get("/", route({ permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => {
const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ id: guild_id });
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
if (!guild.features.includes("ALIASABLE_NAMES")) {
const invite = await Invite.findOne({ where: { guild_id: guild_id, vanity_url: true } });
@@ -24,30 +25,22 @@ router.get("/", route({ permission: "MANAGE_GUILD" }), async (req: Request, res:
}
});
-export interface VanityUrlSchema {
- /**
- * @minLength 1
- * @maxLength 20
- */
- code?: string;
-}
-
router.patch("/", route({ body: "VanityUrlSchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => {
const { guild_id } = req.params;
const body = req.body as VanityUrlSchema;
const code = body.code?.replace(InviteRegex, "");
- const guild = await Guild.findOneOrFail({ id: guild_id });
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
if (!guild.features.includes("VANITY_URL")) throw new HTTPError("Your guild doesn't support vanity urls");
if (!code || code.length === 0) throw new HTTPError("Code cannot be null or empty");
- const invite = await Invite.findOne({ code });
+ const invite = await Invite.findOne({ where: { code } });
if (invite) throw new HTTPError("Invite already exists");
- const { id } = await Channel.findOneOrFail({ guild_id, type: ChannelType.GUILD_TEXT });
+ const { id } = await Channel.findOneOrFail({ where: { guild_id, type: ChannelType.GUILD_TEXT } });
- await new Invite({
+ await OrmUtils.mergeDeep(new Invite(), {
vanity_url: true,
code: code,
temporary: false,
@@ -60,7 +53,7 @@ router.patch("/", route({ body: "VanityUrlSchema", permission: "MANAGE_GUILD" })
channel_id: id
}).save();
- return res.json({ code: code });
+ return res.json({ where: { code } });
});
export default router;
diff --git a/api/src/routes/guilds/#guild_id/voice-states/#user_id/index.ts b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts
index f9fbea54..28a9e8c1 100644
--- a/api/src/routes/guilds/#guild_id/voice-states/#user_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts
@@ -1,23 +1,12 @@
-import { Channel, ChannelType, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent } from "@fosscord/util";
+import { Channel, ChannelType, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent, VoiceStateUpdateSchema } from "@fosscord/util";
import { route } from "@fosscord/api";
import { Request, Response, Router } from "express";
+import { OrmUtils } from "@fosscord/util";
const router = Router();
-//TODO need more testing when community guild and voice stage channel are working
-
-export interface VoiceStateUpdateSchema {
- channel_id: string;
- guild_id?: string;
- suppress?: boolean;
- request_to_speak_timestamp?: Date;
- self_mute?: boolean;
- self_deaf?: boolean;
- self_video?: boolean;
-}
-
router.patch("/", route({ body: "VoiceStateUpdateSchema" }), async (req: Request, res: Response) => {
const body = req.body as VoiceStateUpdateSchema;
- var { guild_id, user_id } = req.params;
+ let { guild_id, user_id } = req.params;
if (user_id === "@me") user_id = req.user_id;
const perms = await getPermission(req.user_id, guild_id, body.channel_id);
@@ -33,15 +22,17 @@ router.patch("/", route({ body: "VoiceStateUpdateSchema" }), async (req: Request
if (!body.suppress) body.request_to_speak_timestamp = new Date();
if (body.request_to_speak_timestamp) perms.hasThrow("REQUEST_TO_SPEAK");
- const voice_state = await VoiceState.findOne({
- guild_id,
- channel_id: body.channel_id,
- user_id
+ let voice_state = await VoiceState.findOne({
+ where: {
+ guild_id,
+ channel_id: body.channel_id,
+ user_id
+ }
});
if (!voice_state) throw DiscordApiErrors.UNKNOWN_VOICE_STATE;
- voice_state.assign(body);
- const channel = await Channel.findOneOrFail({ guild_id, id: body.channel_id });
+ voice_state = OrmUtils.mergeDeep(voice_state, body) as VoiceState;
+ const channel = await Channel.findOneOrFail({ where: { guild_id, id: body.channel_id } });
if (channel.type !== ChannelType.GUILD_STAGE_VOICE) {
throw DiscordApiErrors.CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE;
}
diff --git a/api/src/routes/guilds/#guild_id/webhooks.ts b/src/api/routes/guilds/#guild_id/webhooks.ts
index 8b2febea..c8c1eb5c 100644
--- a/api/src/routes/guilds/#guild_id/webhooks.ts
+++ b/src/api/routes/guilds/#guild_id/webhooks.ts
@@ -1,8 +1,7 @@
import { Router, Response, Request } from "express";
import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
const router = Router();
//TODO: implement webhooks
diff --git a/api/src/routes/guilds/#guild_id/welcome_screen.ts b/src/api/routes/guilds/#guild_id/welcome_screen.ts
index 7141f17e..d08300ba 100644
--- a/api/src/routes/guilds/#guild_id/welcome_screen.ts
+++ b/src/api/routes/guilds/#guild_id/welcome_screen.ts
@@ -1,25 +1,14 @@
import { Request, Response, Router } from "express";
-import { Guild, getPermission, Snowflake, Member } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { Guild, getPermission, Snowflake, Member, GuildUpdateWelcomeScreenSchema } from "@fosscord/util";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
const router: Router = Router();
-export interface GuildUpdateWelcomeScreenSchema {
- welcome_channels?: {
- channel_id: string;
- description: string;
- emoji_id?: string;
- emoji_name: string;
- }[];
- enabled?: boolean;
- description?: string;
-}
-
router.get("/", route({}), async (req: Request, res: Response) => {
const guild_id = req.params.guild_id;
- const guild = await Guild.findOneOrFail({ id: guild_id });
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
await Member.IsInGuildOrFail(req.user_id, guild_id);
res.json(guild.welcome_screen);
@@ -29,7 +18,7 @@ router.patch("/", route({ body: "GuildUpdateWelcomeScreenSchema", permission: "M
const guild_id = req.params.guild_id;
const body = req.body as GuildUpdateWelcomeScreenSchema;
- const guild = await Guild.findOneOrFail({ id: guild_id });
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
if (!guild.welcome_screen.enabled) throw new HTTPError("Welcome screen disabled", 400);
if (body.welcome_channels) guild.welcome_screen.welcome_channels = body.welcome_channels; // TODO: check if they exist and are valid
diff --git a/api/src/routes/guilds/#guild_id/widget.json.ts b/src/api/routes/guilds/#guild_id/widget.json.ts
index c31519fa..37739418 100644
--- a/api/src/routes/guilds/#guild_id/widget.json.ts
+++ b/src/api/routes/guilds/#guild_id/widget.json.ts
@@ -1,7 +1,8 @@
import { Request, Response, Router } from "express";
import { Config, Permissions, Guild, Invite, Channel, Member } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { random, route } from "@fosscord/api";
+import { OrmUtils } from "@fosscord/util";
const router: Router = Router();
@@ -17,11 +18,11 @@ const router: Router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ id: guild_id });
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
if (!guild.widget_enabled) throw new HTTPError("Widget Disabled", 404);
// Fetch existing widget invite for widget channel
- var invite = await Invite.findOne({ channel_id: guild.widget_channel_id });
+ let invite = await Invite.findOne({ where: { channel_id: guild.widget_channel_id } });
if (guild.widget_channel_id && !invite) {
// Create invite for channel if none exists
@@ -41,7 +42,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
inviter_id: null
};
- invite = await new Invite(body).save();
+ invite = await OrmUtils.mergeDeep(new Invite(), body).save();
}
// Fetch voice channels, and the @everyone permissions object
@@ -63,7 +64,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
// Fetch members
// TODO: Understand how Discord's max 100 random member sample works, and apply to here (see top of this file)
- let members = await Member.find({ guild_id: guild_id });
+ let members = await Member.find({ where: { guild_id } });
// Construct object to respond with
const data = {
diff --git a/api/src/routes/guilds/#guild_id/widget.png.ts b/src/api/routes/guilds/#guild_id/widget.png.ts
index 4c82b740..a61d938d 100644
--- a/api/src/routes/guilds/#guild_id/widget.png.ts
+++ b/src/api/routes/guilds/#guild_id/widget.png.ts
@@ -1,6 +1,6 @@
import { Request, Response, Router } from "express";
import { Guild } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
import fs from "fs";
import path from "path";
@@ -14,7 +14,7 @@ const router: Router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ id: guild_id });
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
if (!guild.widget_enabled) throw new HTTPError("Unknown Guild", 404);
// Fetch guild information
@@ -34,7 +34,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
const sizeOf = require("image-size");
// TODO: Widget style templates need Fosscord branding
- const source = path.join(__dirname, "..", "..", "..", "..", "assets", "widget", `${style}.png`);
+ const source = path.join(__dirname, "..", "..", "..", "..", "..", "assets", "widget", `${style}.png`);
if (!fs.existsSync(source)) {
throw new HTTPError("Widget template does not exist.", 400);
}
diff --git a/api/src/routes/guilds/#guild_id/widget.ts b/src/api/routes/guilds/#guild_id/widget.ts
index 2640618d..dbb4cc0c 100644
--- a/api/src/routes/guilds/#guild_id/widget.ts
+++ b/src/api/routes/guilds/#guild_id/widget.ts
@@ -1,19 +1,14 @@
import { Request, Response, Router } from "express";
-import { Guild } from "@fosscord/util";
+import { Guild, WidgetModifySchema } from "@fosscord/util";
import { route } from "@fosscord/api";
-export interface WidgetModifySchema {
- enabled: boolean; // whether the widget is enabled
- channel_id: string; // the widget channel id
-}
-
const router: Router = Router();
// https://discord.com/developers/docs/resources/guild#get-guild-widget-settings
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ id: guild_id });
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
return res.json({ enabled: guild.widget_enabled || false, channel_id: guild.widget_channel_id || null });
});
diff --git a/api/src/routes/guilds/index.ts b/src/api/routes/guilds/index.ts
index 10721413..e4d66192 100644
--- a/api/src/routes/guilds/index.ts
+++ b/src/api/routes/guilds/index.ts
@@ -1,30 +1,16 @@
import { Router, Request, Response } from "express";
-import { Role, Guild, Snowflake, Config, getRights, Member, Channel, DiscordApiErrors, handleFile } from "@fosscord/util";
+import { Role, Guild, Snowflake, Config, getRights, Member, Channel, DiscordApiErrors, handleFile, GuildCreateSchema } from "@fosscord/util";
import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../channels/#channel_id";
const router: Router = Router();
-export interface GuildCreateSchema {
- /**
- * @maxLength 100
- */
- name: string;
- region?: string;
- icon?: string | null;
- channels?: ChannelModifySchema[];
- guild_template_code?: string;
- system_channel_id?: string;
- rules_channel_id?: string;
-}
-
//TODO: create default channel
router.post("/", route({ body: "GuildCreateSchema", right: "CREATE_GUILDS" }), async (req: Request, res: Response) => {
const body = req.body as GuildCreateSchema;
const { maxGuilds } = Config.get().limits.user;
- const guild_count = await Member.count({ id: req.user_id });
+ const guild_count = await Member.count({ where: { id: req.user_id } });
const rights = await getRights(req.user_id);
if ((guild_count >= maxGuilds)&&!rights.has("MANAGE_GUILDS")) {
throw DiscordApiErrors.MAXIMUM_GUILDS.withParams(maxGuilds);
diff --git a/api/src/routes/guilds/templates/index.ts b/src/api/routes/guilds/templates/index.ts
index 3d922e85..3a0de9e8 100644
--- a/api/src/routes/guilds/templates/index.ts
+++ b/src/api/routes/guilds/templates/index.ts
@@ -1,15 +1,9 @@
import { Request, Response, Router } from "express";
-import { Template, Guild, Role, Snowflake, Config, User, Member } from "@fosscord/util";
+import { Template, Guild, Role, Snowflake, Config, User, Member, DiscordApiErrors, OrmUtils, GuildTemplateCreateSchema } from "@fosscord/util";
import { route } from "@fosscord/api";
-import { DiscordApiErrors } from "@fosscord/util";
import fetch from "node-fetch";
const router: Router = Router();
-export interface GuildTemplateCreateSchema {
- name: string;
- avatar?: string | null;
-}
-
router.get("/:code", route({}), async (req: Request, res: Response) => {
const { allowDiscordTemplates, allowRaws, enabled } = Config.get().templates;
if (!enabled) res.json({ code: 403, message: "Template creation & usage is disabled on this instance." }).sendStatus(403);
@@ -33,7 +27,7 @@ router.get("/:code", route({}), async (req: Request, res: Response) => {
return res.json(code.split("external:", 2)[1]);
}
- const template = await Template.findOneOrFail({ code: code });
+ const template = await Template.findOneOrFail({ where: { code } });
res.json(template);
});
@@ -47,23 +41,23 @@ router.post("/:code", route({ body: "GuildTemplateCreateSchema" }), async (req:
const { maxGuilds } = Config.get().limits.user;
- const guild_count = await Member.count({ id: req.user_id });
+ const guild_count = await Member.count({ where: { id: req.user_id } });
if (guild_count >= maxGuilds) {
throw DiscordApiErrors.MAXIMUM_GUILDS.withParams(maxGuilds);
}
- const template = await Template.findOneOrFail({ code: code });
+ const template = await Template.findOneOrFail({ where: { code } });
const guild_id = Snowflake.generate();
const [guild, role] = await Promise.all([
- new Guild({
+ OrmUtils.mergeDeep(new Guild(), {
...body,
...template.serialized_source_guild,
id: guild_id,
owner_id: req.user_id
}).save(),
- new Role({
+ (OrmUtils.mergeDeep(new Role(), {
id: guild_id,
guild_id: guild_id,
color: 0,
@@ -74,7 +68,7 @@ router.post("/:code", route({ body: "GuildTemplateCreateSchema" }), async (req:
permissions: BigInt("2251804225"),
position: 0,
tags: null
- }).save()
+ }) as Role).save()
]);
await Member.addToGuild(req.user_id, guild_id);
diff --git a/api/src/routes/invites/index.ts b/src/api/routes/invites/index.ts
index eeafb22a..1b434505 100644
--- a/api/src/routes/invites/index.ts
+++ b/src/api/routes/invites/index.ts
@@ -1,7 +1,7 @@
import { Router, Request, Response } from "express";
import { emitEvent, getPermission, Guild, Invite, InviteDeleteEvent, User, PublicInviteRelation } from "@fosscord/util";
import { route } from "@fosscord/api";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
const router: Router = Router();
@@ -15,9 +15,9 @@ router.get("/:code", route({}), async (req: Request, res: Response) => {
router.post("/:code", route({right: "USE_MASS_INVITES"}), async (req: Request, res: Response) => {
const { code } = req.params;
- const { guild_id } = await Invite.findOneOrFail({ code })
- const { features } = await Guild.findOneOrFail({ id: guild_id});
- const { public_flags } = await User.findOneOrFail({ id: req.user_id });
+ const { guild_id } = await Invite.findOneOrFail({ where: { code } })
+ const { features } = await Guild.findOneOrFail({ where: { id: guild_id} });
+ const { public_flags } = await User.findOneOrFail({ where: { id: req.user_id } });
if(features.includes("INTERNAL_EMPLOYEE_ONLY") && (public_flags & 1) !== 1) throw new HTTPError("Only intended for the staff of this server.", 401);
if(features.includes("INVITES_CLOSED")) throw new HTTPError("Sorry, this guild has joins closed.", 403);
@@ -30,7 +30,7 @@ router.post("/:code", route({right: "USE_MASS_INVITES"}), async (req: Request, r
// * cant use permission of route() function because path doesn't have guild_id/channel_id
router.delete("/:code", route({}), async (req: Request, res: Response) => {
const { code } = req.params;
- const invite = await Invite.findOneOrFail({ code });
+ const invite = await Invite.findOneOrFail({ where: { code } });
const { guild_id, channel_id } = invite;
const permission = await getPermission(req.user_id, guild_id, channel_id);
diff --git a/api/src/routes/oauth2/tokens.ts b/src/api/routes/oauth2/tokens.ts
index bd284221..bd284221 100644
--- a/api/src/routes/oauth2/tokens.ts
+++ b/src/api/routes/oauth2/tokens.ts
diff --git a/api/src/routes/outbound-promotions.ts b/src/api/routes/outbound-promotions.ts
index 411e95bf..411e95bf 100644
--- a/api/src/routes/outbound-promotions.ts
+++ b/src/api/routes/outbound-promotions.ts
diff --git a/api/src/routes/partners/#guild_id/requirements.ts b/src/api/routes/partners/#guild_id/requirements.ts
index 545c5c78..545c5c78 100644
--- a/api/src/routes/partners/#guild_id/requirements.ts
+++ b/src/api/routes/partners/#guild_id/requirements.ts
diff --git a/api/src/routes/ping.ts b/src/api/routes/ping.ts
index 3c1da2c3..3c1da2c3 100644
--- a/api/src/routes/ping.ts
+++ b/src/api/routes/ping.ts
diff --git a/api/src/routes/policies/instance/domains.ts b/src/api/routes/policies/instance/domains.ts
index 20cd07ba..20cd07ba 100644
--- a/api/src/routes/policies/instance/domains.ts
+++ b/src/api/routes/policies/instance/domains.ts
diff --git a/api/src/routes/policies/instance/index.ts b/src/api/routes/policies/instance/index.ts
index e3da014f..e3da014f 100644
--- a/api/src/routes/policies/instance/index.ts
+++ b/src/api/routes/policies/instance/index.ts
diff --git a/api/src/routes/policies/instance/limits.ts b/src/api/routes/policies/instance/limits.ts
index 7de1476b..7de1476b 100644
--- a/api/src/routes/policies/instance/limits.ts
+++ b/src/api/routes/policies/instance/limits.ts
diff --git a/api/src/routes/scheduled-maintenances/upcoming_json.ts b/src/api/routes/scheduled-maintenances/upcoming_json.ts
index 83092e44..83092e44 100644
--- a/api/src/routes/scheduled-maintenances/upcoming_json.ts
+++ b/src/api/routes/scheduled-maintenances/upcoming_json.ts
diff --git a/api/src/routes/science.ts b/src/api/routes/science.ts
index 8556a3ad..8556a3ad 100644
--- a/api/src/routes/science.ts
+++ b/src/api/routes/science.ts
diff --git a/api/src/routes/stage-instances.ts b/src/api/routes/stage-instances.ts
index 411e95bf..411e95bf 100644
--- a/api/src/routes/stage-instances.ts
+++ b/src/api/routes/stage-instances.ts
diff --git a/api/src/routes/sticker-packs/index.ts b/src/api/routes/sticker-packs/index.ts
index e6560d12..e6560d12 100644
--- a/api/src/routes/sticker-packs/index.ts
+++ b/src/api/routes/sticker-packs/index.ts
diff --git a/api/src/routes/stickers/#sticker_id/index.ts b/src/api/routes/stickers/#sticker_id/index.ts
index 293ca089..b484a7a1 100644
--- a/api/src/routes/stickers/#sticker_id/index.ts
+++ b/src/api/routes/stickers/#sticker_id/index.ts
@@ -6,7 +6,7 @@ const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
const { sticker_id } = req.params;
- res.json(await Sticker.find({ id: sticker_id }));
+ res.json(await Sticker.find({ where: { id: sticker_id } }));
});
export default router;
diff --git a/api/src/routes/stop.ts b/src/api/routes/stop.ts
index 7f8b78ba..7f8b78ba 100644
--- a/api/src/routes/stop.ts
+++ b/src/api/routes/stop.ts
diff --git a/api/src/routes/store/published-listings/applications.ts b/src/api/routes/store/published-listings/applications.ts
index 060a4c3d..060a4c3d 100644
--- a/api/src/routes/store/published-listings/applications.ts
+++ b/src/api/routes/store/published-listings/applications.ts
diff --git a/api/src/routes/store/published-listings/applications/#id/subscription-plans.ts b/src/api/routes/store/published-listings/applications/#id/subscription-plans.ts
index 54151ae5..54151ae5 100644
--- a/api/src/routes/store/published-listings/applications/#id/subscription-plans.ts
+++ b/src/api/routes/store/published-listings/applications/#id/subscription-plans.ts
diff --git a/api/src/routes/store/published-listings/skus.ts b/src/api/routes/store/published-listings/skus.ts
index 060a4c3d..060a4c3d 100644
--- a/api/src/routes/store/published-listings/skus.ts
+++ b/src/api/routes/store/published-listings/skus.ts
diff --git a/api/src/routes/store/published-listings/skus/#sku_id/subscription-plans.ts b/src/api/routes/store/published-listings/skus/#sku_id/subscription-plans.ts
index 723a5160..e7f44ded 100644
--- a/api/src/routes/store/published-listings/skus/#sku_id/subscription-plans.ts
+++ b/src/api/routes/store/published-listings/skus/#sku_id/subscription-plans.ts
@@ -9,23 +9,23 @@ const skus = new Map([
[
{
id: "511651856145973248",
- name: "Premium Monthly (Legacy)",
+ name: "Individual Premium Tier 2 Monthly (Legacy)",
interval: 1,
interval_count: 1,
tax_inclusive: true,
sku_id: "521842865731534868",
- currency: "usd",
+ currency: "eur",
price: 0,
price_tier: null
},
{
id: "511651860671627264",
- name: "Premium Yearly (Legacy)",
+ name: "Individiual Premium Tier 2 Yearly (Legacy)",
interval: 2,
interval_count: 1,
tax_inclusive: true,
sku_id: "521842865731534868",
- currency: "usd",
+ currency: "eur",
price: 0,
price_tier: null
}
@@ -36,23 +36,34 @@ const skus = new Map([
[
{
id: "511651871736201216",
- name: "Premium Classic Monthly",
+ name: "Individual Premium Tier 1 Monthly",
interval: 1,
interval_count: 1,
tax_inclusive: true,
sku_id: "521846918637420545",
- currency: "usd",
+ currency: "eur",
price: 0,
price_tier: null
},
{
id: "511651876987469824",
- name: "Premium Classic Yearly",
+ name: "Individual Premum Tier 1 Yearly",
interval: 2,
interval_count: 1,
tax_inclusive: true,
sku_id: "521846918637420545",
- currency: "usd",
+ currency: "eur",
+ price: 0,
+ price_tier: null
+ },
+ {
+ id: "978380684370378761",
+ name: "Individual Premum Tier 0",
+ interval: 2,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "521846918637420545",
+ currency: "eur",
price: 0,
price_tier: null
}
@@ -63,34 +74,34 @@ const skus = new Map([
[
{
id: "642251038925127690",
- name: "Premium Quarterly",
+ name: "Individual Premium Tier 2 Quarterly",
interval: 1,
interval_count: 3,
tax_inclusive: true,
sku_id: "521847234246082599",
- currency: "usd",
+ currency: "eur",
price: 0,
price_tier: null
},
{
id: "511651880837840896",
- name: "Premium Monthly",
+ name: "Individual Premium Tier 2 Monthly",
interval: 1,
interval_count: 1,
tax_inclusive: true,
sku_id: "521847234246082599",
- currency: "usd",
+ currency: "eur",
price: 0,
price_tier: null
},
{
id: "511651885459963904",
- name: "Premium Yearly",
+ name: "Individual Premium Tier 2 Yearly",
interval: 2,
interval_count: 1,
tax_inclusive: true,
sku_id: "521847234246082599",
- currency: "usd",
+ currency: "eur",
price: 0,
price_tier: null
}
@@ -101,25 +112,25 @@ const skus = new Map([
[
{
id: "590665532894740483",
- name: "Server Boost Monthly",
+ name: "Crowd Premium Monthly",
interval: 1,
interval_count: 1,
tax_inclusive: true,
sku_id: "590663762298667008",
discount_price: 0,
- currency: "usd",
+ currency: "eur",
price: 0,
price_tier: null
},
{
id: "590665538238152709",
- name: "Server Boost Yearly",
+ name: "Crowd Premium Yearly",
interval: 2,
interval_count: 1,
tax_inclusive: true,
sku_id: "590663762298667008",
discount_price: 0,
- currency: "usd",
+ currency: "eur",
price: 0,
price_tier: null
}
diff --git a/api/src/routes/teams.ts b/src/api/routes/teams.ts
index 7ce3abcb..7ce3abcb 100644
--- a/api/src/routes/teams.ts
+++ b/src/api/routes/teams.ts
diff --git a/api/src/routes/template.ts.disabled b/src/api/routes/template.ts.disabled
index fcc59ef4..fcc59ef4 100644
--- a/api/src/routes/template.ts.disabled
+++ b/src/api/routes/template.ts.disabled
diff --git a/api/src/routes/track.ts b/src/api/routes/track.ts
index 8556a3ad..8556a3ad 100644
--- a/api/src/routes/track.ts
+++ b/src/api/routes/track.ts
diff --git a/api/src/routes/updates.ts b/src/api/routes/updates.ts
index cb4577c8..a24e94c1 100644
--- a/api/src/routes/updates.ts
+++ b/src/api/routes/updates.ts
@@ -7,7 +7,7 @@ const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
const { client } = Config.get();
- const release = await Release.findOneOrFail({ name: client.releases.upstreamVersion})
+ const release = await Release.findOneOrFail({ where: { name: client.releases.upstreamVersion } })
res.json({
name: release.name,
diff --git a/api/src/routes/users/#id/index.ts b/src/api/routes/users/#id/index.ts
index bdb1060f..bdb1060f 100644
--- a/api/src/routes/users/#id/index.ts
+++ b/src/api/routes/users/#id/index.ts
diff --git a/api/src/routes/users/#id/profile.ts b/src/api/routes/users/#id/profile.ts
index 4dbb84cf..7a995a8c 100644
--- a/api/src/routes/users/#id/profile.ts
+++ b/src/api/routes/users/#id/profile.ts
@@ -15,10 +15,10 @@ router.get("/", route({ test: { response: { body: "UserProfileResponse" } } }),
if (req.params.id === "@me") req.params.id = req.user_id;
const user = await User.getPublicUser(req.params.id, { relations: ["connected_accounts"] });
- var mutual_guilds: object[] = [];
- var premium_guild_since;
- const requested_member = await Member.find( { id: req.params.id, })
- const self_member = await Member.find( { id: req.user_id, })
+ let mutual_guilds: object[] = [];
+ let premium_guild_since;
+ const requested_member = await Member.find( { where: { id: req.params.id, } })
+ const self_member = await Member.find( { where: { id: req.user_id, } })
for(const rmem of requested_member) {
if(rmem.premium_since) {
diff --git a/api/src/routes/users/#id/relationships.ts b/src/api/routes/users/#id/relationships.ts
index de7cb9d3..61655c25 100644
--- a/api/src/routes/users/#id/relationships.ts
+++ b/src/api/routes/users/#id/relationships.ts
@@ -16,7 +16,7 @@ export interface UserRelationsResponse {
router.get("/", route({ test: { response: { body: "UserRelationsResponse" } } }), async (req: Request, res: Response) => {
- var mutual_relations: object[] = [];
+ let mutual_relations: object[] = [];
const requested_relations = await User.findOneOrFail({
where: { id: req.params.id },
relations: ["relationships"]
@@ -29,7 +29,7 @@ router.get("/", route({ test: { response: { body: "UserRelationsResponse" } } })
for(const rmem of requested_relations.relationships) {
for(const smem of self_relations.relationships)
if (rmem.to_id === smem.to_id && rmem.type === 1 && rmem.to_id !== req.user_id) {
- var relation_user = await User.getPublicUser(rmem.to_id)
+ let relation_user = await User.getPublicUser(rmem.to_id)
mutual_relations.push({id: relation_user.id, username: relation_user.username, avatar: relation_user.avatar, discriminator: relation_user.discriminator, public_flags: relation_user.public_flags})
}
diff --git a/api/src/routes/users/@me/activities/statistics/applications.ts b/src/api/routes/users/@me/activities/statistics/applications.ts
index 014df8af..014df8af 100644
--- a/api/src/routes/users/@me/activities/statistics/applications.ts
+++ b/src/api/routes/users/@me/activities/statistics/applications.ts
diff --git a/api/src/routes/users/@me/affinities/guilds.ts b/src/api/routes/users/@me/affinities/guilds.ts
index 8d744744..8d744744 100644
--- a/api/src/routes/users/@me/affinities/guilds.ts
+++ b/src/api/routes/users/@me/affinities/guilds.ts
diff --git a/api/src/routes/users/@me/affinities/users.ts b/src/api/routes/users/@me/affinities/users.ts
index 6d4e4991..6d4e4991 100644
--- a/api/src/routes/users/@me/affinities/users.ts
+++ b/src/api/routes/users/@me/affinities/users.ts
diff --git a/api/src/routes/users/@me/applications/#app_id/entitlements.ts b/src/api/routes/users/@me/applications/#app_id/entitlements.ts
index 411e95bf..411e95bf 100644
--- a/api/src/routes/users/@me/applications/#app_id/entitlements.ts
+++ b/src/api/routes/users/@me/applications/#app_id/entitlements.ts
diff --git a/api/src/routes/users/@me/billing/country-code.ts b/src/api/routes/users/@me/billing/country-code.ts
index 33d40796..33d40796 100644
--- a/api/src/routes/users/@me/billing/country-code.ts
+++ b/src/api/routes/users/@me/billing/country-code.ts
diff --git a/api/src/routes/users/@me/billing/payment-sources.ts b/src/api/routes/users/@me/billing/payment-sources.ts
index 014df8af..014df8af 100644
--- a/api/src/routes/users/@me/billing/payment-sources.ts
+++ b/src/api/routes/users/@me/billing/payment-sources.ts
diff --git a/api/src/routes/users/@me/billing/subscriptions.ts b/src/api/routes/users/@me/billing/subscriptions.ts
index 411e95bf..411e95bf 100644
--- a/api/src/routes/users/@me/billing/subscriptions.ts
+++ b/src/api/routes/users/@me/billing/subscriptions.ts
diff --git a/api/src/routes/users/@me/channels.ts b/src/api/routes/users/@me/channels.ts
index 78f531e1..ad483529 100644
--- a/api/src/routes/users/@me/channels.ts
+++ b/src/api/routes/users/@me/channels.ts
@@ -1,5 +1,5 @@
import { Request, Response, Router } from "express";
-import { Recipient, DmChannelDTO, Channel } from "@fosscord/util";
+import { Recipient, DmChannelDTO, Channel, DmChannelCreateSchema } from "@fosscord/util";
import { route } from "@fosscord/api";
const router: Router = Router();
@@ -12,11 +12,6 @@ router.get("/", route({}), async (req: Request, res: Response) => {
res.json(await Promise.all(recipients.map((r) => DmChannelDTO.from(r.channel, [req.user_id]))));
});
-export interface DmChannelCreateSchema {
- name?: string;
- recipients: string[];
-}
-
router.post("/", route({ body: "DmChannelCreateSchema" }), async (req: Request, res: Response) => {
const body = req.body as DmChannelCreateSchema;
res.json(await Channel.createDMChannel(body.recipients, req.user_id, body.name));
diff --git a/api/src/routes/users/@me/connections.ts b/src/api/routes/users/@me/connections.ts
index 411e95bf..411e95bf 100644
--- a/api/src/routes/users/@me/connections.ts
+++ b/src/api/routes/users/@me/connections.ts
diff --git a/api/src/routes/users/@me/delete.ts b/src/api/routes/users/@me/delete.ts
index c24c3f1e..1d81c2b9 100644
--- a/api/src/routes/users/@me/delete.ts
+++ b/src/api/routes/users/@me/delete.ts
@@ -2,7 +2,7 @@ import { Router, Request, Response } from "express";
import { Guild, Member, User } from "@fosscord/util";
import { route } from "@fosscord/api";
import bcrypt from "bcrypt";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
const router = Router();
diff --git a/api/src/routes/users/@me/devices.ts b/src/api/routes/users/@me/devices.ts
index 8556a3ad..8556a3ad 100644
--- a/api/src/routes/users/@me/devices.ts
+++ b/src/api/routes/users/@me/devices.ts
diff --git a/api/src/routes/users/@me/disable.ts b/src/api/routes/users/@me/disable.ts
index 4aff3774..4aff3774 100644
--- a/api/src/routes/users/@me/disable.ts
+++ b/src/api/routes/users/@me/disable.ts
diff --git a/api/src/routes/users/@me/email-settings.ts b/src/api/routes/users/@me/email-settings.ts
index 3114984e..3114984e 100644
--- a/api/src/routes/users/@me/email-settings.ts
+++ b/src/api/routes/users/@me/email-settings.ts
diff --git a/api/src/routes/users/@me/entitlements.ts b/src/api/routes/users/@me/entitlements.ts
index 341e2b4c..341e2b4c 100644
--- a/api/src/routes/users/@me/entitlements.ts
+++ b/src/api/routes/users/@me/entitlements.ts
diff --git a/api/src/routes/users/@me/guilds.ts b/src/api/routes/users/@me/guilds.ts
index 754a240e..4d4fccd4 100644
--- a/api/src/routes/users/@me/guilds.ts
+++ b/src/api/routes/users/@me/guilds.ts
@@ -1,6 +1,6 @@
import { Router, Request, Response } from "express";
import { Guild, Member, User, GuildDeleteEvent, GuildMemberRemoveEvent, emitEvent, Config } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { route } from "@fosscord/api";
const router: Router = Router();
diff --git a/api/src/routes/users/@me/guilds/premium/subscription-slots.ts b/src/api/routes/users/@me/guilds/premium/subscription-slots.ts
index 014df8af..014df8af 100644
--- a/api/src/routes/users/@me/guilds/premium/subscription-slots.ts
+++ b/src/api/routes/users/@me/guilds/premium/subscription-slots.ts
diff --git a/api/src/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts
index 7fc20457..7d095451 100644
--- a/api/src/routes/users/@me/index.ts
+++ b/src/api/routes/users/@me/index.ts
@@ -1,40 +1,22 @@
import { Router, Request, Response } from "express";
-import { User, PrivateUserProjection, emitEvent, UserUpdateEvent, handleFile, FieldErrors } from "@fosscord/util";
+import { User, PrivateUserProjection, emitEvent, UserUpdateEvent, handleFile, FieldErrors, UserModifySchema } from "@fosscord/util";
import { route } from "@fosscord/api";
import bcrypt from "bcrypt";
+import { OrmUtils, generateToken } from "@fosscord/util";
const router: Router = Router();
-export interface UserModifySchema {
- /**
- * @minLength 1
- * @maxLength 100
- */
- username?: string;
- discriminator?: string;
- avatar?: string | null;
- /**
- * @maxLength 1024
- */
- bio?: string;
- accent_color?: number;
- banner?: string | null;
- password?: string;
- new_password?: string;
- code?: string;
-}
-
router.get("/", route({}), async (req: Request, res: Response) => {
res.json(await User.findOne({ select: PrivateUserProjection, where: { id: req.user_id } }));
});
router.patch("/", route({ body: "UserModifySchema" }), async (req: Request, res: Response) => {
+ var token = null as any;
const body = req.body as UserModifySchema;
if (body.avatar) body.avatar = await handleFile(`/avatars/${req.user_id}`, body.avatar as string);
if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string);
-
- const user = await User.findOneOrFail({ where: { id: req.user_id }, select: [...PrivateUserProjection, "data"] });
+ let user = await User.findOneOrFail({ where: { id: req.user_id }, select: [...PrivateUserProjection, "data"] });
if (body.password) {
if (user.data?.hash) {
@@ -54,10 +36,12 @@ router.patch("/", route({ body: "UserModifySchema" }), async (req: Request, res:
});
}
user.data.hash = await bcrypt.hash(body.new_password, 12);
+ user.data.valid_tokens_since = new Date();
+ token = await generateToken(user.id) as string;
}
if(body.username){
- var check_username = body?.username?.replace(/\s/g, '');
+ let check_username = body?.username?.replace(/\s/g, '');
if(!check_username) {
throw FieldErrors({
username: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") }
@@ -65,7 +49,7 @@ router.patch("/", route({ body: "UserModifySchema" }), async (req: Request, res:
}
}
- user.assign(body);
+ user = OrmUtils.mergeDeep(user, body);
await user.save();
// @ts-ignore
@@ -77,8 +61,11 @@ router.patch("/", route({ body: "UserModifySchema" }), async (req: Request, res:
user_id: req.user_id,
data: user
} as UserUpdateEvent);
-
- res.json(user);
+
+ res.json({
+ ...user,
+ token
+ });
});
export default router;
diff --git a/api/src/routes/users/@me/library.ts b/src/api/routes/users/@me/library.ts
index 7ac13bae..7ac13bae 100644
--- a/api/src/routes/users/@me/library.ts
+++ b/src/api/routes/users/@me/library.ts
diff --git a/api/src/routes/users/@me/mfa/codes.ts b/src/api/routes/users/@me/mfa/codes.ts
index 6ddf32f0..4224a1c0 100644
--- a/api/src/routes/users/@me/mfa/codes.ts
+++ b/src/api/routes/users/@me/mfa/codes.ts
@@ -1,21 +1,16 @@
import { Router, Request, Response } from "express";
import { route } from "@fosscord/api";
-import { BackupCode, Config, FieldErrors, generateMfaBackupCodes, User } from "@fosscord/util";
+import { BackupCode, Config, FieldErrors, generateMfaBackupCodes, MfaCodesSchema, User } from "@fosscord/util";
import bcrypt from "bcrypt";
const router = Router();
-export interface MfaCodesSchema {
- password: string;
- regenerate?: boolean;
-}
-
// TODO: This route is replaced with users/@me/mfa/codes-verification in newer clients
router.post("/", route({ body: "MfaCodesSchema" }), async (req: Request, res: Response) => {
const { password, regenerate } = req.body as MfaCodesSchema;
- const user = await User.findOneOrFail({ id: req.user_id }, { select: ["data"] });
+ const user = await User.findOneOrFail({ where: { id: req.user_id }, select: ["data"] });
if (!await bcrypt.compare(password, user.data.hash || "")) {
throw FieldErrors({ password: { message: req.t("auth:login.INVALID_PASSWORD"), code: "INVALID_PASSWORD" } });
@@ -33,10 +28,12 @@ router.post("/", route({ body: "MfaCodesSchema" }), async (req: Request, res: Re
}
else {
codes = await BackupCode.find({
- user: {
- id: req.user_id,
- },
- expired: false,
+ where: {
+ user: {
+ id: req.user_id,
+ },
+ expired: false
+ }
});
}
diff --git a/api/src/routes/users/@me/mfa/totp/disable.ts b/src/api/routes/users/@me/mfa/totp/disable.ts
index 5e039ea3..2fe9355c 100644
--- a/api/src/routes/users/@me/mfa/totp/disable.ts
+++ b/src/api/routes/users/@me/mfa/totp/disable.ts
@@ -2,20 +2,16 @@ import { Router, Request, Response } from "express";
import { route } from "@fosscord/api";
import { verifyToken } from 'node-2fa';
import { HTTPError } from "lambert-server";
-import { User, generateToken, BackupCode } from "@fosscord/util";
+import { User, generateToken, BackupCode, TotpDisableSchema } from "@fosscord/util";
const router = Router();
-export interface TotpDisableSchema {
- code: string;
-}
-
router.post("/", route({ body: "TotpDisableSchema" }), async (req: Request, res: Response) => {
const body = req.body as TotpDisableSchema;
- const user = await User.findOneOrFail({ id: req.user_id }, { select: ["totp_secret"] });
+ const user = await User.findOneOrFail({ where: { id: req.user_id }, select: ["totp_secret"] });
- const backup = await BackupCode.findOne({ code: body.code });
+ const backup = await BackupCode.findOne({ where: { code: body.code } });
if (!backup) {
const ret = verifyToken(user.totp_secret!, body.code);
if (!ret || ret.delta != 0)
diff --git a/api/src/routes/users/@me/mfa/totp/enable.ts b/src/api/routes/users/@me/mfa/totp/enable.ts
index 87f36d55..ac668d1d 100644
--- a/api/src/routes/users/@me/mfa/totp/enable.ts
+++ b/src/api/routes/users/@me/mfa/totp/enable.ts
@@ -1,5 +1,5 @@
import { Router, Request, Response } from "express";
-import { User, generateToken, BackupCode, generateMfaBackupCodes, Config } from "@fosscord/util";
+import { User, generateToken, BackupCode, generateMfaBackupCodes, Config, TotpEnableSchema } from "@fosscord/util";
import { route } from "@fosscord/api";
import bcrypt from "bcrypt";
import { HTTPError } from "lambert-server";
@@ -7,12 +7,6 @@ import { verifyToken } from 'node-2fa';
const router = Router();
-export interface TotpEnableSchema {
- password: string;
- code?: string;
- secret?: string;
-}
-
router.post("/", route({ body: "TotpEnableSchema" }), async (req: Request, res: Response) => {
const body = req.body as TotpEnableSchema;
diff --git a/api/src/routes/users/@me/notes.ts b/src/api/routes/users/@me/notes.ts
index 3c503942..f938f088 100644
--- a/api/src/routes/users/@me/notes.ts
+++ b/src/api/routes/users/@me/notes.ts
@@ -29,7 +29,7 @@ router.put("/:id", route({}), async (req: Request, res: Response) => {
if (note && note.length) {
// upsert a note
- if (await Note.findOne({ owner: { id: owner.id }, target: { id: target.id } })) {
+ if (await Note.findOne({ where: { owner: { id: owner.id }, target: { id: target.id } } })) {
Note.update(
{ owner: { id: owner.id }, target: { id: target.id } },
{ owner, target, content: note }
diff --git a/api/src/routes/users/@me/relationships.ts b/src/api/routes/users/@me/relationships.ts
index 0c13cdba..f7464b99 100644
--- a/api/src/routes/users/@me/relationships.ts
+++ b/src/api/routes/users/@me/relationships.ts
@@ -9,9 +9,10 @@ import {
Config
} from "@fosscord/util";
import { Router, Response, Request } from "express";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { DiscordApiErrors } from "@fosscord/util";
import { route } from "@fosscord/api";
+import { OrmUtils } from "@fosscord/util";
const router = Router();
@@ -37,24 +38,15 @@ router.get("/", route({}), async (req: Request, res: Response) => {
return res.json(related_users);
});
-export interface RelationshipPutSchema {
- type?: RelationshipType;
-}
-
router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request, res: Response) => {
return await updateRelationship(
req,
res,
- await User.findOneOrFail({ id: req.params.id }, { relations: ["relationships", "relationships.to"], select: userProjection }),
+ await User.findOneOrFail({ where: { id: req.params.id }, relations: ["relationships", "relationships.to"], select: userProjection }),
req.body.type ?? RelationshipType.friends
);
});
-export interface RelationshipPostSchema {
- discriminator: string;
- username: string;
-}
-
router.post("/", route({ body: "RelationshipPostSchema" }), async (req: Request, res: Response) => {
return await updateRelationship(
req,
@@ -75,8 +67,8 @@ router.delete("/:id", route({}), async (req: Request, res: Response) => {
const { id } = req.params;
if (id === req.user_id) throw new HTTPError("You can't remove yourself as a friend");
- const user = await User.findOneOrFail({ id: req.user_id }, { select: userProjection, relations: ["relationships"] });
- const friend = await User.findOneOrFail({ id: id }, { select: userProjection, relations: ["relationships"] });
+ const user = await User.findOneOrFail({ where: { id: req.user_id }, select: userProjection, relations: ["relationships"] });
+ const friend = await User.findOneOrFail({ where: { id: id }, select: userProjection, relations: ["relationships"] });
const relationship = user.relationships.find((x) => x.to_id === id);
const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id);
@@ -124,12 +116,13 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ
const id = friend.id;
if (id === req.user_id) throw new HTTPError("You can't add yourself as a friend");
- const user = await User.findOneOrFail(
- { id: req.user_id },
- { relations: ["relationships", "relationships.to"], select: userProjection }
- );
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ relations: ["relationships", "relationships.to"],
+ select: userProjection
+ });
- var relationship = user.relationships.find((x) => x.to_id === id);
+ let relationship = user.relationships.find((x) => x.to_id === id);
const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id);
// TODO: you can add infinitely many blocked users (should this be prevented?)
@@ -139,7 +132,7 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ
relationship.type = RelationshipType.blocked;
await relationship.save();
} else {
- relationship = await new Relationship({ to_id: id, type: RelationshipType.blocked, from_id: req.user_id }).save();
+ relationship = await (OrmUtils.mergeDeep(new Relationship(), { to_id: id, type: RelationshipType.blocked, from_id: req.user_id }) as Relationship).save();
}
if (friendRequest && friendRequest.type !== RelationshipType.blocked) {
@@ -165,8 +158,8 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ
const { maxFriends } = Config.get().limits.user;
if (user.relationships.length >= maxFriends) throw DiscordApiErrors.MAXIMUM_FRIENDS.withParams(maxFriends);
- var incoming_relationship = new Relationship({ nickname: undefined, type: RelationshipType.incoming, to: user, from: friend });
- var outgoing_relationship = new Relationship({
+ let incoming_relationship = OrmUtils.mergeDeep(new Relationship(), { nickname: undefined, type: RelationshipType.incoming, to: user, from: friend });
+ let outgoing_relationship = OrmUtils.mergeDeep(new Relationship(), {
nickname: undefined,
type: RelationshipType.outgoing,
to: friend,
@@ -177,7 +170,7 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ
if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you");
if (friendRequest.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user");
// accept friend request
- incoming_relationship = friendRequest;
+ incoming_relationship = friendRequest as any; //TODO: checkme, any cast
incoming_relationship.type = RelationshipType.friends;
}
@@ -185,7 +178,7 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ
if (relationship.type === RelationshipType.outgoing) throw new HTTPError("You already sent a friend request");
if (relationship.type === RelationshipType.blocked) throw new HTTPError("Unblock the user before sending a friend request");
if (relationship.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user");
- outgoing_relationship = relationship;
+ outgoing_relationship = relationship as any; //TODO: checkme, any cast
outgoing_relationship.type = RelationshipType.friends;
}
diff --git a/api/src/routes/users/@me/settings.ts b/src/api/routes/users/@me/settings.ts
index b22b72fb..7578d36e 100644
--- a/api/src/routes/users/@me/settings.ts
+++ b/src/api/routes/users/@me/settings.ts
@@ -4,14 +4,12 @@ import { route } from "@fosscord/api";
const router = Router();
-export interface UserSettingsSchema extends Partial<UserSettings> {}
-
router.patch("/", route({ body: "UserSettingsSchema" }), async (req: Request, res: Response) => {
const body = req.body as UserSettings;
if (body.locale === "en") body.locale = "en-US"; // fix discord client crash on unkown locale
- const user = await User.findOneOrFail({ id: req.user_id, bot: false });
- user.settings = { ...user.settings, ...body };
+ const user = await User.findOneOrFail({ where: { id: req.user_id, bot: false }, relations: ["settings"] });
+ user.settings = { ...user.settings, ...body } as UserSettings;
await user.save();
res.sendStatus(204);
diff --git a/api/src/routes/voice/regions.ts b/src/api/routes/voice/regions.ts
index 4de304ee..4de304ee 100644
--- a/api/src/routes/voice/regions.ts
+++ b/src/api/routes/voice/regions.ts
diff --git a/api/src/start.ts b/src/api/start.ts
index ccb4d108..9ba198e7 100644
--- a/api/src/start.ts
+++ b/src/api/start.ts
@@ -1,13 +1,12 @@
process.on("uncaughtException", console.error);
process.on("unhandledRejection", console.error);
-import "missing-native-js-functions";
import { config } from "dotenv";
config();
import { FosscordServer } from "./Server";
import cluster from "cluster";
import os from "os";
-var cores = 1;
+let cores = 1;
try {
cores = Number(process.env.THREADS) || os.cpus().length;
} catch {
@@ -27,7 +26,7 @@ if (cluster.isMaster && process.env.NODE_ENV == "production") {
cluster.fork();
});
} else {
- var port = Number(process.env.PORT) || 3001;
+ let port = Number(process.env.PORT) || 3001;
const server = new FosscordServer({ port });
server.start().catch(console.error);
diff --git a/api/src/util/entities/AssetCacheItem.ts b/src/api/util/entities/AssetCacheItem.ts
index 160dece6..160dece6 100644
--- a/api/src/util/entities/AssetCacheItem.ts
+++ b/src/api/util/entities/AssetCacheItem.ts
diff --git a/api/src/util/entities/blockedEmailDomains.txt b/src/api/util/entities/blockedEmailDomains.txt
index eb88305d..eb88305d 100644
--- a/api/src/util/entities/blockedEmailDomains.txt
+++ b/src/api/util/entities/blockedEmailDomains.txt
diff --git a/api/src/util/entities/trustedEmailDomains.txt b/src/api/util/entities/trustedEmailDomains.txt
index 38ffa4fa..38ffa4fa 100644
--- a/api/src/util/entities/trustedEmailDomains.txt
+++ b/src/api/util/entities/trustedEmailDomains.txt
diff --git a/api/src/util/handlers/Instance.ts b/src/api/util/handlers/Instance.ts
index 6bddfa98..7c337270 100644
--- a/api/src/util/handlers/Instance.ts
+++ b/src/api/util/handlers/Instance.ts
@@ -1,4 +1,5 @@
import { Config, Guild, Session } from "@fosscord/util";
+import { createQueryBuilder } from "typeorm";
export async function initInstance() {
// TODO: clean up database and delete tombstone data
@@ -9,7 +10,7 @@ export async function initInstance() {
const { autoJoin } = Config.get().guild;
if (autoJoin.enabled && !autoJoin.guilds?.length) {
- let guild = await Guild.findOne({});
+ let guild = await Guild.findOne({where: {}, order: {id: "ASC"}});
if (guild) {
// @ts-ignore
await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } });
diff --git a/api/src/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 48f87dfe..ff5ece75 100644
--- a/api/src/util/handlers/Message.ts
+++ b/src/api/util/handlers/Message.ts
@@ -21,11 +21,13 @@ import {
Webhook,
Attachment,
Config,
+ MessageCreateSchema,
} from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import fetch from "node-fetch";
import cheerio from "cheerio";
-import { MessageCreateSchema } from "../../routes/channels/#channel_id/messages";
+import { OrmUtils } from "@fosscord/util";
+
const allow_empty = false;
// TODO: check webhook, application, system author, stickers
// TODO: embed gifs/videos/images
@@ -47,7 +49,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
const channel = await Channel.findOneOrFail({ where: { id: opts.channel_id }, relations: ["recipients"] });
if (!channel || !opts.channel_id) throw new HTTPError("Channel not found", 404);
- const message = new Message({
+ const message = OrmUtils.mergeDeep(new Message(), {
...opts,
sticker_items: opts.sticker_ids?.map((x) => ({ id: x })),
guild_id: channel.guild_id,
@@ -68,10 +70,10 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
rights.hasThrow("SEND_MESSAGES");
}
if (opts.application_id) {
- message.application = await Application.findOneOrFail({ id: opts.application_id });
+ message.application = await Application.findOneOrFail({ where: { id: opts.application_id } });
}
if (opts.webhook_id) {
- message.webhook = await Webhook.findOneOrFail({ id: opts.webhook_id });
+ message.webhook = await Webhook.findOneOrFail({ where: { id: opts.webhook_id } });
}
const permission = await getPermission(opts.author_id, channel.guild_id, opts.channel_id);
@@ -85,7 +87,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
permission.hasThrow("READ_MESSAGE_HISTORY");
// code below has to be redone when we add custom message routing
if (message.guild_id !== null) {
- const guild = await Guild.findOneOrFail({ id: channel.guild_id });
+ const guild = await Guild.findOneOrFail({ where: { id: channel.guild_id } });
if (!guild.features.includes("CROSS_CHANNEL_REPLIES")) {
if (opts.message_reference.guild_id !== channel.guild_id) throw new HTTPError("You can only reference messages from this guild");
if (opts.message_reference.channel_id !== opts.channel_id) throw new HTTPError("You can only reference messages from this channel");
@@ -102,11 +104,11 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
throw new HTTPError("Empty messages are not allowed", 50006);
}
- var content = opts.content;
- var mention_channel_ids = [] as string[];
- var mention_role_ids = [] as string[];
- var mention_user_ids = [] as string[];
- var mention_everyone = false;
+ let content = opts.content;
+ let mention_channel_ids = [] as string[];
+ let mention_role_ids = [] as string[];
+ let mention_user_ids = [] as string[];
+ let mention_everyone = false;
if (content) { // TODO: explicit-only mentions
message.content = content.trim();
@@ -120,7 +122,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
await Promise.all(
Array.from(content.matchAll(ROLE_MENTION)).map(async ([_, mention]) => {
- const role = await Role.findOneOrFail({ id: mention, guild_id: channel.guild_id });
+ const role = await Role.findOneOrFail({ where: { id: mention, guild_id: channel.guild_id } });
if (role.mentionable || permission.has("MANAGE_ROLES")) {
mention_role_ids.push(mention);
}
@@ -132,9 +134,9 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
}
}
- message.mention_channels = mention_channel_ids.map((x) => new Channel({ id: x }));
- message.mention_roles = mention_role_ids.map((x) => new Role({ id: x }));
- message.mentions = mention_user_ids.map((x) => new User({ id: x }));
+ message.mention_channels = mention_channel_ids.map((x) => OrmUtils.mergeDeep(new Channel(), { id: x }));
+ message.mention_roles = mention_role_ids.map((x) => OrmUtils.mergeDeep(new Role(), { id: x }));
+ message.mentions = mention_user_ids.map((x) => OrmUtils.mergeDeep(new User(), { id: x }));
message.mention_everyone = mention_everyone;
// TODO: check and put it all in the body
@@ -144,7 +146,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
// TODO: cache link result in db
export async function postHandleMessage(message: Message) {
- var links = message.content?.match(LINK_REGEX);
+ let links = message.content?.match(LINK_REGEX);
if (!links) return;
const data = { ...message };
@@ -201,9 +203,10 @@ export async function postHandleMessage(message: Message) {
export async function sendMessage(opts: MessageOptions) {
const message = await handleMessage({ ...opts, timestamp: new Date() });
+ //TODO: check this, removed toJSON call
await Promise.all([
Message.insert(message),
- emitEvent({ event: "MESSAGE_CREATE", channel_id: opts.channel_id, data: message.toJSON() } as MessageCreateEvent)
+ emitEvent({ event: "MESSAGE_CREATE", channel_id: opts.channel_id, data: message } as MessageCreateEvent)
]);
postHandleMessage(message).catch((e) => {}); // no await as it should catch error non-blockingly
diff --git a/api/src/util/handlers/Voice.ts b/src/api/util/handlers/Voice.ts
index 4d60eb91..4d60eb91 100644
--- a/api/src/util/handlers/Voice.ts
+++ b/src/api/util/handlers/Voice.ts
diff --git a/api/src/util/handlers/route.ts b/src/api/util/handlers/route.ts
index 3d3bbc37..71e14955 100644
--- a/api/src/util/handlers/route.ts
+++ b/src/api/util/handlers/route.ts
@@ -19,7 +19,7 @@ import Ajv from "ajv";
import { AnyValidateFunction } from "ajv/dist/core";
import addFormats from "ajv-formats";
-const SchemaPath = path.join(__dirname, "..", "..", "..", "assets", "schemas.json");
+const SchemaPath = path.join(__dirname, "..", "..", "..","..", "assets", "schemas.json");
const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" }));
export const ajv = new Ajv({
@@ -87,7 +87,7 @@ const normalizeBody = (body: any = {}) => {
};
export function route(opts: RouteOptions) {
- var validate: AnyValidateFunction<any> | undefined;
+ let validate: AnyValidateFunction<any> | undefined;
if (opts.body) {
validate = ajv.getSchema(opts.body);
if (!validate) throw new Error(`Body schema ${opts.body} not found`);
@@ -117,6 +117,11 @@ export function route(opts: RouteOptions) {
const valid = validate(normalizeBody(req.body));
if (!valid) {
const fields: Record<string, { code?: string; message: string }> = {};
+ if(process.env.LOG_INVALID_BODY) {
+ console.log(`Got invalid request: ${req.method} ${req.originalUrl}`)
+ console.log(req.body)
+ validate.errors?.forEach(x => console.log(x.params))
+ }
validate.errors?.forEach((x) => (fields[x.instancePath.slice(1)] = { code: x.keyword, message: x.message || "" }));
throw FieldErrors(fields);
}
diff --git a/api/src/util/index.ts b/src/api/util/index.ts
index fd743a9b..31e75325 100644
--- a/api/src/util/index.ts
+++ b/src/api/util/index.ts
@@ -1,10 +1,10 @@
+export * from "./entities/AssetCacheItem";
+export * from "./handlers/Message";
+export * from "./handlers/route";
+export * from "./handlers/Voice";
export * from "./utility/Base64";
export * from "./utility/ipAddress";
-export * from "./handlers/Message";
export * from "./utility/passwordStrength";
export * from "./utility/RandomInviteID";
-export * from "./handlers/route";
export * from "./utility/String";
-export * from "./handlers/Voice";
-export * from "./utility/captcha";
-export * from "./entities/AssetCacheItem";
+export * from "./utility/captcha";
\ No newline at end of file
diff --git a/api/src/util/utility/Base64.ts b/src/api/util/utility/Base64.ts
index 46cff77a..46cff77a 100644
--- a/api/src/util/utility/Base64.ts
+++ b/src/api/util/utility/Base64.ts
diff --git a/api/src/util/utility/RandomInviteID.ts b/src/api/util/utility/RandomInviteID.ts
index 7ea344e0..7ea344e0 100644
--- a/api/src/util/utility/RandomInviteID.ts
+++ b/src/api/util/utility/RandomInviteID.ts
diff --git a/api/src/util/utility/String.ts b/src/api/util/utility/String.ts
index 982b7e11..982b7e11 100644
--- a/api/src/util/utility/String.ts
+++ b/src/api/util/utility/String.ts
diff --git a/api/src/util/utility/captcha.ts b/src/api/util/utility/captcha.ts
index 739647d2..739647d2 100644
--- a/api/src/util/utility/captcha.ts
+++ b/src/api/util/utility/captcha.ts
diff --git a/api/src/util/utility/ipAddress.ts b/src/api/util/utility/ipAddress.ts
index 13cc9603..8d986b26 100644
--- a/api/src/util/utility/ipAddress.ts
+++ b/src/api/util/utility/ipAddress.ts
@@ -65,7 +65,7 @@ export async function IPAnalysis(ip: string): Promise<typeof exampleData> {
const { ipdataApiKey } = Config.get().security;
if (!ipdataApiKey) return { ...exampleData, ip };
- return (await fetch(`https://api.ipdata.co/${ip}?api-key=${ipdataApiKey}`)).json();
+ return (await fetch(`https://api.ipdata.co/${ip}?api-key=${ipdataApiKey}`)).json() as any;
}
export function isProxy(data: typeof exampleData) {
diff --git a/api/src/util/utility/passwordStrength.ts b/src/api/util/utility/passwordStrength.ts
index 439700d0..8eca63b8 100644
--- a/api/src/util/utility/passwordStrength.ts
+++ b/src/api/util/utility/passwordStrength.ts
@@ -1,5 +1,4 @@
import { Config } from "@fosscord/util";
-import "missing-native-js-functions";
const reNUMBER = /[0-9]/g;
const reUPPERCASELETTER = /[A-Z]/g;
@@ -19,7 +18,7 @@ const blocklist: string[] = []; // TODO: update ones passwordblocklist is stored
*/
export function checkPassword(password: string): number {
const { minLength, minNumbers, minUpperCase, minSymbols } = Config.get().register.password;
- var strength = 0;
+ let strength = 0;
// checks for total password len
if (password.length >= minLength - 1) {
diff --git a/cdn/src/Server.ts b/src/cdn/Server.ts
index b8d71fa9..b27d3321 100644
--- a/cdn/src/Server.ts
+++ b/src/cdn/Server.ts
@@ -1,5 +1,5 @@
import { Server, ServerOptions } from "lambert-server";
-import { Config, initDatabase, registerRoutes } from "@fosscord/util";
+import { Config, getOrInitialiseDatabase, registerRoutes } from "@fosscord/util";
import path from "path";
import avatarsRoute from "./routes/avatars";
import iconsRoute from "./routes/role-icons";
@@ -15,7 +15,7 @@ export class CDNServer extends Server {
}
async start() {
- await initDatabase();
+ await getOrInitialiseDatabase();
await Config.init();
this.app.use((req, res, next) => {
res.set("Access-Control-Allow-Origin", "*");
diff --git a/cdn/src/index.ts b/src/cdn/index.ts
index a24300d6..a24300d6 100644
--- a/cdn/src/index.ts
+++ b/src/cdn/index.ts
diff --git a/cdn/src/routes/attachments.ts b/src/cdn/routes/attachments.ts
index ae50bc48..723a6c03 100644
--- a/cdn/src/routes/attachments.ts
+++ b/src/cdn/routes/attachments.ts
@@ -2,7 +2,7 @@ import { Router, Response, Request } from "express";
import { Config, Snowflake } from "@fosscord/util";
import { storage } from "../util/Storage";
import FileType from "file-type";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import { multer } from "../util/multer";
import imageSize from "image-size";
@@ -35,8 +35,8 @@ router.post(
Config.get()?.cdn.endpointPublic || "http://localhost:3003";
await storage.set(path, buffer);
- var width;
- var height;
+ let width;
+ let height;
if (mimetype.includes("image")) {
const dimensions = imageSize(buffer);
if (dimensions) {
diff --git a/cdn/src/routes/avatars.ts b/src/cdn/routes/avatars.ts
index 2a4a0ffe..40705b2e 100644
--- a/cdn/src/routes/avatars.ts
+++ b/src/cdn/routes/avatars.ts
@@ -2,7 +2,7 @@ import { Router, Response, Request } from "express";
import { Config, Snowflake } from "@fosscord/util";
import { storage } from "../util/Storage";
import FileType from "file-type";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import crypto from "crypto";
import { multer } from "../util/multer";
@@ -33,7 +33,7 @@ router.post(
const { buffer, mimetype, size, originalname, fieldname } = req.file;
const { user_id } = req.params;
- var hash = crypto
+ let hash = crypto
.createHash("md5")
.update(Snowflake.generate())
.digest("hex");
@@ -59,7 +59,7 @@ router.post(
);
router.get("/:user_id", async (req: Request, res: Response) => {
- var { user_id } = req.params;
+ let { user_id } = req.params;
user_id = user_id.split(".")[0]; // remove .file extension
const path = `avatars/${user_id}`;
@@ -74,7 +74,7 @@ router.get("/:user_id", async (req: Request, res: Response) => {
});
router.get("/:user_id/:hash", async (req: Request, res: Response) => {
- var { user_id, hash } = req.params;
+ let { user_id, hash } = req.params;
hash = hash.split(".")[0]; // remove .file extension
const path = `avatars/${user_id}/${hash}`;
diff --git a/cdn/src/routes/external.ts b/src/cdn/routes/external.ts
index dc90e3c8..c9441fc2 100644
--- a/cdn/src/routes/external.ts
+++ b/src/cdn/routes/external.ts
@@ -1,10 +1,9 @@
import { Router, Response, Request } from "express";
import fetch from "node-fetch";
-import { HTTPError } from "lambert-server";
-import { Snowflake } from "@fosscord/util";
+import { HTTPError } from "@fosscord/util";
+import { Snowflake, Config } from "@fosscord/util";
import { storage } from "../util/Storage";
import FileType from "file-type";
-import { Config } from "@fosscord/util";
// TODO: somehow handle the deletion of images posted to the /external route
diff --git a/cdn/src/routes/ping.ts b/src/cdn/routes/ping.ts
index 38daf81e..38daf81e 100644
--- a/cdn/src/routes/ping.ts
+++ b/src/cdn/routes/ping.ts
diff --git a/cdn/src/routes/role-icons.ts b/src/cdn/routes/role-icons.ts
index 12aae8a4..2e5c42dd 100644
--- a/cdn/src/routes/role-icons.ts
+++ b/src/cdn/routes/role-icons.ts
@@ -2,7 +2,7 @@ import { Router, Response, Request } from "express";
import { Config, Snowflake } from "@fosscord/util";
import { storage } from "../util/Storage";
import FileType from "file-type";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "@fosscord/util";
import crypto from "crypto";
import { multer } from "../util/multer";
@@ -33,7 +33,7 @@ router.post(
const { buffer, mimetype, size, originalname, fieldname } = req.file;
const { role_id } = req.params;
- var hash = crypto
+ let hash = crypto
.createHash("md5")
.update(Snowflake.generate())
.digest("hex");
@@ -58,7 +58,7 @@ router.post(
);
router.get("/:role_id", async (req: Request, res: Response) => {
- var { role_id } = req.params;
+ let { role_id } = req.params;
//role_id = role_id.split(".")[0]; // remove .file extension
const path = `role-icons/${role_id}`;
@@ -73,7 +73,7 @@ router.get("/:role_id", async (req: Request, res: Response) => {
});
router.get("/:role_id/:hash", async (req: Request, res: Response) => {
- var { role_id, hash } = req.params;
+ let { role_id, hash } = req.params;
//hash = hash.split(".")[0]; // remove .file extension
const path = `role-icons/${role_id}/${hash}`;
diff --git a/cdn/src/start.ts b/src/cdn/start.ts
index 71681b40..71681b40 100644
--- a/cdn/src/start.ts
+++ b/src/cdn/start.ts
diff --git a/cdn/src/util/FileStorage.ts b/src/cdn/util/FileStorage.ts
index 84ecf556..aee9d345 100644
--- a/cdn/src/util/FileStorage.ts
+++ b/src/cdn/util/FileStorage.ts
@@ -1,17 +1,16 @@
import { Storage } from "./Storage";
import fs from "fs";
-import fse from "fs-extra";
import { join, relative, dirname } from "path";
-import "missing-native-js-functions";
import { Readable } from "stream";
-import ExifTransformer = require("exif-be-gone");
+//import ExifTransformer = require("exif-be-gone");
+import ExifTransformer from "exif-be-gone";
// TODO: split stored files into separate folders named after cloned route
function getPath(path: string) {
// STORAGE_LOCATION has a default value in start.ts
const root = process.env.STORAGE_LOCATION || "../";
- var filename = join(root, path);
+ let filename = join(root, path);
if (path.indexOf("\0") !== -1 || !filename.startsWith(root))
throw new Error("invalid path");
@@ -36,7 +35,8 @@ export class FileStorage implements Storage {
async set(path: string, value: any) {
path = getPath(path);
- fse.ensureDirSync(dirname(path));
+ //fse.ensureDirSync(dirname(path));
+ fs.mkdirSync(dirname(path), {recursive: true});
value = Readable.from(value);
const cleaned_file = fs.createWriteStream(path);
diff --git a/cdn/src/util/S3Storage.ts b/src/cdn/util/S3Storage.ts
index c4066817..c4066817 100644
--- a/cdn/src/util/S3Storage.ts
+++ b/src/cdn/util/S3Storage.ts
diff --git a/cdn/src/util/Storage.ts b/src/cdn/util/Storage.ts
index 89dd5634..728804a0 100644
--- a/cdn/src/util/Storage.ts
+++ b/src/cdn/util/Storage.ts
@@ -1,6 +1,7 @@
import { FileStorage } from "./FileStorage";
import path from "path";
-import fse from "fs-extra";
+//import fse from "fs-extra";
+import fs from "fs";
import { bgCyan, black } from "picocolors";
import { S3 } from "@aws-sdk/client-s3";
import { S3Storage } from "./S3Storage";
@@ -22,7 +23,8 @@ if (process.env.STORAGE_PROVIDER === "file" || !process.env.STORAGE_PROVIDER) {
location = path.join(process.cwd(), "files");
}
console.log(`[CDN] storage location: ${bgCyan(`${black(location)}`)}`);
- fse.ensureDirSync(location);
+ //fse.ensureDirSync(location);
+ fs.mkdirSync(location, {recursive: true});
process.env.STORAGE_LOCATION = location;
storage = new FileStorage();
diff --git a/cdn/src/util/index.ts b/src/cdn/util/index.ts
index 07a5c31a..07a5c31a 100644
--- a/cdn/src/util/index.ts
+++ b/src/cdn/util/index.ts
diff --git a/cdn/src/util/multer.ts b/src/cdn/util/multer.ts
index bfdf6aff..bfdf6aff 100644
--- a/cdn/src/util/multer.ts
+++ b/src/cdn/util/multer.ts
diff --git a/gateway/src/Server.ts b/src/gateway/Server.ts
index 7e1489be..82fbeba2 100644
--- a/gateway/src/Server.ts
+++ b/src/gateway/Server.ts
@@ -1,7 +1,6 @@
-import "missing-native-js-functions";
import dotenv from "dotenv";
dotenv.config();
-import { closeDatabase, Config, initDatabase, initEvent } from "@fosscord/util";
+import { closeDatabase, Config, getOrInitialiseDatabase, initEvent } from "@fosscord/util";
import ws from "ws";
import { Connection } from "./events/Connection";
import http from "http";
@@ -47,7 +46,7 @@ export class Server {
}
async start(): Promise<void> {
- await initDatabase();
+ await getOrInitialiseDatabase();
await Config.init();
await initEvent();
if (!this.server.listening) {
diff --git a/gateway/src/events/Close.ts b/src/gateway/events/Close.ts
index 5b7c512c..5b7c512c 100644
--- a/gateway/src/events/Close.ts
+++ b/src/gateway/events/Close.ts
diff --git a/gateway/src/events/Connection.ts b/src/gateway/events/Connection.ts
index 4954cd08..508b4741 100644
--- a/gateway/src/events/Connection.ts
+++ b/src/gateway/events/Connection.ts
@@ -8,7 +8,7 @@ import { Close } from "./Close";
import { Message } from "./Message";
import { createDeflate } from "zlib";
import { URL } from "url";
-var erlpack: any;
+let erlpack: any;
try {
erlpack = require("@yukikaze-bot/erlpack");
} catch (error) {}
@@ -27,6 +27,21 @@ export async function Connection(
socket.on("close", Close);
// @ts-ignore
socket.on("message", Message);
+
+ if(process.env.WS_LOGEVENTS)
+ [
+ "close",
+ "error",
+ "upgrade",
+ //"message",
+ "open",
+ "ping",
+ "pong",
+ "unexpected-response"
+ ].forEach(x=>{
+ socket.on(x, y => console.log(x, y));
+ });
+
console.log(`[Gateway] Connections: ${this.clients.size}`);
const { searchParams } = new URL(`http://localhost${request.url}`);
diff --git a/src/gateway/events/Message.ts b/src/gateway/events/Message.ts
new file mode 100644
index 00000000..569f5fc7
--- /dev/null
+++ b/src/gateway/events/Message.ts
@@ -0,0 +1,61 @@
+import { CLOSECODES } from "../util/Constants";
+import { WebSocket, Payload } from "@fosscord/gateway";
+let erlpack: any;
+try {
+ erlpack = require("@yukikaze-bot/erlpack");
+} catch (error) {}
+import OPCodeHandlers from "../opcodes";
+import { check } from "../opcodes/instanceOf";
+
+const PayloadSchema = {
+ op: Number,
+ $d: Object || Number, // or number for heartbeat sequence
+ $s: Number,
+ $t: String,
+};
+
+export async function Message(this: WebSocket, buffer: Buffer) {
+ // TODO: compression
+ let data: Payload;
+
+ if (this.encoding === "etf" && buffer instanceof Buffer)
+ data = erlpack.unpack(buffer);
+ else if (this.encoding === "json")
+ data = JSON.parse(buffer as unknown as string); //TODO: is this even correct?? seems to work for web clients...
+ else if(/--debug|--inspect/.test(process.execArgv.join(' '))) {
+ debugger;
+ return;
+ }
+ else {
+ console.log("Invalid gateway connection! Use a debugger to inspect!");
+ return;
+ }
+
+ if(process.env.WS_VERBOSE)
+ console.log(`[Websocket] Incomming message: ${JSON.stringify(data)}`);
+ if(data.op !== 1)
+ check.call(this, PayloadSchema, data);
+ else { //custom validation for numbers, because heartbeat
+ if(data.s || data.t || (typeof data.d !== "number" && data.d)) {
+ console.log("Invalid heartbeat...");
+ this.close(CLOSECODES.Decode_error);
+ }
+ }
+
+ // @ts-ignore
+ const OPCodeHandler = OPCodeHandlers[data.op];
+ if (!OPCodeHandler) {
+ console.error("[Gateway] Unkown opcode " + data.op);
+ // TODO: if all opcodes are implemented comment this out:
+ // this.close(CLOSECODES.Unknown_opcode);
+ return;
+ }
+
+ try {
+ return await OPCodeHandler.call(this, data);
+ } catch (error) {
+ console.error(error);
+ if (!this.CLOSED && this.CLOSING)
+ return this.close(CLOSECODES.Unknown_error);
+ }
+}
diff --git a/gateway/src/index.ts b/src/gateway/index.ts
index d77ce931..d77ce931 100644
--- a/gateway/src/index.ts
+++ b/src/gateway/index.ts
diff --git a/gateway/src/listener/listener.ts b/src/gateway/listener/listener.ts
index 060de65b..8c69e193 100644
--- a/gateway/src/listener/listener.ts
+++ b/src/gateway/listener/listener.ts
@@ -13,7 +13,6 @@ import {
import { OPCODES } from "../util/Constants";
import { Send } from "../util/Send";
import { WebSocket } from "@fosscord/gateway";
-import "missing-native-js-functions";
import { Channel as AMQChannel } from "amqplib";
import { Recipient } from "@fosscord/util";
@@ -50,10 +49,10 @@ export async function setupListener(this: WebSocket) {
where: { user_id: this.user_id, closed: false },
relations: ["channel"],
}),
- Relationship.find({
+ Relationship.find({ where: {
from_id: this.user_id,
type: RelationshipType.friends,
- }),
+ } }),
]);
const guilds = members.map((x) => x.guild);
diff --git a/gateway/src/opcodes/Heartbeat.ts b/src/gateway/opcodes/Heartbeat.ts
index 50394130..42b72d4b 100644
--- a/gateway/src/opcodes/Heartbeat.ts
+++ b/src/gateway/opcodes/Heartbeat.ts
@@ -2,7 +2,7 @@ import { Payload, WebSocket } from "@fosscord/gateway";
import { setHeartbeat } from "../util/Heartbeat";
import { Send } from "../util/Send";
-export async function onHeartbeat(this: WebSocket, data: Payload) {
+export async function onHeartbeat(this: WebSocket, _data: Payload) {
// TODO: validate payload
setHeartbeat(this);
diff --git a/gateway/src/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts
index 860000da..44db598c 100644
--- a/gateway/src/opcodes/Identify.ts
+++ b/src/gateway/opcodes/Identify.ts
@@ -18,16 +18,18 @@ import {
PrivateSessionProjection,
MemberPrivateProjection,
PresenceUpdateEvent,
+ UserSettings,
+ IdentifySchema,
} from "@fosscord/util";
import { Send } from "../util/Send";
import { CLOSECODES, OPCODES } from "../util/Constants";
import { genSessionId } from "../util/SessionUtils";
import { setupListener } from "../listener/listener";
-import { IdentifySchema } from "../schema/Identify";
// import experiments from "./experiments.json";
const experiments: any = [];
import { check } from "./instanceOf";
import { Recipient } from "@fosscord/util";
+import { OrmUtils } from "@fosscord/util";
// TODO: user sharding
// TODO: check privileged intents, if defined in the config
@@ -50,15 +52,15 @@ export async function onIdentify(this: WebSocket, data: Payload) {
const session_id = genSessionId();
this.session_id = session_id; //Set the session of the WebSocket object
-
+
const [user, read_states, members, recipients, session, application] =
await Promise.all([
User.findOneOrFail({
where: { id: this.user_id },
- relations: ["relationships", "relationships.to"],
+ relations: ["relationships", "relationships.to", "settings"],
select: [...PrivateUserProjection, "relationships"],
}),
- ReadState.find({ user_id: this.user_id }),
+ ReadState.find({ where: { user_id: this.user_id } }),
Member.find({
where: { id: this.user_id },
select: MemberPrivateProjection,
@@ -83,7 +85,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
// TODO: public user selection
}),
// save the session and delete it when the websocket is closed
- new Session({
+ await OrmUtils.mergeDeep(new Session(), {
user_id: this.user_id,
session_id: session_id,
// TODO: check if status is only one of: online, dnd, offline, idle
@@ -96,12 +98,17 @@ export async function onIdentify(this: WebSocket, data: Payload) {
},
activities: [],
}).save(),
- Application.findOne({ id: this.user_id }),
+ Application.findOne({ where: { id: this.user_id } }),
]);
if (!user) return this.close(CLOSECODES.Authentication_failed);
+ if (!user.settings) { //settings may not exist after updating...
+ user.settings = new UserSettings();
+ user.settings.id = user.id;
+ //await (user.settings as UserSettings).save();
+ }
- if (!identify.intents) identify.intents = BigInt("0x6ffffffff");
+ if (!identify.intents) identify.intents = "30064771071";
this.intents = new Intents(identify.intents);
if (identify.shard) {
this.shard_id = identify.shard[0];
@@ -117,7 +124,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
return this.close(CLOSECODES.Invalid_shard);
}
}
- var users: PublicUser[] = [];
+ let users: PublicUser[] = [];
const merged_members = members.map((x: Member) => {
return [
@@ -231,7 +238,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
const d: ReadyEventData = {
v: 8,
- application,
+ application: {id: application?.id??'', flags: application?.flags??0}, //TODO: check this code!
user: privateUser,
user_settings: user.settings,
// @ts-ignore
diff --git a/gateway/src/opcodes/LazyRequest.ts b/src/gateway/opcodes/LazyRequest.ts
index 7503ee61..74996f5b 100644
--- a/gateway/src/opcodes/LazyRequest.ts
+++ b/src/gateway/opcodes/LazyRequest.ts
@@ -1,12 +1,9 @@
-import { getPermission, listenEvent, Member, Role } from "@fosscord/util";
-import { LazyRequest } from "../schema/LazyRequest";
+import { getPermission, listenEvent, Member, Role, getOrInitialiseDatabase, LazyRequest } from "@fosscord/util";
import { Send } from "../util/Send";
import { OPCODES } from "../util/Constants";
import { WebSocket, Payload, handlePresenceUpdate } from "@fosscord/gateway";
import { check } from "./instanceOf";
-import "missing-native-js-functions";
import { getRepository } from "typeorm";
-import "missing-native-js-functions";
// TODO: only show roles/members that have access to this channel
// TODO: config: to list all members (even those who are offline) sorted by role, or just those who are online
@@ -17,8 +14,9 @@ async function getMembers(guild_id: string, range: [number, number]) {
throw new Error("range is not a valid array");
}
// TODO: wait for typeorm to implement ordering for .find queries https://github.com/typeorm/typeorm/issues/2620
+ // TODO: rewrite this, released in 0.3.0
- let members = await getRepository(Member)
+ let members: Member[] = await (await getOrInitialiseDatabase()).getRepository(Member)
.createQueryBuilder("member")
.where("member.guild_id = :guild_id", { guild_id })
.leftJoinAndSelect("member.roles", "role")
@@ -122,7 +120,7 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) {
const ranges = channels![channel_id];
if (!Array.isArray(ranges)) throw new Error("Not a valid Array");
- const member_count = await Member.count({ guild_id });
+ const member_count = await Member.count({ where: { guild_id } });
const ops = await Promise.all(ranges.map((x) => getMembers(guild_id, x)));
// TODO: unsubscribe member_events that are not in op.members
diff --git a/gateway/src/opcodes/PresenceUpdate.ts b/src/gateway/opcodes/PresenceUpdate.ts
index 415df6ee..f31c9161 100644
--- a/gateway/src/opcodes/PresenceUpdate.ts
+++ b/src/gateway/opcodes/PresenceUpdate.ts
@@ -1,6 +1,5 @@
import { WebSocket, Payload } from "@fosscord/gateway";
-import { emitEvent, PresenceUpdateEvent, Session, User } from "@fosscord/util";
-import { ActivitySchema } from "../schema/Activity";
+import { ActivitySchema, emitEvent, PresenceUpdateEvent, Session, User } from "@fosscord/util";
import { check } from "./instanceOf";
export async function onPresenceUpdate(this: WebSocket, { d }: Payload) {
diff --git a/gateway/src/opcodes/RequestGuildMembers.ts b/src/gateway/opcodes/RequestGuildMembers.ts
index b80721dc..b80721dc 100644
--- a/gateway/src/opcodes/RequestGuildMembers.ts
+++ b/src/gateway/opcodes/RequestGuildMembers.ts
diff --git a/gateway/src/opcodes/Resume.ts b/src/gateway/opcodes/Resume.ts
index 42dc586d..42dc586d 100644
--- a/gateway/src/opcodes/Resume.ts
+++ b/src/gateway/opcodes/Resume.ts
diff --git a/gateway/src/opcodes/VoiceStateUpdate.ts b/src/gateway/opcodes/VoiceStateUpdate.ts
index 321e6b17..c4297a68 100644
--- a/gateway/src/opcodes/VoiceStateUpdate.ts
+++ b/src/gateway/opcodes/VoiceStateUpdate.ts
@@ -1,4 +1,3 @@
-import { VoiceStateUpdateSchema } from "../schema/VoiceStateUpdateSchema";
import { Payload, WebSocket } from "@fosscord/gateway";
import { genVoiceToken } from "../util/SessionUtils";
import { check } from "./instanceOf";
@@ -7,11 +6,13 @@ import {
emitEvent,
Guild,
Member,
- Region,
VoiceServerUpdateEvent,
VoiceState,
VoiceStateUpdateEvent,
+ VoiceStateUpdateSchema,
} from "@fosscord/util";
+import { OrmUtils } from "@fosscord/util";
+import { Region } from "@fosscord/util";
// 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.
@@ -19,6 +20,11 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) {
check.call(this, VoiceStateUpdateSchema, data.d);
const body = data.d as VoiceStateUpdateSchema;
+ if(body.guild_id == null) {
+ console.log(`[Gateway] VoiceStateUpdate called with guild_id == null by user ${this.user_id}!`);
+ return;
+ }
+
let voiceState: VoiceState;
try {
voiceState = await VoiceState.findOneOrFail({
@@ -47,9 +53,9 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) {
//The event send by Discord's client on channel leave has both guild_id and channel_id as null
if (body.guild_id === null) body.guild_id = voiceState.guild_id;
- voiceState.assign(body);
+ voiceState = OrmUtils.mergeDeep(voiceState, body);
} catch (error) {
- voiceState = new VoiceState({
+ voiceState = OrmUtils.mergeDeep(new VoiceState(), {
...body,
user_id: this.user_id,
deaf: false,
@@ -84,7 +90,7 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) {
//If it's null it means that we are leaving the channel and this event is not needed
if (voiceState.channel_id !== null) {
- const guild = await Guild.findOne({ id: voiceState.guild_id });
+ const guild = await Guild.findOne({ where: { id: voiceState.guild_id } });
const regions = Config.get().regions;
let guildRegion: Region;
if (guild && guild.region) {
diff --git a/gateway/src/opcodes/experiments.json b/src/gateway/opcodes/experiments.json
index 0370b5da..0370b5da 100644
--- a/gateway/src/opcodes/experiments.json
+++ b/src/gateway/opcodes/experiments.json
diff --git a/gateway/src/opcodes/index.ts b/src/gateway/opcodes/index.ts
index 027739db..027739db 100644
--- a/gateway/src/opcodes/index.ts
+++ b/src/gateway/opcodes/index.ts
diff --git a/gateway/src/opcodes/instanceOf.ts b/src/gateway/opcodes/instanceOf.ts
index 6fd50852..eb6f6ea1 100644
--- a/gateway/src/opcodes/instanceOf.ts
+++ b/src/gateway/opcodes/instanceOf.ts
@@ -1,4 +1,4 @@
-import { instanceOf } from "lambert-server";
+import { instanceOf } from "@fosscord/util";
import { WebSocket } from "@fosscord/gateway";
import { CLOSECODES } from "../util/Constants";
diff --git a/gateway/src/start.ts b/src/gateway/start.ts
index 09a54751..2000522a 100644
--- a/gateway/src/start.ts
+++ b/src/gateway/start.ts
@@ -5,7 +5,7 @@ import { Server } from "./Server";
import { config } from "dotenv";
config();
-var port = Number(process.env.PORT);
+let port = Number(process.env.PORT);
if (isNaN(port)) port = 3002;
const server = new Server({
diff --git a/gateway/src/util/Constants.ts b/src/gateway/util/Constants.ts
index 692f9028..692f9028 100644
--- a/gateway/src/util/Constants.ts
+++ b/src/gateway/util/Constants.ts
diff --git a/gateway/src/util/Heartbeat.ts b/src/gateway/util/Heartbeat.ts
index f6871cfe..f6871cfe 100644
--- a/gateway/src/util/Heartbeat.ts
+++ b/src/gateway/util/Heartbeat.ts
diff --git a/gateway/src/util/Send.ts b/src/gateway/util/Send.ts
index c8627b03..2a28d8e0 100644
--- a/gateway/src/util/Send.ts
+++ b/src/gateway/util/Send.ts
@@ -1,4 +1,4 @@
-var erlpack: any;
+let erlpack: any;
try {
erlpack = require("@yukikaze-bot/erlpack");
} catch (error) {
@@ -7,6 +7,8 @@ try {
import { Payload, WebSocket } from "@fosscord/gateway";
export async function Send(socket: WebSocket, data: Payload) {
+ if(process.env.WS_VERBOSE)
+ console.log(`[Websocket] Outgoing message: ${JSON.stringify(data)}`);
let buffer: Buffer | string;
if (socket.encoding === "etf") buffer = erlpack.pack(data);
// TODO: encode circular object
diff --git a/gateway/src/util/SessionUtils.ts b/src/gateway/util/SessionUtils.ts
index bf854042..bf854042 100644
--- a/gateway/src/util/SessionUtils.ts
+++ b/src/gateway/util/SessionUtils.ts
diff --git a/gateway/src/util/WebSocket.ts b/src/gateway/util/WebSocket.ts
index e3313f40..9496da85 100644
--- a/gateway/src/util/WebSocket.ts
+++ b/src/gateway/util/WebSocket.ts
@@ -8,8 +8,8 @@ export interface WebSocket extends WS {
session_id: string;
encoding: "etf" | "json";
compress?: "zlib-stream";
- shard_count?: bigint;
- shard_id?: bigint;
+ shard_count?: number;
+ shard_id?: number;
deflate?: Deflate;
heartbeatTimeout: NodeJS.Timeout;
readyTimeout: NodeJS.Timeout;
diff --git a/gateway/src/util/index.ts b/src/gateway/util/index.ts
index 0be5ecee..0be5ecee 100644
--- a/gateway/src/util/index.ts
+++ b/src/gateway/util/index.ts
diff --git a/src/plugins/example-plugin/build.sh b/src/plugins/example-plugin/build.sh
new file mode 100755
index 00000000..1b36607b
--- /dev/null
+++ b/src/plugins/example-plugin/build.sh
@@ -0,0 +1,5 @@
+#rm -rf dist/
+#mkdir dist
+rm -rfv *.js *.js.map
+ln -s ../../bundle/node_modules node_modules
+tsc -p .
diff --git a/src/plugins/example-plugin/index.ts b/src/plugins/example-plugin/index.ts
new file mode 100644
index 00000000..d5db6563
--- /dev/null
+++ b/src/plugins/example-plugin/index.ts
@@ -0,0 +1,7 @@
+/*import { Plugin } from "@fosscord/util"
+
+export default class TestPlugin extends Plugin {
+ onPluginLoaded(): void {
+ console.log("Hello from test plugin! IT WORKS!!!!!!!");
+ }
+}*/
\ No newline at end of file
diff --git a/src/plugins/example-plugin/plugin.json b/src/plugins/example-plugin/plugin.json
new file mode 100644
index 00000000..980edbdf
--- /dev/null
+++ b/src/plugins/example-plugin/plugin.json
@@ -0,0 +1,9 @@
+{
+ "id": "example-plugin",
+ "name": "Fosscord example plugin",
+ "authors": [
+ "The Arcane Brony"
+ ],
+ "repository": "https://github.com/fosscord/fosscord-server",
+ "license": ""
+}
diff --git a/webrtc/tsconfig.json b/src/plugins/example-plugin/tsconfig.json
index 77353db0..7efe9434 100644
--- a/webrtc/tsconfig.json
+++ b/src/plugins/example-plugin/tsconfig.json
@@ -1,72 +1,85 @@
-{
- "include": ["src/**/*.ts"],
- "compilerOptions": {
- /* Visit https://aka.ms/tsconfig.json to read more about this file */
-
- /* Basic Options */
- // "incremental": true, /* Enable incremental compilation */
- "target": "ESNext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
- "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
- "lib": [
- "ES2021"
- ] /* Specify library files to be included in the compilation. */,
- "allowJs": true /* Allow javascript files to be compiled. */,
- "checkJs": true /* Report errors in .js files. */,
- // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
- "declaration": true /* Generates corresponding '.d.ts' file. */,
- "declarationMap": false /* Generates a sourcemap for each corresponding '.d.ts' file. */,
- "sourceMap": true /* Generates corresponding '.map' file. */,
- // "outFile": "./", /* Concatenate and emit output to single file. */
- "outDir": "./dist/" /* Redirect output structure to the directory. */,
- "rootDir": "./src/" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
- // "composite": true, /* Enable project compilation */
- // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
- // "removeComments": true, /* Do not emit comments to output. */
- // "noEmit": true, /* Do not emit outputs. */
- // "importHelpers": true, /* Import emit helpers from 'tslib'. */
- // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
- // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
-
- /* Strict Type-Checking Options */
- "strict": true /* Enable all strict type-checking options. */,
- "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
- "strictNullChecks": true /* Enable strict null checks. */,
- // "strictFunctionTypes": true, /* Enable strict checking of function types. */
- // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
- "strictPropertyInitialization": false /* Enable strict checking of property initialization in classes. */,
- // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
- "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
-
- /* Additional Checks */
- // "noUnusedLocals": true, /* Report errors on unused locals. */
- // "noUnusedParameters": true, /* Report errors on unused parameters. */
- // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
- // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
-
- /* Module Resolution Options */
- // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
- // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
- // "typeRoots": [], /* List of folders to include type definitions from. */
- "types": [
- "node"
- ] /* Type declaration files to be included in compilation. */,
- // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
- "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
- // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
- // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
-
- /* Source Map Options */
- // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
- // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
- // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
- // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
-
- /* Experimental Options */
- // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
- // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
-
- /* Advanced Options */
- "skipLibCheck": true /* Skip type checking of declaration files. */,
- "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
- }
-}
+{
+ "include": ["./**/*.ts"],
+ "exclude": [],
+ "compilerOptions": {
+
+ /* Basic Options */
+ "incremental": false /* Enable incremental compilation */,
+ "target": "ESNext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
+ "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
+ "lib": [
+ "ESNext"
+ ] /* Specify library files to be included in the compilation. */,
+ "allowJs": true /* Allow javascript files to be compiled. */,
+ "checkJs": true /* Report errors in .js files. */,
+ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
+ "declaration": false /* Generates corresponding '.d.ts' file. */,
+ "declarationMap": false /* Generates a sourcemap for each corresponding '.d.ts' file. */,
+ "sourceMap": true /* Generates corresponding '.map' file. */,
+ // "outFile": "./", /* Concatenate and emit output to single file. */
+ "outDir": "./dist/" /* Redirect output structure to the directory. */,
+ "rootDir": "./" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
+ // "composite": true, /* Enable project compilation */
+ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
+ // "removeComments": true, /* Do not emit comments to output. */
+ // "noEmit": true, /* Do not emit outputs. */
+ // "importHelpers": true, /* Import emit helpers from 'tslib'. */
+ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
+ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
+
+ /* Strict Type-Checking Options */
+ "strict": true /* Enable all strict type-checking options. */,
+ "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
+ "strictNullChecks": true /* Enable strict null checks. */,
+ // "strictFunctionTypes": true, /* Enable strict checking of function types. */
+ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
+ "strictPropertyInitialization": false /* Enable strict checking of property initialization in classes. */,
+ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
+ "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
+
+ /* Additional Checks */
+ // "noUnusedLocals": true, /* Report errors on unused locals. */
+ // "noUnusedParameters": true, /* Report errors on unused parameters. */
+ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
+ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
+
+ /* Module Resolution Options */
+ "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
+ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
+ // "typeRoots": [], /* List of folders to include type definitions from. */
+ "types": [
+ "node"
+ ] /* Type declaration files to be included in compilation. */,
+ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
+ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
+
+ /* Source Map Options */
+ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
+ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
+
+ /* Experimental Options */
+ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
+ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
+
+ /* Advanced Options */
+ "skipLibCheck": true /* Skip type checking of declaration files. */,
+ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "resolveJsonModule": true,
+ "baseUrl": "../../bundle/dist/",
+ "paths": {
+ "@fosscord/api": ["../../api/src/index"],
+ "@fosscord/gateway": ["../../gateway/src/index"],
+ "@fosscord/cdn": ["../../cdn/src/index"],
+ "@fosscord/util": ["../../util/src/index"]
+ },
+ "plugins": [{ "transform": "@ovos-media/ts-transform-paths" }],
+ "noEmitHelpers": true,
+ "importHelpers": true
+ }
+}
diff --git a/bundle/src/start.ts b/src/start.ts
index de3b5848..a20581c3 100644
--- a/bundle/src/start.ts
+++ b/src/start.ts
@@ -9,7 +9,7 @@ config();
import { execSync } from "child_process";
// TODO: add socket event transmission
-var cores = 1;
+let cores = 1;
try {
cores = Number(process.env.THREADS) || os.cpus().length;
} catch {
diff --git a/src/stats.ts b/src/stats.ts
new file mode 100644
index 00000000..654e0a4f
--- /dev/null
+++ b/src/stats.ts
@@ -0,0 +1,24 @@
+import os from "os";
+import { red } from "picocolors";
+
+export function initStats() {
+
+ console.log(`[Path] running in ${__dirname}`);
+ try {
+ console.log(`[CPU] ${os.cpus()[0].model} Cores x${os.cpus().length}`);
+ }
+ catch {
+ console.log('[CPU] Failed to get cpu model!')
+ }
+
+ console.log(`[System] ${os.platform()} ${os.arch()}`);
+ console.log(`[Process] running with PID: ${process.pid}`);
+ if (process.getuid && process.getuid() === 0) {
+ console.warn(
+ red(
+ `[Process] Warning fosscord is running as root, this highly discouraged and might expose your system vulnerable to attackers. Please run fosscord as a user without root privileges.`
+ )
+ );
+ }
+
+}
diff --git a/src/util/config/Config.ts b/src/util/config/Config.ts
new file mode 100644
index 00000000..7aee1775
--- /dev/null
+++ b/src/util/config/Config.ts
@@ -0,0 +1,22 @@
+import { ApiConfiguration, ClientConfiguration, DefaultsConfiguration, EndpointConfiguration, GeneralConfiguration, GifConfiguration, GuildConfiguration, KafkaConfiguration, LimitsConfiguration, LoginConfiguration, MetricsConfiguration, RabbitMQConfiguration, RegionConfiguration, RegisterConfiguration, SecurityConfiguration, SentryConfiguration, TemplateConfiguration } from ".";
+
+export class ConfigValue {
+ gateway: EndpointConfiguration = new EndpointConfiguration();
+ cdn: EndpointConfiguration = new EndpointConfiguration();
+ api: ApiConfiguration = new ApiConfiguration();
+ general: GeneralConfiguration = new GeneralConfiguration();
+ limits: LimitsConfiguration = new LimitsConfiguration();
+ security: SecurityConfiguration = new SecurityConfiguration();
+ login: LoginConfiguration = new LoginConfiguration();
+ register: RegisterConfiguration = new RegisterConfiguration();
+ regions: RegionConfiguration = new RegionConfiguration();
+ guild: GuildConfiguration = new GuildConfiguration();
+ gif: GifConfiguration = new GifConfiguration();
+ rabbitmq: RabbitMQConfiguration = new RabbitMQConfiguration();
+ kafka: KafkaConfiguration = new KafkaConfiguration();
+ templates: TemplateConfiguration = new TemplateConfiguration();
+ client: ClientConfiguration = new ClientConfiguration();
+ metrics: MetricsConfiguration = new MetricsConfiguration();
+ sentry: SentryConfiguration = new SentryConfiguration();
+ defaults: DefaultsConfiguration = new DefaultsConfiguration();
+}
\ No newline at end of file
diff --git a/src/util/config/index.ts b/src/util/config/index.ts
new file mode 100644
index 00000000..0a9b58ae
--- /dev/null
+++ b/src/util/config/index.ts
@@ -0,0 +1,2 @@
+export * from "./Config";
+export * from "./types/index";
diff --git a/src/util/config/types/ApiConfiguration.ts b/src/util/config/types/ApiConfiguration.ts
new file mode 100644
index 00000000..16b1efba
--- /dev/null
+++ b/src/util/config/types/ApiConfiguration.ts
@@ -0,0 +1,5 @@
+export class ApiConfiguration {
+ defaultVersion: string = "9";
+ activeVersions: string[] = ["6", "7", "8", "9"];
+ useFosscordEnhancements: boolean = true;
+}
\ No newline at end of file
diff --git a/src/util/config/types/ClientConfiguration.ts b/src/util/config/types/ClientConfiguration.ts
new file mode 100644
index 00000000..1adda1e2
--- /dev/null
+++ b/src/util/config/types/ClientConfiguration.ts
@@ -0,0 +1,8 @@
+import { ClientReleaseConfiguration } from ".";
+
+export class ClientConfiguration {
+ //classes
+ releases: ClientReleaseConfiguration = new ClientReleaseConfiguration();
+ //base types
+ useTestClient: boolean = true;
+}
\ No newline at end of file
diff --git a/src/util/config/types/DefaultsConfiguration.ts b/src/util/config/types/DefaultsConfiguration.ts
new file mode 100644
index 00000000..9b02a590
--- /dev/null
+++ b/src/util/config/types/DefaultsConfiguration.ts
@@ -0,0 +1,6 @@
+import { GuildDefaults, UserDefaults } from ".";
+
+export class DefaultsConfiguration {
+ guild: GuildDefaults = new GuildDefaults();
+ user: UserDefaults = new UserDefaults();
+}
\ No newline at end of file
diff --git a/src/util/config/types/EndpointConfiguration.ts b/src/util/config/types/EndpointConfiguration.ts
new file mode 100644
index 00000000..87baea31
--- /dev/null
+++ b/src/util/config/types/EndpointConfiguration.ts
@@ -0,0 +1,5 @@
+export class EndpointConfiguration {
+ endpointClient: string | null = null;
+ endpointPrivate: string | null = null;
+ endpointPublic: string | null = null;
+}
\ No newline at end of file
diff --git a/src/util/config/types/GeneralConfiguration.ts b/src/util/config/types/GeneralConfiguration.ts
new file mode 100644
index 00000000..55848b44
--- /dev/null
+++ b/src/util/config/types/GeneralConfiguration.ts
@@ -0,0 +1,12 @@
+import { Snowflake } from "../../util";
+
+export class GeneralConfiguration {
+ instanceName: string = "Fosscord Instance";
+ instanceDescription: string | null = "This is a Fosscord instance made in the pre-release days";
+ frontPage: string | null = null;
+ tosPage: string | null = null;
+ correspondenceEmail: string | null = "noreply@localhost.local";
+ correspondenceUserID: string | null = null;
+ image: string | null = null;
+ instanceId: string = Snowflake.generate();
+}
\ No newline at end of file
diff --git a/src/util/config/types/GifConfiguration.ts b/src/util/config/types/GifConfiguration.ts
new file mode 100644
index 00000000..6a2d520d
--- /dev/null
+++ b/src/util/config/types/GifConfiguration.ts
@@ -0,0 +1,5 @@
+export class GifConfiguration {
+ enabled: boolean = true;
+ provider: "tenor" = "tenor"; // more coming soon
+ apiKey?: string = "LIVDSRZULELA";
+}
\ No newline at end of file
diff --git a/src/util/config/types/GuildConfiguration.ts b/src/util/config/types/GuildConfiguration.ts
new file mode 100644
index 00000000..3d43b368
--- /dev/null
+++ b/src/util/config/types/GuildConfiguration.ts
@@ -0,0 +1,6 @@
+import { DiscoveryConfiguration, AutoJoinConfiguration } from ".";
+
+export class GuildConfiguration {
+ discovery: DiscoveryConfiguration = new DiscoveryConfiguration();
+ autoJoin: AutoJoinConfiguration = new AutoJoinConfiguration();
+}
diff --git a/src/util/config/types/KafkaConfiguration.ts b/src/util/config/types/KafkaConfiguration.ts
new file mode 100644
index 00000000..7932f49e
--- /dev/null
+++ b/src/util/config/types/KafkaConfiguration.ts
@@ -0,0 +1,5 @@
+import { KafkaBroker } from ".";
+
+export class KafkaConfiguration {
+ brokers: KafkaBroker[] | null = null;
+}
\ No newline at end of file
diff --git a/src/util/config/types/LimitConfigurations.ts b/src/util/config/types/LimitConfigurations.ts
new file mode 100644
index 00000000..bcc2e7e2
--- /dev/null
+++ b/src/util/config/types/LimitConfigurations.ts
@@ -0,0 +1,9 @@
+import { ChannelLimits, GuildLimits, MessageLimits, RateLimits, UserLimits } from ".";
+
+export class LimitsConfiguration {
+ user: UserLimits = new UserLimits();
+ guild: GuildLimits = new GuildLimits();
+ message: MessageLimits = new MessageLimits();
+ channel: ChannelLimits = new ChannelLimits();
+ rate: RateLimits = new RateLimits();
+}
\ No newline at end of file
diff --git a/src/util/config/types/LoginConfiguration.ts b/src/util/config/types/LoginConfiguration.ts
new file mode 100644
index 00000000..255c9451
--- /dev/null
+++ b/src/util/config/types/LoginConfiguration.ts
@@ -0,0 +1,3 @@
+export class LoginConfiguration {
+ requireCaptcha: boolean = false;
+}
\ No newline at end of file
diff --git a/src/util/config/types/MetricsConfiguration.ts b/src/util/config/types/MetricsConfiguration.ts
new file mode 100644
index 00000000..d7cd4937
--- /dev/null
+++ b/src/util/config/types/MetricsConfiguration.ts
@@ -0,0 +1,3 @@
+export class MetricsConfiguration {
+ timeout: number = 30000;
+}
\ No newline at end of file
diff --git a/src/util/config/types/RabbitMQConfiguration.ts b/src/util/config/types/RabbitMQConfiguration.ts
new file mode 100644
index 00000000..ce4a9123
--- /dev/null
+++ b/src/util/config/types/RabbitMQConfiguration.ts
@@ -0,0 +1,3 @@
+export class RabbitMQConfiguration {
+ host: string | null = null;
+}
\ No newline at end of file
diff --git a/src/util/config/types/RegionConfiguration.ts b/src/util/config/types/RegionConfiguration.ts
new file mode 100644
index 00000000..09d9271c
--- /dev/null
+++ b/src/util/config/types/RegionConfiguration.ts
@@ -0,0 +1,16 @@
+import { Region } from ".";
+
+export class RegionConfiguration {
+ default: string = "fosscord";
+ useDefaultAsOptimal: boolean = true;
+ available: Region[] = [
+ {
+ id: "fosscord",
+ name: "Fosscord",
+ endpoint: "127.0.0.1:3004",
+ vip: false,
+ custom: false,
+ deprecated: false,
+ },
+ ];
+}
\ No newline at end of file
diff --git a/src/util/config/types/RegisterConfiguration.ts b/src/util/config/types/RegisterConfiguration.ts
new file mode 100644
index 00000000..a0dc97c5
--- /dev/null
+++ b/src/util/config/types/RegisterConfiguration.ts
@@ -0,0 +1,18 @@
+import { DateOfBirthConfiguration, EmailConfiguration, PasswordConfiguration } from ".";
+
+export class RegisterConfiguration {
+ //classes
+ email: EmailConfiguration = new EmailConfiguration();
+ dateOfBirth: DateOfBirthConfiguration = new DateOfBirthConfiguration();
+ password: PasswordConfiguration = new PasswordConfiguration();
+ //base types
+ disabled: boolean = false;
+ requireCaptcha: boolean = true;
+ requireInvite: boolean = false;
+ guestsRequireInvite: boolean = true;
+ allowNewRegistration: boolean = true;
+ allowMultipleAccounts: boolean = true;
+ blockProxies: boolean = true;
+ incrementingDiscriminators: boolean = false; // random otherwise
+ defaultRights: string = "0";
+}
diff --git a/src/util/config/types/SecurityConfiguration.ts b/src/util/config/types/SecurityConfiguration.ts
new file mode 100644
index 00000000..405b86ac
--- /dev/null
+++ b/src/util/config/types/SecurityConfiguration.ts
@@ -0,0 +1,17 @@
+import crypto from "crypto";
+import { CaptchaConfiguration, TwoFactorConfiguration } from ".";
+
+export class SecurityConfiguration {
+ //classes
+ captcha: CaptchaConfiguration = new CaptchaConfiguration();
+ twoFactor: TwoFactorConfiguration = new TwoFactorConfiguration();
+ //base types
+ autoUpdate: boolean | number = true;
+ requestSignature: string = crypto.randomBytes(32).toString("base64");
+ jwtSecret: string = crypto.randomBytes(256).toString("base64");
+ // header to get the real user ip address
+ // X-Forwarded-For for nginx/reverse proxies
+ // CF-Connecting-IP for cloudflare
+ forwadedFor: string | null = null;
+ ipdataApiKey: string | null = "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9";
+}
diff --git a/src/util/config/types/SentryConfiguration.ts b/src/util/config/types/SentryConfiguration.ts
new file mode 100644
index 00000000..836094a1
--- /dev/null
+++ b/src/util/config/types/SentryConfiguration.ts
@@ -0,0 +1,8 @@
+import { hostname } from "os";
+
+export class SentryConfiguration {
+ enabled: boolean = false;
+ endpoint: string = "https://05e8e3d005f34b7d97e920ae5870a5e5@sentry.thearcanebrony.net/6";
+ traceSampleRate: number = 1.0;
+ environment: string = hostname();
+}
\ No newline at end of file
diff --git a/src/util/config/types/TemplateConfiguration.ts b/src/util/config/types/TemplateConfiguration.ts
new file mode 100644
index 00000000..4a9aa8f2
--- /dev/null
+++ b/src/util/config/types/TemplateConfiguration.ts
@@ -0,0 +1,6 @@
+export class TemplateConfiguration {
+ enabled: boolean = true;
+ allowTemplateCreation: boolean = true;
+ allowDiscordTemplates: boolean = true;
+ allowRaws: boolean = true;
+}
\ No newline at end of file
diff --git a/src/util/config/types/index.ts b/src/util/config/types/index.ts
new file mode 100644
index 00000000..608503a0
--- /dev/null
+++ b/src/util/config/types/index.ts
@@ -0,0 +1,18 @@
+export * from "./ApiConfiguration";
+export * from "./ClientConfiguration";
+export * from "./DefaultsConfiguration";
+export * from "./EndpointConfiguration";
+export * from "./GeneralConfiguration";
+export * from "./GifConfiguration";
+export * from "./GuildConfiguration";
+export * from "./KafkaConfiguration";
+export * from "./LimitConfigurations";
+export * from "./LoginConfiguration";
+export * from "./MetricsConfiguration";
+export * from "./RabbitMQConfiguration";
+export * from "./RegionConfiguration";
+export * from "./RegisterConfiguration";
+export * from "./SecurityConfiguration";
+export * from "./SentryConfiguration";
+export * from "./TemplateConfiguration";
+export * from "./subconfigurations/index";
diff --git a/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts b/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts
new file mode 100644
index 00000000..54e7f365
--- /dev/null
+++ b/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts
@@ -0,0 +1,4 @@
+export class ClientReleaseConfiguration {
+ useLocalRelease: boolean = true; //TODO
+ upstreamVersion: string = "0.0.264";
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/client/index.ts b/src/util/config/types/subconfigurations/client/index.ts
new file mode 100644
index 00000000..96bbb0ca
--- /dev/null
+++ b/src/util/config/types/subconfigurations/client/index.ts
@@ -0,0 +1 @@
+export * from "./ClientReleaseConfiguration";
diff --git a/src/util/config/types/subconfigurations/defaults/GuildDefaults.ts b/src/util/config/types/subconfigurations/defaults/GuildDefaults.ts
new file mode 100644
index 00000000..d6ff7697
--- /dev/null
+++ b/src/util/config/types/subconfigurations/defaults/GuildDefaults.ts
@@ -0,0 +1,8 @@
+export class GuildDefaults {
+ maxPresences: number = 250000;
+ maxVideoChannelUsers: number = 200;
+ afkTimeout: number = 300;
+ defaultMessageNotifications: number = 1;
+ explicitContentFilter: number = 0;
+ test: number = 123;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/defaults/UserDefaults.ts b/src/util/config/types/subconfigurations/defaults/UserDefaults.ts
new file mode 100644
index 00000000..4481c011
--- /dev/null
+++ b/src/util/config/types/subconfigurations/defaults/UserDefaults.ts
@@ -0,0 +1,5 @@
+export class UserDefaults {
+ premium: boolean = false;
+ premium_type: number = 2;
+ verified: boolean = true;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/defaults/index.ts b/src/util/config/types/subconfigurations/defaults/index.ts
new file mode 100644
index 00000000..50258d1c
--- /dev/null
+++ b/src/util/config/types/subconfigurations/defaults/index.ts
@@ -0,0 +1,2 @@
+export * from "./GuildDefaults";
+export * from "./UserDefaults";
diff --git a/src/util/config/types/subconfigurations/guild/AutoJoin.ts b/src/util/config/types/subconfigurations/guild/AutoJoin.ts
new file mode 100644
index 00000000..47dfe5ec
--- /dev/null
+++ b/src/util/config/types/subconfigurations/guild/AutoJoin.ts
@@ -0,0 +1,5 @@
+export class AutoJoinConfiguration {
+ enabled: boolean = true;
+ guilds: string[] = [];
+ canLeave: boolean = true;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/guild/Discovery.ts b/src/util/config/types/subconfigurations/guild/Discovery.ts
new file mode 100644
index 00000000..59d8a8ae
--- /dev/null
+++ b/src/util/config/types/subconfigurations/guild/Discovery.ts
@@ -0,0 +1,6 @@
+export class DiscoveryConfiguration {
+ showAllGuilds: boolean = false;
+ useRecommendation: boolean = false; // TODO: Recommendation, privacy concern?
+ offset: number = 0;
+ limit: number = 24;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/guild/index.ts b/src/util/config/types/subconfigurations/guild/index.ts
new file mode 100644
index 00000000..e9614856
--- /dev/null
+++ b/src/util/config/types/subconfigurations/guild/index.ts
@@ -0,0 +1,2 @@
+export * from "./AutoJoin";
+export * from "./Discovery";
diff --git a/src/util/config/types/subconfigurations/index.ts b/src/util/config/types/subconfigurations/index.ts
new file mode 100644
index 00000000..bfbadc92
--- /dev/null
+++ b/src/util/config/types/subconfigurations/index.ts
@@ -0,0 +1,8 @@
+export * from "./client/index";
+export * from "./defaults/index";
+export * from "./guild/index";
+export * from "./kafka/index";
+export * from "./limits/index";
+export * from "./region/index";
+export * from "./register/index";
+export * from "./security/index";
diff --git a/src/util/config/types/subconfigurations/kafka/KafkaBroker.ts b/src/util/config/types/subconfigurations/kafka/KafkaBroker.ts
new file mode 100644
index 00000000..4f9a5e51
--- /dev/null
+++ b/src/util/config/types/subconfigurations/kafka/KafkaBroker.ts
@@ -0,0 +1,4 @@
+export interface KafkaBroker {
+ ip: string;
+ port: number;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/kafka/index.ts b/src/util/config/types/subconfigurations/kafka/index.ts
new file mode 100644
index 00000000..2c633950
--- /dev/null
+++ b/src/util/config/types/subconfigurations/kafka/index.ts
@@ -0,0 +1 @@
+export * from "./KafkaBroker";
diff --git a/src/util/config/types/subconfigurations/limits/ChannelLimits.ts b/src/util/config/types/subconfigurations/limits/ChannelLimits.ts
new file mode 100644
index 00000000..2f8f9485
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/ChannelLimits.ts
@@ -0,0 +1,5 @@
+export class ChannelLimits {
+ maxPins: number = 500;
+ maxTopic: number = 1024;
+ maxWebhooks: number = 100;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/GuildLimits.ts b/src/util/config/types/subconfigurations/limits/GuildLimits.ts
new file mode 100644
index 00000000..91ad39ae
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/GuildLimits.ts
@@ -0,0 +1,8 @@
+export class GuildLimits {
+ maxRoles: number = 1000;
+ maxEmojis: number = 2000;
+ maxMembers: number = 25000000;
+ maxChannels: number = 65535;
+ maxChannelsInCategory: number = 65535;
+ hideOfflineMember: number = 3;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/MessageLimits.ts b/src/util/config/types/subconfigurations/limits/MessageLimits.ts
new file mode 100644
index 00000000..51576b90
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/MessageLimits.ts
@@ -0,0 +1,8 @@
+export class MessageLimits {
+ maxCharacters: number = 1048576;
+ maxTTSCharacters: number = 160;
+ maxReactions: number = 2048;
+ maxAttachmentSize: number = 1024 * 1024 * 1024;
+ maxBulkDelete: number = 1000;
+ maxEmbedDownloadSize: number = 1024 * 1024 * 5;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/RateLimits.ts b/src/util/config/types/subconfigurations/limits/RateLimits.ts
new file mode 100644
index 00000000..25e7a1e0
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/RateLimits.ts
@@ -0,0 +1,18 @@
+import { RouteRateLimit, RateLimitOptions } from ".";
+
+export class RateLimits {
+ disabled: boolean = true;
+ ip: Omit<RateLimitOptions, "bot_count"> = {
+ count: 500,
+ window: 5
+ };
+ global: RateLimitOptions = {
+ count: 250,
+ window: 5
+ };
+ error: RateLimitOptions = {
+ count: 10,
+ window: 5
+ };
+ routes: RouteRateLimit;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/UserLimits.ts b/src/util/config/types/subconfigurations/limits/UserLimits.ts
new file mode 100644
index 00000000..0d10e0b3
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/UserLimits.ts
@@ -0,0 +1,5 @@
+export class UserLimits {
+ maxGuilds: number = 1048576;
+ maxUsername: number = 127;
+ maxFriends: number = 5000;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/index.ts b/src/util/config/types/subconfigurations/limits/index.ts
new file mode 100644
index 00000000..0b7304f6
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/index.ts
@@ -0,0 +1,6 @@
+export * from "./ChannelLimits";
+export * from "./GuildLimits";
+export * from "./MessageLimits";
+export * from "./RateLimits";
+export * from "./UserLimits";
+export * from "./ratelimits/index";
diff --git a/src/util/config/types/subconfigurations/limits/ratelimits/Auth.ts b/src/util/config/types/subconfigurations/limits/ratelimits/Auth.ts
new file mode 100644
index 00000000..df171044
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/ratelimits/Auth.ts
@@ -0,0 +1,12 @@
+import { RateLimitOptions } from "./RateLimitOptions";
+
+export class AuthRateLimit {
+ login: RateLimitOptions = {
+ count: 5,
+ window: 60
+ };
+ register: RateLimitOptions = {
+ count: 2,
+ window: 60 * 60 * 12
+ };
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/ratelimits/RateLimitOptions.ts b/src/util/config/types/subconfigurations/limits/ratelimits/RateLimitOptions.ts
new file mode 100644
index 00000000..7089e28e
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/ratelimits/RateLimitOptions.ts
@@ -0,0 +1,6 @@
+export interface RateLimitOptions {
+ bot?: number;
+ count: number;
+ window: number;
+ onyIp?: boolean;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/ratelimits/Route.ts b/src/util/config/types/subconfigurations/limits/ratelimits/Route.ts
new file mode 100644
index 00000000..844b1b9a
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/ratelimits/Route.ts
@@ -0,0 +1,19 @@
+import { AuthRateLimit } from "./Auth";
+import { RateLimitOptions } from "./RateLimitOptions";
+
+export class RouteRateLimit {
+ guild: RateLimitOptions = {
+ count: 5,
+ window: 5
+ };
+ webhook: RateLimitOptions = {
+ count: 10,
+ window: 5
+ };
+ channel: RateLimitOptions = {
+ count: 10,
+ window: 5
+ };
+ auth: AuthRateLimit;
+ // TODO: rate limit configuration for all routes
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/ratelimits/index.ts b/src/util/config/types/subconfigurations/limits/ratelimits/index.ts
new file mode 100644
index 00000000..432eb601
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/ratelimits/index.ts
@@ -0,0 +1,3 @@
+export * from "./Auth";
+export * from "./RateLimitOptions";
+export * from "./Route";
diff --git a/src/util/config/types/subconfigurations/region/Region.ts b/src/util/config/types/subconfigurations/region/Region.ts
new file mode 100644
index 00000000..a8717e1f
--- /dev/null
+++ b/src/util/config/types/subconfigurations/region/Region.ts
@@ -0,0 +1,12 @@
+export interface Region {
+ id: string;
+ name: string;
+ endpoint: string;
+ location?: {
+ latitude: number;
+ longitude: number;
+ };
+ vip: boolean;
+ custom: boolean;
+ deprecated: boolean;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/region/index.ts b/src/util/config/types/subconfigurations/region/index.ts
new file mode 100644
index 00000000..2beb8de7
--- /dev/null
+++ b/src/util/config/types/subconfigurations/region/index.ts
@@ -0,0 +1 @@
+export * from "./Region";
diff --git a/src/util/config/types/subconfigurations/register/DateOfBirth.ts b/src/util/config/types/subconfigurations/register/DateOfBirth.ts
new file mode 100644
index 00000000..5a3c4e9d
--- /dev/null
+++ b/src/util/config/types/subconfigurations/register/DateOfBirth.ts
@@ -0,0 +1,4 @@
+export class DateOfBirthConfiguration {
+ required: boolean = true;
+ minimum: number = 13; // in years
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/register/Email.ts b/src/util/config/types/subconfigurations/register/Email.ts
new file mode 100644
index 00000000..115d49e0
--- /dev/null
+++ b/src/util/config/types/subconfigurations/register/Email.ts
@@ -0,0 +1,7 @@
+export class EmailConfiguration {
+ required: boolean = false;
+ allowlist: boolean = false;
+ blocklist: boolean = true;
+ domains: string[] = [];// TODO: efficiently save domain blocklist in database
+ // domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"),
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/register/Password.ts b/src/util/config/types/subconfigurations/register/Password.ts
new file mode 100644
index 00000000..977473ac
--- /dev/null
+++ b/src/util/config/types/subconfigurations/register/Password.ts
@@ -0,0 +1,7 @@
+export class PasswordConfiguration {
+ required: boolean = false;
+ minLength: number = 8;
+ minNumbers: number = 2;
+ minUpperCase: number =2;
+ minSymbols: number = 0;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/register/index.ts b/src/util/config/types/subconfigurations/register/index.ts
new file mode 100644
index 00000000..d9738120
--- /dev/null
+++ b/src/util/config/types/subconfigurations/register/index.ts
@@ -0,0 +1,3 @@
+export * from "./DateOfBirth";
+export * from "./Email";
+export * from "./Password";
diff --git a/src/util/config/types/subconfigurations/security/Captcha.ts b/src/util/config/types/subconfigurations/security/Captcha.ts
new file mode 100644
index 00000000..ad6aa762
--- /dev/null
+++ b/src/util/config/types/subconfigurations/security/Captcha.ts
@@ -0,0 +1,6 @@
+export class CaptchaConfiguration {
+ enabled: boolean = false;
+ service: "recaptcha" | "hcaptcha" | null = null; // TODO: hcaptcha, custom
+ sitekey: string | null = null;
+ secret: string | null = null;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/security/TwoFactor.ts b/src/util/config/types/subconfigurations/security/TwoFactor.ts
new file mode 100644
index 00000000..33a47385
--- /dev/null
+++ b/src/util/config/types/subconfigurations/security/TwoFactor.ts
@@ -0,0 +1,3 @@
+export class TwoFactorConfiguration {
+ generateBackupCodes: boolean = true;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/security/index.ts b/src/util/config/types/subconfigurations/security/index.ts
new file mode 100644
index 00000000..17619589
--- /dev/null
+++ b/src/util/config/types/subconfigurations/security/index.ts
@@ -0,0 +1,2 @@
+export * from "./Captcha";
+export * from "./TwoFactor";
diff --git a/util/src/dtos/DmChannelDTO.ts b/src/util/dtos/DmChannelDTO.ts
index 226b2f9d..226b2f9d 100644
--- a/util/src/dtos/DmChannelDTO.ts
+++ b/src/util/dtos/DmChannelDTO.ts
diff --git a/util/src/dtos/UserDTO.ts b/src/util/dtos/UserDTO.ts
index ee2752a4..ee2752a4 100644
--- a/util/src/dtos/UserDTO.ts
+++ b/src/util/dtos/UserDTO.ts
diff --git a/util/src/dtos/index.ts b/src/util/dtos/index.ts
index 0e8f8459..0e8f8459 100644
--- a/util/src/dtos/index.ts
+++ b/src/util/dtos/index.ts
diff --git a/util/src/entities/Application.ts b/src/util/entities/Application.ts
index fab3d93f..103f8e84 100644
--- a/util/src/entities/Application.ts
+++ b/src/util/entities/Application.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, OneToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
import { Team } from "./Team";
@@ -8,21 +8,77 @@ import { User } from "./User";
export class Application extends BaseClass {
@Column()
name: string;
-
+
@Column({ nullable: true })
icon?: string;
-
- @Column()
+
+ @Column({ nullable: true })
description: string;
-
- @Column({ type: "simple-array", nullable: true })
- rpc_origins?: string[];
-
+
+ @Column({ nullable: true })
+ summary: string = "";
+
+ @Column({ type: "simple-json", nullable: true })
+ type?: any;
+
@Column()
- bot_public: boolean;
-
+ hook: boolean = true;
+
+ @Column()
+ bot_public?: boolean = true;
+
+ @Column()
+ bot_require_code_grant?: boolean = false;
+
@Column()
- bot_require_code_grant: boolean;
+ verify_key: string;
+
+ @JoinColumn({ name: "owner_id" })
+ @ManyToOne(() => User)
+ owner: User;
+
+ @Column()
+ flags: number = 0;
+
+ @Column({ type: "simple-array", nullable: true })
+ redirect_uris: string[] = [];
+
+ @Column({ nullable: true })
+ rpc_application_state: number = 0;
+
+ @Column({ nullable: true })
+ store_application_state: number = 1;
+
+ @Column({ nullable: true })
+ verification_state: number = 1;
+
+ @Column({ nullable: true })
+ interactions_endpoint_url?: string;
+
+ @Column({ nullable: true })
+ integration_public: boolean = true;
+
+ @Column({ nullable: true })
+ integration_require_code_grant: boolean = false;
+
+ @Column({ nullable: true })
+ discoverability_state: number = 1;
+
+ @Column({ nullable: true })
+ discovery_eligibility_flags: number = 2240;
+
+ @JoinColumn({ name: "bot_user_id" })
+ @OneToOne(() => User)
+ bot?: User;
+
+ @Column({ type: "simple-array", nullable: true })
+ tags?: string[];
+
+ @Column({ nullable: true })
+ cover_image?: string; // the application's default rich presence invite cover image hash
+
+ @Column({ type: "simple-json", nullable: true })
+ install_params?: {scopes: string[], permissions: string};
@Column({ nullable: true })
terms_of_service_url?: string;
@@ -30,38 +86,29 @@ export class Application extends BaseClass {
@Column({ nullable: true })
privacy_policy_url?: string;
- @JoinColumn({ name: "owner_id" })
- @ManyToOne(() => User)
- owner?: User;
+ //just for us
- @Column({ nullable: true })
- summary?: string;
+ //@Column({ type: "simple-array", nullable: true })
+ //rpc_origins?: string[];
+
+ //@JoinColumn({ name: "guild_id" })
+ //@ManyToOne(() => Guild)
+ //guild?: Guild; // if this application is a game sold, this field will be the guild to which it has been linked
- @Column()
- verify_key: string;
+ //@Column({ nullable: true })
+ //primary_sku_id?: string; // if this application is a game sold, this field will be the id of the "Game SKU" that is created,
+
+ //@Column({ nullable: true })
+ //slug?: string; // if this application is a game sold, this field will be the URL slug that links to the store page
@JoinColumn({ name: "team_id" })
@ManyToOne(() => Team, {
onDelete: "CASCADE",
+ nullable: true
})
team?: Team;
- @JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild)
- guild: Guild; // if this application is a game sold, this field will be the guild to which it has been linked
-
- @Column({ nullable: true })
- primary_sku_id?: string; // if this application is a game sold, this field will be the id of the "Game SKU" that is created,
-
- @Column({ nullable: true })
- slug?: string; // if this application is a game sold, this field will be the URL slug that links to the store page
-
- @Column({ nullable: true })
- cover_image?: string; // the application's default rich presence invite cover image hash
-
- @Column()
- flags: string; // the application's public flags
-}
+ }
export interface ApplicationCommand {
id: string;
diff --git a/util/src/entities/Attachment.ts b/src/util/entities/Attachment.ts
index 7b4b17eb..7b4b17eb 100644
--- a/util/src/entities/Attachment.ts
+++ b/src/util/entities/Attachment.ts
diff --git a/util/src/entities/AuditLog.ts b/src/util/entities/AuditLog.ts
index b003e7ba..b003e7ba 100644
--- a/util/src/entities/AuditLog.ts
+++ b/src/util/entities/AuditLog.ts
diff --git a/util/src/entities/BackupCodes.ts b/src/util/entities/BackupCodes.ts
index d532a39a..9092c14e 100644
--- a/util/src/entities/BackupCodes.ts
+++ b/src/util/entities/BackupCodes.ts
@@ -1,7 +1,6 @@
import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { User } from "./User";
-import crypto from "crypto";
@Entity("backup_codes")
export class BackupCode extends BaseClass {
@@ -17,19 +16,4 @@ export class BackupCode extends BaseClass {
@Column()
expired: boolean;
-}
-
-export function generateMfaBackupCodes(user_id: string) {
- let backup_codes: BackupCode[] = [];
- for (let i = 0; i < 10; i++) {
- const code = BackupCode.create({
- user: { id: user_id },
- code: crypto.randomBytes(4).toString("hex"), // 8 characters
- consumed: false,
- expired: false,
- });
- backup_codes.push(code);
- }
-
- return backup_codes;
}
\ No newline at end of file
diff --git a/util/src/entities/Ban.ts b/src/util/entities/Ban.ts
index 9504bd8e..9504bd8e 100644
--- a/util/src/entities/Ban.ts
+++ b/src/util/entities/Ban.ts
diff --git a/src/util/entities/BaseClass.ts b/src/util/entities/BaseClass.ts
new file mode 100644
index 00000000..aecc2465
--- /dev/null
+++ b/src/util/entities/BaseClass.ts
@@ -0,0 +1,26 @@
+import "reflect-metadata";
+import { BaseEntity, ObjectIdColumn, PrimaryColumn, SaveOptions } from "typeorm";
+import { Snowflake } from "../util/Snowflake";
+
+export class BaseClassWithoutId extends BaseEntity {
+ constructor() {
+ super();
+ }
+}
+
+export const PrimaryIdColumn = process.env.DATABASE?.startsWith("mongodb") ? ObjectIdColumn : PrimaryColumn;
+
+export class BaseClass extends BaseClassWithoutId {
+ @PrimaryIdColumn()
+ id: string;
+
+ constructor() {
+ super();
+ if (!this.id) this.id = Snowflake.generate();
+ }
+
+ save(options?: SaveOptions | undefined): Promise<this> {
+ if (!this.id) this.id = Snowflake.generate();
+ return super.save(options);
+ }
+}
diff --git a/util/src/entities/Categories.ts b/src/util/entities/Categories.ts
index 81fbc303..81fbc303 100644
--- a/util/src/entities/Categories.ts
+++ b/src/util/entities/Categories.ts
diff --git a/util/src/entities/Channel.ts b/src/util/entities/Channel.ts
index 69c08be7..a576d7af 100644
--- a/util/src/entities/Channel.ts
+++ b/src/util/entities/Channel.ts
@@ -1,8 +1,9 @@
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
+import { OrmUtils } from "../util/imports/OrmUtils";
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
import { PublicUserProjection, User } from "./User";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "../util/imports/HTTPError";
import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters } from "../util";
import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces";
import { Recipient } from "./Recipient";
@@ -34,7 +35,7 @@ export enum ChannelType {
KANBAN = 34, // confluence like kanban board
VOICELESS_WHITEBOARD = 35, // whiteboard but without voice (whiteboard + voice is the same as stage)
CUSTOM_START = 64, // start custom channel types from here
- UNHANDLED = 255 // unhandled unowned pass-through channel type
+ UNHANDLED = 255, // unhandled unowned pass-through channel type
}
@Entity("channels")
@@ -149,7 +150,14 @@ export class Channel extends BaseClass {
orphanedRowAction: "delete",
})
webhooks?: Webhook[];
+
+ @Column({ nullable: true })
+ flags?: number = 0;
+ @Column({ nullable: true })
+ default_thread_rate_limit_per_user?: number = 0;
+
+
// TODO: DM channel
static async createChannel(
channel: Partial<Channel>,
@@ -169,23 +177,21 @@ export class Channel extends BaseClass {
}
if (!opts?.skipNameChecks) {
- const guild = await Guild.findOneOrFail({ id: channel.guild_id });
+ const guild = await Guild.findOneOrFail({ where: { id: channel.guild_id } });
if (!guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") && channel.name) {
- for (var character of InvisibleCharacters)
+ for (let character of InvisibleCharacters)
if (channel.name.includes(character))
throw new HTTPError("Channel name cannot include invalid characters", 403);
if (channel.name.match(/\-\-+/g))
- throw new HTTPError("Channel name cannot include multiple adjacent dashes.", 403)
+ throw new HTTPError("Channel name cannot include multiple adjacent dashes.", 403);
- if (channel.name.charAt(0) === "-" ||
- channel.name.charAt(channel.name.length - 1) === "-")
- throw new HTTPError("Channel name cannot start/end with dash.", 403)
+ if (channel.name.charAt(0) === "-" || channel.name.charAt(channel.name.length - 1) === "-")
+ throw new HTTPError("Channel name cannot start/end with dash.", 403);
}
if (!guild.features.includes("ALLOW_UNNAMED_CHANNELS")) {
- if (!channel.name)
- throw new HTTPError("Channel name cannot be empty.", 403);
+ if (!channel.name) throw new HTTPError("Channel name cannot be empty.", 403);
}
}
@@ -194,7 +200,7 @@ export class Channel extends BaseClass {
case ChannelType.GUILD_NEWS:
case ChannelType.GUILD_VOICE:
if (channel.parent_id && !opts?.skipExistsCheck) {
- const exists = await Channel.findOneOrFail({ id: channel.parent_id });
+ const exists = await Channel.findOneOrFail({ where: { id: channel.parent_id } });
if (!exists) throw new HTTPError("Parent id channel doesn't exist", 400);
if (exists.guild_id !== channel.guild_id)
throw new HTTPError("The category channel needs to be in the guild");
@@ -222,13 +228,13 @@ export class Channel extends BaseClass {
};
await Promise.all([
- new Channel(channel).save(),
+ OrmUtils.mergeDeep(new Channel(), channel).save(),
!opts?.skipEventEmit
? emitEvent({
- event: "CHANNEL_CREATE",
- data: channel,
- guild_id: channel.guild_id,
- } as ChannelCreateEvent)
+ event: "CHANNEL_CREATE",
+ data: channel,
+ guild_id: channel.guild_id,
+ } as ChannelCreateEvent)
: Promise.resolve(),
]);
@@ -246,7 +252,7 @@ export class Channel extends BaseClass {
}
**/
- const type = recipients.length > 1 ? ChannelType.DM : ChannelType.GROUP_DM;
+ const type = recipients.length > 1 ? ChannelType.GROUP_DM : ChannelType.DM;
let channel = null;
@@ -263,7 +269,8 @@ export class Channel extends BaseClass {
if (containsAll(re, channelRecipients)) {
if (channel == null) {
channel = ur.channel;
- await ur.assign({ closed: false }).save();
+ ur = OrmUtils.mergeDeep(ur, { closed: false });
+ await ur.save();
}
}
}
@@ -272,17 +279,21 @@ export class Channel extends BaseClass {
if (channel == null) {
name = trimSpecial(name);
- channel = await new Channel({
- name,
- type,
- owner_id: type === ChannelType.DM ? undefined : null, // 1:1 DMs are ownerless in fosscord-server
- created_at: new Date(),
- last_message_id: null,
- recipients: channelRecipients.map(
- (x) =>
- new Recipient({ user_id: x, closed: !(type === ChannelType.GROUP_DM || x === creator_user_id) })
- ),
- }).save();
+ channel = await (
+ OrmUtils.mergeDeep(new Channel(), {
+ name,
+ type,
+ owner_id: type === ChannelType.DM ? undefined : null, // 1:1 DMs are ownerless in fosscord-server
+ created_at: new Date(),
+ last_message_id: null,
+ recipients: channelRecipients.map((x) =>
+ OrmUtils.mergeDeep(new Recipient(), {
+ user_id: x,
+ closed: !(type === ChannelType.GROUP_DM || x === creator_user_id),
+ })
+ ),
+ }) as Channel
+ ).save();
}
const channel_dto = await DmChannelDTO.from(channel);
@@ -299,7 +310,7 @@ export class Channel extends BaseClass {
await emitEvent({ event: "CHANNEL_CREATE", data: channel_dto, user_id: creator_user_id });
}
- if (recipients.length === 1) return channel_dto;
+ if (recipients.length === 1) return channel_dto;
else return channel_dto.excludedRecipients([creator_user_id]);
}
diff --git a/util/src/entities/ClientRelease.ts b/src/util/entities/ClientRelease.ts
index c5afd307..c5afd307 100644
--- a/util/src/entities/ClientRelease.ts
+++ b/src/util/entities/ClientRelease.ts
diff --git a/src/util/entities/Config.ts b/src/util/entities/Config.ts
new file mode 100644
index 00000000..606fe901
--- /dev/null
+++ b/src/util/entities/Config.ts
@@ -0,0 +1,11 @@
+import { Column, Entity } from "typeorm";
+import { BaseClassWithoutId, PrimaryIdColumn } from "./BaseClass";
+
+@Entity("config")
+export class ConfigEntity extends BaseClassWithoutId {
+ @PrimaryIdColumn()
+ key: string;
+
+ @Column({ type: "simple-json", nullable: true })
+ value: number | boolean | null | string | undefined;
+}
\ No newline at end of file
diff --git a/util/src/entities/ConnectedAccount.ts b/src/util/entities/ConnectedAccount.ts
index 09ae30ab..09ae30ab 100644
--- a/util/src/entities/ConnectedAccount.ts
+++ b/src/util/entities/ConnectedAccount.ts
diff --git a/util/src/entities/Emoji.ts b/src/util/entities/Emoji.ts
index a3615b7d..a3615b7d 100644
--- a/util/src/entities/Emoji.ts
+++ b/src/util/entities/Emoji.ts
diff --git a/util/src/entities/Encryption.ts b/src/util/entities/Encryption.ts
index 3b82ff84..6b578d15 100644
--- a/util/src/entities/Encryption.ts
+++ b/src/util/entities/Encryption.ts
@@ -2,7 +2,7 @@ import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "ty
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
import { PublicUserProjection, User } from "./User";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "..";
import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters } from "../util";
import { BitField, BitFieldResolvable, BitFlag } from "../util/BitField";
import { Recipient } from "./Recipient";
diff --git a/util/src/entities/Group.ts b/src/util/entities/Group.ts
index b24d38cf..b24d38cf 100644
--- a/util/src/entities/Group.ts
+++ b/src/util/entities/Group.ts
diff --git a/util/src/entities/Guild.ts b/src/util/entities/Guild.ts
index 70bb41c5..d146e577 100644
--- a/util/src/entities/Guild.ts
+++ b/src/util/entities/Guild.ts
@@ -1,4 +1,5 @@
import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToMany, OneToOne, RelationId } from "typeorm";
+import { OrmUtils } from "../util/imports/OrmUtils";
import { Config, handleFile, Snowflake } from "..";
import { Ban } from "./Ban";
import { BaseClass } from "./BaseClass";
@@ -52,7 +53,7 @@ export class Guild extends BaseClass {
afk_channel?: Channel;
@Column({ nullable: true })
- afk_timeout?: number;
+ afk_timeout?: number = Config.get().defaults.guild.afkTimeout;
// * commented out -> use owner instead
// application id of the guild creator if it is bot-created
@@ -70,7 +71,7 @@ export class Guild extends BaseClass {
banner?: string;
@Column({ nullable: true })
- default_message_notifications?: number;
+ default_message_notifications?: number = Config.get().defaults.guild.defaultMessageNotifications;
@Column({ nullable: true })
description?: string;
@@ -79,7 +80,7 @@ export class Guild extends BaseClass {
discovery_splash?: string;
@Column({ nullable: true })
- explicit_content_filter?: number;
+ explicit_content_filter?: number = Config.get().defaults.guild.explicitContentFilter;
@Column({ type: "simple-array" })
features: string[]; //TODO use enum
@@ -95,19 +96,19 @@ export class Guild extends BaseClass {
large?: boolean;
@Column({ nullable: true })
- max_members?: number; // e.g. default 100.000
+ max_members?: number = Config.get().limits.guild.maxMembers; // e.g. default 100.000
@Column({ nullable: true })
- max_presences?: number;
+ max_presences?: number = Config.get().defaults.guild.maxPresences;
@Column({ nullable: true })
- max_video_channel_users?: number; // ? default: 25, is this max 25 streaming or watching
+ max_video_channel_users?: number = Config.get().defaults.guild.maxVideoChannelUsers; // ? default: 25, is this max 25 streaming or watching
@Column({ nullable: true })
- member_count?: number;
+ member_count?: number = 0;
@Column({ nullable: true })
- presence_count?: number; // users online
+ presence_count?: number = 0; // users online
@OneToMany(() => Member, (member: Member) => member.guild, {
cascade: true,
@@ -269,7 +270,7 @@ export class Guild extends BaseClass {
@Column({ nullable: true })
nsfw?: boolean;
-
+
// TODO: nested guilds
@Column({ nullable: true })
parent?: string;
@@ -277,6 +278,10 @@ export class Guild extends BaseClass {
// only for developer portal
permissions?: number;
+ //new guild settings, 11/08/2022:
+ @Column({ nullable: true })
+ premium_progress_bar_enabled: boolean = false;
+
static async createGuild(body: {
name?: string;
icon?: string | null;
@@ -285,7 +290,7 @@ export class Guild extends BaseClass {
}) {
const guild_id = Snowflake.generate();
- const guild = await new Guild({
+ const guild: Guild = OrmUtils.mergeDeep(new Guild(), {
name: body.name || "Fosscord",
icon: await handleFile(`/icons/${guild_id}`, body.icon as string),
region: Config.get().regions.default,
@@ -316,11 +321,12 @@ export class Guild extends BaseClass {
welcome_channels: [],
},
widget_enabled: true, // NB: don't set it as false to prevent artificial restrictions
- }).save();
+ });
+ await guild.save();
// we have to create the role _after_ the guild because else we would get a "SQLITE_CONSTRAINT: FOREIGN KEY constraint failed" error
// TODO: make the @everyone a pseudorole that is dynamically generated at runtime so we can save storage
- await new Role({
+ let role: Role = OrmUtils.mergeDeep(new Role(), {
id: guild_id,
guild_id: guild_id,
color: 0,
@@ -332,8 +338,9 @@ export class Guild extends BaseClass {
permissions: String("2251804225"),
position: 0,
icon: null,
- unicode_emoji: null
- }).save();
+ unicode_emoji: null,
+ });
+ await role.save();
if (!body.channels || !body.channels.length) body.channels = [{ id: "01", type: 0, name: "general" }];
@@ -346,9 +353,9 @@ export class Guild extends BaseClass {
});
for (const channel of body.channels?.sort((a, b) => (a.parent_id ? 1 : -1))) {
- var id = ids.get(channel.id) || Snowflake.generate();
+ let id = ids.get(channel.id) || Snowflake.generate();
- var parent_id = ids.get(channel.parent_id);
+ let parent_id = ids.get(channel.parent_id);
await Channel.createChannel({ ...channel, guild_id, id, parent_id }, body.owner_id, {
keepId: true,
diff --git a/util/src/entities/Invite.ts b/src/util/entities/Invite.ts
index 6ac64ddc..1e0ebe52 100644
--- a/util/src/entities/Invite.ts
+++ b/src/util/entities/Invite.ts
@@ -4,19 +4,20 @@ import { BaseClassWithoutId } from "./BaseClass";
import { Channel } from "./Channel";
import { Guild } from "./Guild";
import { User } from "./User";
+import { random } from "@fosscord/api";
export const PublicInviteRelation = ["inviter", "guild", "channel"];
@Entity("invites")
export class Invite extends BaseClassWithoutId {
@PrimaryColumn()
- code: string;
+ code: string = random();
@Column()
- temporary: boolean;
+ temporary: boolean = true;
@Column()
- uses: number;
+ uses: number = 0;
@Column()
max_uses: number;
@@ -25,7 +26,7 @@ export class Invite extends BaseClassWithoutId {
max_age: number;
@Column()
- created_at: Date;
+ created_at: Date = new Date();
@Column()
expires_at: Date;
@@ -55,7 +56,9 @@ export class Invite extends BaseClassWithoutId {
inviter_id: string;
@JoinColumn({ name: "inviter_id" })
- @ManyToOne(() => User)
+ @ManyToOne(() => User, {
+ onDelete: "CASCADE"
+ })
inviter: User;
@Column({ nullable: true })
@@ -75,7 +78,7 @@ export class Invite extends BaseClassWithoutId {
vanity_url?: boolean;
static async joinGuild(user_id: string, code: string) {
- const invite = await Invite.findOneOrFail({ code });
+ const invite = await Invite.findOneOrFail({ where: { code } });
if (invite.uses++ >= invite.max_uses && invite.max_uses !== 0) await Invite.delete({ code });
else await invite.save();
diff --git a/util/src/entities/Member.ts b/src/util/entities/Member.ts
index fe2d5590..baac58ed 100644
--- a/util/src/entities/Member.ts
+++ b/src/util/entities/Member.ts
@@ -20,11 +20,12 @@ import {
GuildMemberRemoveEvent,
GuildMemberUpdateEvent,
} from "../interfaces";
-import { HTTPError } from "lambert-server";
+import { HTTPError } from "../util/imports/HTTPError";
import { Role } from "./Role";
import { BaseClassWithoutId } from "./BaseClass";
import { Ban, PublicGuildRelations } from ".";
import { DiscordApiErrors } from "../util/Constants";
+import { OrmUtils } from "../util/imports/OrmUtils";
export const MemberPrivateProjection: (keyof Member)[] = [
"id",
@@ -70,7 +71,7 @@ export class Member extends BaseClassWithoutId {
@Column({ nullable: true })
nick?: string;
-
+
@JoinTable({
name: "member_roles",
joinColumn: { name: "index", referencedColumnName: "index" },
@@ -85,8 +86,8 @@ export class Member extends BaseClassWithoutId {
@Column()
joined_at: Date;
- @Column({ type: "bigint", nullable: true })
- premium_since?: number;
+ @Column({ nullable: true })
+ premium_since?: Date;
@Column()
deaf: boolean;
@@ -102,14 +103,14 @@ export class Member extends BaseClassWithoutId {
@Column({ nullable: true })
last_message_id?: string;
-
+
/**
@JoinColumn({ name: "id" })
@ManyToOne(() => User, {
onDelete: "DO NOTHING",
// do not auto-kick force-joined members just because their joiners left the server
}) **/
- @Column({ nullable: true})
+ @Column({ nullable: true })
joined_by?: string;
// TODO: add this when we have proper read receipts
@@ -117,22 +118,24 @@ export class Member extends BaseClassWithoutId {
// read_state: ReadState;
static async IsInGuildOrFail(user_id: string, guild_id: string) {
- if (await Member.count({ id: user_id, guild: { id: guild_id } })) return true;
+ if (await Member.count({ where: { id: user_id, guild: { id: guild_id } } })) return true;
throw new HTTPError("You are not member of this guild", 403);
}
static async removeFromGuild(user_id: string, guild_id: string) {
- const guild = await Guild.findOneOrFail({ select: ["owner_id"], where: { id: guild_id } });
+ const guild = await Guild.findOneOrFail({ select: ["owner_id", "member_count"], where: { id: guild_id } });
if (guild.owner_id === user_id) throw new Error("The owner cannot be removed of the guild");
const member = await Member.findOneOrFail({ where: { id: user_id, guild_id }, relations: ["user"] });
// use promise all to execute all promises at the same time -> save time
+ //TODO: check for bugs
+ if (guild.member_count) guild.member_count--;
return Promise.all([
Member.delete({
id: user_id,
guild_id,
}),
- Guild.decrement({ id: guild_id }, "member_count", -1),
+ //Guild.decrement({ id: guild_id }, "member_count", -1),
emitEvent({
event: "GUILD_DELETE",
@@ -155,11 +158,11 @@ export class Member extends BaseClassWithoutId {
Member.findOneOrFail({
where: { id: user_id, guild_id },
relations: ["user", "roles"], // we don't want to load the role objects just the ids
- select: ["index", "roles.id"],
+ select: ["index"],
}),
Role.findOneOrFail({ where: { id: role_id, guild_id }, select: ["id"] }),
]);
- member.roles.push(new Role({ id: role_id }));
+ member.roles.push(OrmUtils.mergeDeep(new Role(), { id: role_id }));
await Promise.all([
member.save(),
@@ -181,9 +184,9 @@ export class Member extends BaseClassWithoutId {
Member.findOneOrFail({
where: { id: user_id, guild_id },
relations: ["user", "roles"], // we don't want to load the role objects just the ids
- select: ["roles.id", "index"],
+ select: ["index"],
}),
- await Role.findOneOrFail({ id: role_id, guild_id }),
+ await Role.findOneOrFail({ where: { id: role_id, guild_id } }),
]);
member.roles = member.roles.filter((x) => x.id == role_id);
@@ -233,7 +236,7 @@ export class Member extends BaseClassWithoutId {
throw DiscordApiErrors.USER_BANNED;
}
const { maxGuilds } = Config.get().limits.user;
- const guild_count = await Member.count({ id: user_id });
+ const guild_count = await Member.count({ where: { id: user_id } });
if (guild_count >= maxGuilds) {
throw new HTTPError(`You are at the ${maxGuilds} server limit.`, 403);
}
@@ -245,7 +248,7 @@ export class Member extends BaseClassWithoutId {
relations: PublicGuildRelations,
});
- if (await Member.count({ id: user.id, guild: { id: guild_id } }))
+ if (await Member.count({ where: { id: user.id, guild: { id: guild_id } } }))
throw new HTTPError("You are already a member of this guild", 400);
const member = {
@@ -254,16 +257,17 @@ export class Member extends BaseClassWithoutId {
nick: undefined,
roles: [guild_id], // @everyone role
joined_at: new Date(),
- premium_since: (new Date()).getTime(),
+ premium_since: null,
deaf: false,
mute: false,
pending: false,
};
-
+ //TODO: check for bugs
+ if (guild.member_count) guild.member_count++;
await Promise.all([
- new Member({
+ OrmUtils.mergeDeep(new Member(), {
...member,
- roles: [new Role({ id: guild_id })],
+ roles: [OrmUtils.mergeDeep(new Role(), { id: guild_id })],
// read_state: {},
settings: {
channel_overrides: [],
@@ -276,7 +280,7 @@ export class Member extends BaseClassWithoutId {
},
// Member.save is needed because else the roles relations wouldn't be updated
}).save(),
- Guild.increment({ id: guild_id }, "member_count", 1),
+ //Guild.increment({ id: guild_id }, "member_count", 1),
emitEvent({
event: "GUILD_MEMBER_ADD",
data: {
diff --git a/util/src/entities/Message.ts b/src/util/entities/Message.ts
index e18cf691..ba3d4f2d 100644
--- a/util/src/entities/Message.ts
+++ b/src/util/entities/Message.ts
@@ -8,7 +8,6 @@ import {
Column,
CreateDateColumn,
Entity,
- FindConditions,
Index,
JoinColumn,
JoinTable,
diff --git a/util/src/entities/Migration.ts b/src/util/entities/Migration.ts
index 3f39ae72..3f39ae72 100644
--- a/util/src/entities/Migration.ts
+++ b/src/util/entities/Migration.ts
diff --git a/util/src/entities/Note.ts b/src/util/entities/Note.ts
index 36017c5e..36017c5e 100644
--- a/util/src/entities/Note.ts
+++ b/src/util/entities/Note.ts
diff --git a/util/src/entities/RateLimit.ts b/src/util/entities/RateLimit.ts
index f5916f6b..f5916f6b 100644
--- a/util/src/entities/RateLimit.ts
+++ b/src/util/entities/RateLimit.ts
diff --git a/util/src/entities/ReadState.ts b/src/util/entities/ReadState.ts
index b915573b..b915573b 100644
--- a/util/src/entities/ReadState.ts
+++ b/src/util/entities/ReadState.ts
diff --git a/util/src/entities/Recipient.ts b/src/util/entities/Recipient.ts
index a945f938..a945f938 100644
--- a/util/src/entities/Recipient.ts
+++ b/src/util/entities/Recipient.ts
diff --git a/util/src/entities/Relationship.ts b/src/util/entities/Relationship.ts
index c3592c76..c3592c76 100644
--- a/util/src/entities/Relationship.ts
+++ b/src/util/entities/Relationship.ts
diff --git a/util/src/entities/Role.ts b/src/util/entities/Role.ts
index 4b721b5b..4b721b5b 100644
--- a/util/src/entities/Role.ts
+++ b/src/util/entities/Role.ts
diff --git a/util/src/entities/Session.ts b/src/util/entities/Session.ts
index 969efa89..969efa89 100644
--- a/util/src/entities/Session.ts
+++ b/src/util/entities/Session.ts
diff --git a/util/src/entities/Sticker.ts b/src/util/entities/Sticker.ts
index 37bc6fbe..37bc6fbe 100644
--- a/util/src/entities/Sticker.ts
+++ b/src/util/entities/Sticker.ts
diff --git a/util/src/entities/StickerPack.ts b/src/util/entities/StickerPack.ts
index ec8c69a2..ec8c69a2 100644
--- a/util/src/entities/StickerPack.ts
+++ b/src/util/entities/StickerPack.ts
diff --git a/util/src/entities/Team.ts b/src/util/entities/Team.ts
index 22140b7f..22140b7f 100644
--- a/util/src/entities/Team.ts
+++ b/src/util/entities/Team.ts
diff --git a/util/src/entities/TeamMember.ts b/src/util/entities/TeamMember.ts
index b726e1e8..b726e1e8 100644
--- a/util/src/entities/TeamMember.ts
+++ b/src/util/entities/TeamMember.ts
diff --git a/util/src/entities/Template.ts b/src/util/entities/Template.ts
index 1d952283..1d952283 100644
--- a/util/src/entities/Template.ts
+++ b/src/util/entities/Template.ts
diff --git a/util/src/entities/User.ts b/src/util/entities/User.ts
index 470398a5..5432f298 100644
--- a/util/src/entities/User.ts
+++ b/src/util/entities/User.ts
@@ -1,11 +1,11 @@
-import { Column, Entity, FindOneOptions, JoinColumn, OneToMany } from "typeorm";
+import { Column, Entity, FindOneOptions, FindOptionsSelectByString, JoinColumn, OneToMany, OneToOne } from "typeorm";
+import { OrmUtils } from "../util/imports/OrmUtils";
import { BaseClass } from "./BaseClass";
import { BitField } from "../util/BitField";
import { Relationship } from "./Relationship";
import { ConnectedAccount } from "./ConnectedAccount";
import { Config, FieldErrors, Snowflake, trimSpecial } from "..";
-import { Member, Session } from ".";
-import { Note } from "./Note";
+import { Member, Session, UserSettings } from ".";
export enum PublicUserEnum {
username,
@@ -83,30 +83,30 @@ export class User extends BaseClass {
phone?: string; // phone number of the user
@Column({ select: false })
- desktop: boolean; // if the user has desktop app installed
+ desktop: boolean = false; // if the user has desktop app installed
@Column({ select: false })
- mobile: boolean; // if the user has mobile app installed
+ mobile: boolean = false; // if the user has mobile app installed
@Column()
- premium: boolean; // if user bought individual premium
-
- @Column()
- premium_type: number; // individual premium level
+ premium: boolean = Config.get().defaults.user.premium; // if user bought individual premium
@Column()
- bot: boolean; // if user is bot
+ premium_type: number = Config.get().defaults.user.premium_type; // individual premium level
@Column()
+ bot: boolean = false; // if user is bot
+
+ @Column({ nullable: true })
bio: string; // short description of the user (max 190 chars -> should be configurable)
@Column()
- system: boolean; // shouldn't be used, the api sends this field type true, if the generated message comes from a system generated author
+ system: boolean = false; // shouldn't be used, the api sends this field type true, if the generated message comes from a system generated author
@Column({ select: false })
- nsfw_allowed: boolean; // if the user can do age-restricted actions (NSFW channels/guilds/commands)
-
- @Column({ select: false })
+ nsfw_allowed: boolean = true; // if the user can do age-restricted actions (NSFW channels/guilds/commands) // TODO: depending on age
+
+ @Column({ select: false, nullable: true })
mfa_enabled: boolean; // if multi factor authentication is enabled
@Column({ select: false, nullable: true })
@@ -116,31 +116,31 @@ export class User extends BaseClass {
totp_last_ticket?: string;
@Column()
- created_at: Date; // registration date
+ created_at: Date = new Date(); // registration date
@Column({ nullable: true })
- premium_since: Date; // premium date
+ premium_since: Date = new Date(); // premium date
@Column({ select: false })
- verified: boolean; // if the user is offically verified
+ verified: boolean = Config.get().defaults.user.verified; // if the user is offically verified
@Column()
- disabled: boolean; // if the account is disabled
+ disabled: boolean = false; // if the account is disabled
@Column()
- deleted: boolean; // if the user was deleted
+ deleted: boolean = false; // if the user was deleted
@Column({ nullable: true, select: false })
email?: string; // email of the user
@Column()
- flags: string; // UserFlags
+ flags: string = "0"; // UserFlags // TODO: generate
@Column()
- public_flags: number;
+ public_flags: number = 0;
@Column({ type: "bigint" })
- rights: string; // Rights
+ rights: string = Config.get().register.defaultRights; // Rights
@OneToMany(() => Session, (session: Session) => session.user)
sessions: Session[];
@@ -166,14 +166,30 @@ export class User extends BaseClass {
};
@Column({ type: "simple-array", select: false })
- fingerprints: string[]; // array of fingerprints -> used to prevent multiple accounts
+ fingerprints: string[] = []; // array of fingerprints -> used to prevent multiple accounts
- @Column({ type: "simple-json", select: false })
+
+ @OneToOne(()=> UserSettings, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ eager: false
+ })
+ @JoinColumn()
settings: UserSettings;
-
+
// workaround to prevent fossord-unaware clients from deleting settings not used by them
@Column({ type: "simple-json", select: false })
- extended_settings: string;
+ extended_settings: string = "{}";
+
+ @Column({ type: "simple-json" })
+ notes: { [key: string]: string } = {}; //key is ID of user
+
+ async save(): Promise<any> {
+ if(!this.settings) this.settings = new UserSettings();
+ this.settings.id = this.id;
+ //await this.settings.save();
+ return super.save();
+ }
toPublicUser() {
const user: any = {};
@@ -184,19 +200,17 @@ export class User extends BaseClass {
}
static async getPublicUser(user_id: string, opts?: FindOneOptions<User>) {
- return await User.findOneOrFail(
- { id: user_id },
- {
- ...opts,
- select: [...PublicUserProjection, ...(opts?.select || [])],
- }
- );
+ return await User.findOneOrFail({
+ where: { id: user_id },
+ select: [...PublicUserProjection, ...((opts?.select as FindOptionsSelectByString<User>) || [])],
+ ...opts,
+ });
}
- private static async generateDiscriminator(username: string): Promise<string | undefined> {
+ public static async generateDiscriminator(username: string): Promise<string | undefined> {
if (Config.get().register.incrementingDiscriminators) {
// discriminator will be incrementally generated
-
+
// First we need to figure out the currently highest discrimnator for the given username and then increment it
const users = await User.find({ where: { username }, select: ["discriminator"] });
const highestDiscriminator = Math.max(0, ...users.map((u) => Number(u.discriminator)));
@@ -244,7 +258,7 @@ export class User extends BaseClass {
throw FieldErrors({
username: {
code: "USERNAME_TOO_MANY_USERS",
- message: req.t("auth:register.USERNAME_TOO_MANY_USERS"),
+ message: req?.t("auth:register.USERNAME_TOO_MANY_USERS"),
},
});
}
@@ -252,40 +266,22 @@ export class User extends BaseClass {
// TODO: save date_of_birth
// appearently discord doesn't save the date of birth and just calculate if nsfw is allowed
// if nsfw_allowed is null/undefined it'll require date_of_birth to set it to true/false
- const language = req.language === "en" ? "en-US" : req.language || "en-US";
+ const language = req?.language === "en" ? "en-US" : req?.language || "en-US";
- const user = new User({
- created_at: new Date(),
+ const user = OrmUtils.mergeDeep(new User(), {
+ //required:
username: username,
discriminator,
id: Snowflake.generate(),
- bot: false,
- system: false,
- premium_since: new Date(),
- desktop: false,
- mobile: false,
- premium: true,
- premium_type: 2,
- bio: "",
- mfa_enabled: false,
- verified: true,
- disabled: false,
- deleted: false,
email: email,
- rights: "0", // TODO: grant rights correctly, as 0 actually stands for no rights at all
- nsfw_allowed: true, // TODO: depending on age
- public_flags: "0",
- flags: "0", // TODO: generate
data: {
hash: password,
valid_tokens_since: new Date(),
},
- settings: { ...defaultSettings, locale: language },
- extended_settings: {},
- fingerprints: [],
- notes: {},
+ settings: { ...new UserSettings(), locale: language }
});
+ //await (user.settings as UserSettings).save();
await user.save();
setImmediate(async () => {
@@ -300,85 +296,6 @@ export class User extends BaseClass {
}
}
-export const defaultSettings: UserSettings = {
- afk_timeout: 3600,
- allow_accessibility_detection: true,
- animate_emoji: true,
- animate_stickers: 0,
- contact_sync_enabled: false,
- convert_emoticons: false,
- custom_status: null,
- default_guilds_restricted: false,
- detect_platform_accounts: false,
- developer_mode: true,
- disable_games_tab: true,
- enable_tts_command: false,
- explicit_content_filter: 0,
- friend_source_flags: { all: true },
- gateway_connected: false,
- gif_auto_play: true,
- guild_folders: [],
- guild_positions: [],
- inline_attachment_media: true,
- inline_embed_media: true,
- locale: "en-US",
- message_display_compact: true,
- native_phone_integration_enabled: true,
- render_embeds: true,
- render_reactions: true,
- restricted_guilds: [],
- show_current_game: true,
- status: "online",
- stream_notifications_enabled: false,
- theme: "dark",
- timezone_offset: 0, // TODO: timezone from request
-};
-
-export interface UserSettings {
- afk_timeout: number;
- allow_accessibility_detection: boolean;
- animate_emoji: boolean;
- animate_stickers: number;
- contact_sync_enabled: boolean;
- convert_emoticons: boolean;
- custom_status: {
- emoji_id?: string;
- emoji_name?: string;
- expires_at?: number;
- text?: string;
- } | null;
- default_guilds_restricted: boolean;
- detect_platform_accounts: boolean;
- developer_mode: boolean;
- disable_games_tab: boolean;
- enable_tts_command: boolean;
- explicit_content_filter: number;
- friend_source_flags: { all: boolean };
- gateway_connected: boolean;
- gif_auto_play: boolean;
- // every top guild is displayed as a "folder"
- guild_folders: {
- color: number;
- guild_ids: string[];
- id: number;
- name: string;
- }[];
- guild_positions: string[]; // guild ids ordered by position
- inline_attachment_media: boolean;
- inline_embed_media: boolean;
- locale: string; // en_US
- message_display_compact: boolean;
- native_phone_integration_enabled: boolean;
- render_embeds: boolean;
- render_reactions: boolean;
- restricted_guilds: string[];
- show_current_game: boolean;
- status: "online" | "offline" | "dnd" | "idle" | "invisible";
- stream_notifications_enabled: boolean;
- theme: "dark" | "white"; // dark
- timezone_offset: number; // e.g -60
-}
-
export const CUSTOM_USER_FLAG_OFFSET = BigInt(1) << BigInt(32);
export class UserFlags extends BitField {
diff --git a/util/src/entities/UserGroup.ts b/src/util/entities/UserGroup.ts
index 709b9d0b..709b9d0b 100644
--- a/util/src/entities/UserGroup.ts
+++ b/src/util/entities/UserGroup.ts
diff --git a/src/util/entities/UserSettings.ts b/src/util/entities/UserSettings.ts
new file mode 100644
index 00000000..ef6f95af
--- /dev/null
+++ b/src/util/entities/UserSettings.ts
@@ -0,0 +1,119 @@
+import { Column, Entity, JoinColumn } from "typeorm";
+import { BaseClassWithoutId, PrimaryIdColumn } from ".";
+
+@Entity("user_settings")
+export class UserSettings extends BaseClassWithoutId {
+ @PrimaryIdColumn()
+ id: string;
+
+ @Column({ nullable: true })
+ afk_timeout: number = 3600;
+
+ @Column({ nullable: true })
+ allow_accessibility_detection: boolean = true;
+
+ @Column({ nullable: true })
+ animate_emoji: boolean = true;
+
+ @Column({ nullable: true })
+ animate_stickers: number = 0;
+
+ @Column({ nullable: true })
+ contact_sync_enabled: boolean = false;
+
+ @Column({ nullable: true })
+ convert_emoticons: boolean = false;
+
+ @Column({ nullable: true, type: "simple-json" })
+ custom_status: CustomStatus | null = null;
+
+ @Column({ nullable: true })
+ default_guilds_restricted: boolean = false;
+
+ @Column({ nullable: true })
+ detect_platform_accounts: boolean = false;
+
+ @Column({ nullable: true })
+ developer_mode: boolean = true;
+
+ @Column({ nullable: true })
+ disable_games_tab: boolean = true;
+
+ @Column({ nullable: true })
+ enable_tts_command: boolean = false;
+
+ @Column({ nullable: true })
+ explicit_content_filter: number = 0;
+
+ @Column({ nullable: true, type: "simple-json" })
+ friend_source_flags: FriendSourceFlags = { all: true };
+
+ @Column({ nullable: true })
+ gateway_connected: boolean = false;
+
+ @Column({ nullable: true })
+ gif_auto_play: boolean = false;
+
+ @Column({ nullable: true, type: "simple-json" })
+ guild_folders: GuildFolder[] = []; // every top guild is displayed as a "folder"
+
+ @Column({ nullable: true, type: "simple-json" })
+ guild_positions: string[] = []; // guild ids ordered by position
+
+ @Column({ nullable: true })
+ inline_attachment_media: boolean = true;
+
+ @Column({ nullable: true })
+ inline_embed_media: boolean = true;
+
+ @Column({ nullable: true })
+ locale: string = "en-US"; // en_US
+
+ @Column({ nullable: true })
+ message_display_compact: boolean = false;
+
+ @Column({ nullable: true })
+ native_phone_integration_enabled: boolean = true;
+
+ @Column({ nullable: true })
+ render_embeds: boolean = true;
+
+ @Column({ nullable: true })
+ render_reactions: boolean = true;
+
+ @Column({ nullable: true, type: "simple-json" })
+ restricted_guilds: string[] = [];
+
+ @Column({ nullable: true })
+ show_current_game: boolean = true;
+
+ @Column({ nullable: true })
+ status: "online" | "offline" | "dnd" | "idle" | "invisible" = "online";
+
+ @Column({ nullable: true })
+ stream_notifications_enabled: boolean = false;
+
+ @Column({ nullable: true })
+ theme: "dark" | "white" = "dark"; // dark
+
+ @Column({ nullable: true })
+ timezone_offset: number = 0; // e.g -60
+}
+
+interface CustomStatus {
+ emoji_id?: string;
+ emoji_name?: string;
+ expires_at?: number;
+ text?: string;
+}
+
+interface GuildFolder {
+ color: number;
+ guild_ids: string[];
+ id: number;
+ name: string;
+}
+
+interface FriendSourceFlags {
+ all: boolean
+}
\ No newline at end of file
diff --git a/util/src/entities/VoiceState.ts b/src/util/entities/VoiceState.ts
index 75748a01..75748a01 100644
--- a/util/src/entities/VoiceState.ts
+++ b/src/util/entities/VoiceState.ts
diff --git a/util/src/entities/Webhook.ts b/src/util/entities/Webhook.ts
index 89538417..89538417 100644
--- a/util/src/entities/Webhook.ts
+++ b/src/util/entities/Webhook.ts
diff --git a/util/src/entities/index.ts b/src/util/entities/index.ts
index c439a4b7..c6f12022 100644
--- a/util/src/entities/index.ts
+++ b/src/util/entities/index.ts
@@ -30,3 +30,4 @@ export * from "./Webhook";
export * from "./ClientRelease";
export * from "./BackupCodes";
export * from "./Note";
+export * from "./UserSettings";
diff --git a/util/src/index.ts b/src/util/index.ts
index ae0f7e54..d944dc49 100644
--- a/util/src/index.ts
+++ b/src/util/index.ts
@@ -1,6 +1,9 @@
import "reflect-metadata";
export * from "./util/index";
+export * from "./config/index";
export * from "./interfaces/index";
export * from "./entities/index";
export * from "./dtos/index";
+export * from "./util/MFA";
+export * from "./schemas";
\ No newline at end of file
diff --git a/util/src/interfaces/Activity.ts b/src/util/interfaces/Activity.ts
index 43984afd..43984afd 100644
--- a/util/src/interfaces/Activity.ts
+++ b/src/util/interfaces/Activity.ts
diff --git a/util/src/interfaces/Event.ts b/src/util/interfaces/Event.ts
index 416082ed..be66c62f 100644
--- a/util/src/interfaces/Event.ts
+++ b/src/util/interfaces/Event.ts
@@ -1,4 +1,4 @@
-import { PublicUser, User, UserSettings } from "../entities/User";
+import { PublicUser, User } from "../entities/User";
import { Channel } from "../entities/Channel";
import { Guild } from "../entities/Guild";
import { Member, PublicMember, UserGuildSettings } from "../entities/Member";
@@ -12,7 +12,7 @@ import { Interaction } from "./Interaction";
import { ConnectedAccount } from "../entities/ConnectedAccount";
import { Relationship, RelationshipType } from "../entities/Relationship";
import { Presence } from "./Presence";
-import { Sticker } from "..";
+import { Sticker, UserSettings } from "..";
import { Activity, Status } from ".";
export interface Event {
@@ -93,7 +93,7 @@ export interface ReadyEventData {
};
application?: {
id: string;
- flags: string;
+ flags: number;
};
merged_members?: PublicMember[][];
// probably all users who the user is in contact with
diff --git a/util/src/interfaces/Interaction.ts b/src/util/interfaces/Interaction.ts
index 5d3aae24..5d3aae24 100644
--- a/util/src/interfaces/Interaction.ts
+++ b/src/util/interfaces/Interaction.ts
diff --git a/util/src/interfaces/Presence.ts b/src/util/interfaces/Presence.ts
index 7663891a..7663891a 100644
--- a/util/src/interfaces/Presence.ts
+++ b/src/util/interfaces/Presence.ts
diff --git a/util/src/interfaces/Status.ts b/src/util/interfaces/Status.ts
index 5d2e1bba..5d2e1bba 100644
--- a/util/src/interfaces/Status.ts
+++ b/src/util/interfaces/Status.ts
diff --git a/util/src/interfaces/index.ts b/src/util/interfaces/index.ts
index ab7fa429..ab7fa429 100644
--- a/util/src/interfaces/index.ts
+++ b/src/util/interfaces/index.ts
diff --git a/src/util/migrations/mariadb/1659901151025-initial.ts b/src/util/migrations/mariadb/1659901151025-initial.ts
new file mode 100644
index 00000000..d15e0add
--- /dev/null
+++ b/src/util/migrations/mariadb/1659901151025-initial.ts
@@ -0,0 +1,1219 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class initial1659901151025 implements MigrationInterface {
+ name = 'initial1659901151025'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE \`config\` (
+ \`key\` varchar(255) NOT NULL,
+ \`value\` text NULL,
+ PRIMARY KEY (\`key\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`relationships\` (
+ \`id\` varchar(255) NOT NULL,
+ \`from_id\` varchar(255) NOT NULL,
+ \`to_id\` varchar(255) NOT NULL,
+ \`nickname\` varchar(255) NULL,
+ \`type\` int NOT NULL,
+ UNIQUE INDEX \`IDX_a0b2ff0a598df0b0d055934a17\` (\`from_id\`, \`to_id\`),
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`connected_accounts\` (
+ \`id\` varchar(255) NOT NULL,
+ \`user_id\` varchar(255) NULL,
+ \`access_token\` varchar(255) NOT NULL,
+ \`friend_sync\` tinyint NOT NULL,
+ \`name\` varchar(255) NOT NULL,
+ \`revoked\` tinyint NOT NULL,
+ \`show_activity\` tinyint NOT NULL,
+ \`type\` varchar(255) NOT NULL,
+ \`verified\` tinyint NOT NULL,
+ \`visibility\` int NOT NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`users\` (
+ \`id\` varchar(255) NOT NULL,
+ \`username\` varchar(255) NOT NULL,
+ \`discriminator\` varchar(255) NOT NULL,
+ \`avatar\` varchar(255) NULL,
+ \`accent_color\` int NULL,
+ \`banner\` varchar(255) NULL,
+ \`phone\` varchar(255) NULL,
+ \`desktop\` tinyint NOT NULL,
+ \`mobile\` tinyint NOT NULL,
+ \`premium\` tinyint NOT NULL,
+ \`premium_type\` int NOT NULL,
+ \`bot\` tinyint NOT NULL,
+ \`bio\` varchar(255) NOT NULL,
+ \`system\` tinyint NOT NULL,
+ \`nsfw_allowed\` tinyint NOT NULL,
+ \`mfa_enabled\` tinyint NOT NULL,
+ \`totp_secret\` varchar(255) NULL,
+ \`totp_last_ticket\` varchar(255) NULL,
+ \`created_at\` datetime NOT NULL,
+ \`premium_since\` datetime NULL,
+ \`verified\` tinyint NOT NULL,
+ \`disabled\` tinyint NOT NULL,
+ \`deleted\` tinyint NOT NULL,
+ \`email\` varchar(255) NULL,
+ \`flags\` varchar(255) NOT NULL,
+ \`public_flags\` int NOT NULL,
+ \`rights\` bigint NOT NULL,
+ \`data\` text NOT NULL,
+ \`fingerprints\` text NOT NULL,
+ \`settings\` text NOT NULL,
+ \`extended_settings\` text NOT NULL,
+ \`notes\` text NOT NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`backup_codes\` (
+ \`id\` varchar(255) NOT NULL,
+ \`code\` varchar(255) NOT NULL,
+ \`consumed\` tinyint NOT NULL,
+ \`expired\` tinyint NOT NULL,
+ \`user_id\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`bans\` (
+ \`id\` varchar(255) NOT NULL,
+ \`user_id\` varchar(255) NULL,
+ \`guild_id\` varchar(255) NULL,
+ \`executor_id\` varchar(255) NULL,
+ \`ip\` varchar(255) NOT NULL,
+ \`reason\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`recipients\` (
+ \`id\` varchar(255) NOT NULL,
+ \`channel_id\` varchar(255) NOT NULL,
+ \`user_id\` varchar(255) NOT NULL,
+ \`closed\` tinyint NOT NULL DEFAULT 0,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`roles\` (
+ \`id\` varchar(255) NOT NULL,
+ \`guild_id\` varchar(255) NULL,
+ \`color\` int NOT NULL,
+ \`hoist\` tinyint NOT NULL,
+ \`managed\` tinyint NOT NULL,
+ \`mentionable\` tinyint NOT NULL,
+ \`name\` varchar(255) NOT NULL,
+ \`permissions\` varchar(255) NOT NULL,
+ \`position\` int NOT NULL,
+ \`icon\` varchar(255) NULL,
+ \`unicode_emoji\` varchar(255) NULL,
+ \`tags\` text NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`members\` (
+ \`index\` int NOT NULL AUTO_INCREMENT,
+ \`id\` varchar(255) NOT NULL,
+ \`guild_id\` varchar(255) NOT NULL,
+ \`nick\` varchar(255) NULL,
+ \`joined_at\` datetime NOT NULL,
+ \`premium_since\` bigint NULL,
+ \`deaf\` tinyint NOT NULL,
+ \`mute\` tinyint NOT NULL,
+ \`pending\` tinyint NOT NULL,
+ \`settings\` text NOT NULL,
+ \`last_message_id\` varchar(255) NULL,
+ \`joined_by\` varchar(255) NULL,
+ UNIQUE INDEX \`IDX_bb2bf9386ac443afbbbf9f12d3\` (\`id\`, \`guild_id\`),
+ PRIMARY KEY (\`index\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`webhooks\` (
+ \`id\` varchar(255) NOT NULL,
+ \`type\` int NOT NULL,
+ \`name\` varchar(255) NULL,
+ \`avatar\` varchar(255) NULL,
+ \`token\` varchar(255) NULL,
+ \`guild_id\` varchar(255) NULL,
+ \`channel_id\` varchar(255) NULL,
+ \`application_id\` varchar(255) NULL,
+ \`user_id\` varchar(255) NULL,
+ \`source_guild_id\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`stickers\` (
+ \`id\` varchar(255) NOT NULL,
+ \`name\` varchar(255) NOT NULL,
+ \`description\` varchar(255) NULL,
+ \`available\` tinyint NULL,
+ \`tags\` varchar(255) NULL,
+ \`pack_id\` varchar(255) NULL,
+ \`guild_id\` varchar(255) NULL,
+ \`user_id\` varchar(255) NULL,
+ \`type\` int NOT NULL,
+ \`format_type\` int NOT NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`attachments\` (
+ \`id\` varchar(255) NOT NULL,
+ \`filename\` varchar(255) NOT NULL,
+ \`size\` int NOT NULL,
+ \`url\` varchar(255) NOT NULL,
+ \`proxy_url\` varchar(255) NOT NULL,
+ \`height\` int NULL,
+ \`width\` int NULL,
+ \`content_type\` varchar(255) NULL,
+ \`message_id\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`messages\` (
+ \`id\` varchar(255) NOT NULL,
+ \`channel_id\` varchar(255) NULL,
+ \`guild_id\` varchar(255) NULL,
+ \`author_id\` varchar(255) NULL,
+ \`member_id\` varchar(255) NULL,
+ \`webhook_id\` varchar(255) NULL,
+ \`application_id\` varchar(255) NULL,
+ \`content\` varchar(255) NULL,
+ \`timestamp\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ \`edited_timestamp\` datetime NULL,
+ \`tts\` tinyint NULL,
+ \`mention_everyone\` tinyint NULL,
+ \`embeds\` text NOT NULL,
+ \`reactions\` text NOT NULL,
+ \`nonce\` text NULL,
+ \`pinned\` tinyint NULL,
+ \`type\` int NOT NULL,
+ \`activity\` text NULL,
+ \`flags\` varchar(255) NULL,
+ \`message_reference\` text NULL,
+ \`interaction\` text NULL,
+ \`components\` text NULL,
+ \`message_reference_id\` varchar(255) NULL,
+ INDEX \`IDX_86b9109b155eb70c0a2ca3b4b6\` (\`channel_id\`),
+ INDEX \`IDX_05535bc695e9f7ee104616459d\` (\`author_id\`),
+ UNIQUE INDEX \`IDX_3ed7a60fb7dbe04e1ba9332a8b\` (\`channel_id\`, \`id\`),
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`read_states\` (
+ \`id\` varchar(255) NOT NULL,
+ \`channel_id\` varchar(255) NOT NULL,
+ \`user_id\` varchar(255) NOT NULL,
+ \`last_message_id\` varchar(255) NULL,
+ \`public_ack\` varchar(255) NULL,
+ \`notifications_cursor\` varchar(255) NULL,
+ \`last_pin_timestamp\` datetime NULL,
+ \`mention_count\` int NULL,
+ UNIQUE INDEX \`IDX_0abf8b443321bd3cf7f81ee17a\` (\`channel_id\`, \`user_id\`),
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`invites\` (
+ \`code\` varchar(255) NOT NULL,
+ \`temporary\` tinyint NOT NULL,
+ \`uses\` int NOT NULL,
+ \`max_uses\` int NOT NULL,
+ \`max_age\` int NOT NULL,
+ \`created_at\` datetime NOT NULL,
+ \`expires_at\` datetime NOT NULL,
+ \`guild_id\` varchar(255) NULL,
+ \`channel_id\` varchar(255) NULL,
+ \`inviter_id\` varchar(255) NULL,
+ \`target_user_id\` varchar(255) NULL,
+ \`target_user_type\` int NULL,
+ \`vanity_url\` tinyint NULL,
+ PRIMARY KEY (\`code\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`voice_states\` (
+ \`id\` varchar(255) NOT NULL,
+ \`guild_id\` varchar(255) NULL,
+ \`channel_id\` varchar(255) NULL,
+ \`user_id\` varchar(255) NULL,
+ \`session_id\` varchar(255) NOT NULL,
+ \`token\` varchar(255) NULL,
+ \`deaf\` tinyint NOT NULL,
+ \`mute\` tinyint NOT NULL,
+ \`self_deaf\` tinyint NOT NULL,
+ \`self_mute\` tinyint NOT NULL,
+ \`self_stream\` tinyint NULL,
+ \`self_video\` tinyint NOT NULL,
+ \`suppress\` tinyint NOT NULL,
+ \`request_to_speak_timestamp\` datetime NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`channels\` (
+ \`id\` varchar(255) NOT NULL,
+ \`created_at\` datetime NOT NULL,
+ \`name\` varchar(255) NULL,
+ \`icon\` text NULL,
+ \`type\` int NOT NULL,
+ \`last_message_id\` varchar(255) NULL,
+ \`guild_id\` varchar(255) NULL,
+ \`parent_id\` varchar(255) NULL,
+ \`owner_id\` varchar(255) NULL,
+ \`last_pin_timestamp\` int NULL,
+ \`default_auto_archive_duration\` int NULL,
+ \`position\` int NULL,
+ \`permission_overwrites\` text NULL,
+ \`video_quality_mode\` int NULL,
+ \`bitrate\` int NULL,
+ \`user_limit\` int NULL,
+ \`nsfw\` tinyint NULL,
+ \`rate_limit_per_user\` int NULL,
+ \`topic\` varchar(255) NULL,
+ \`retention_policy_id\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`emojis\` (
+ \`id\` varchar(255) NOT NULL,
+ \`animated\` tinyint NOT NULL,
+ \`available\` tinyint NOT NULL,
+ \`guild_id\` varchar(255) NOT NULL,
+ \`user_id\` varchar(255) NULL,
+ \`managed\` tinyint NOT NULL,
+ \`name\` varchar(255) NOT NULL,
+ \`require_colons\` tinyint NOT NULL,
+ \`roles\` text NOT NULL,
+ \`groups\` text NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`templates\` (
+ \`id\` varchar(255) NOT NULL,
+ \`code\` varchar(255) NOT NULL,
+ \`name\` varchar(255) NOT NULL,
+ \`description\` varchar(255) NULL,
+ \`usage_count\` int NULL,
+ \`creator_id\` varchar(255) NULL,
+ \`created_at\` datetime NOT NULL,
+ \`updated_at\` datetime NOT NULL,
+ \`source_guild_id\` varchar(255) NULL,
+ \`serialized_source_guild\` text NOT NULL,
+ UNIQUE INDEX \`IDX_be38737bf339baf63b1daeffb5\` (\`code\`),
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`guilds\` (
+ \`id\` varchar(255) NOT NULL,
+ \`afk_channel_id\` varchar(255) NULL,
+ \`afk_timeout\` int NULL,
+ \`banner\` varchar(255) NULL,
+ \`default_message_notifications\` int NULL,
+ \`description\` varchar(255) NULL,
+ \`discovery_splash\` varchar(255) NULL,
+ \`explicit_content_filter\` int NULL,
+ \`features\` text NOT NULL,
+ \`primary_category_id\` int NULL,
+ \`icon\` varchar(255) NULL,
+ \`large\` tinyint NULL,
+ \`max_members\` int NULL,
+ \`max_presences\` int NULL,
+ \`max_video_channel_users\` int NULL,
+ \`member_count\` int NULL,
+ \`presence_count\` int NULL,
+ \`template_id\` varchar(255) NULL,
+ \`mfa_level\` int NULL,
+ \`name\` varchar(255) NOT NULL,
+ \`owner_id\` varchar(255) NULL,
+ \`preferred_locale\` varchar(255) NULL,
+ \`premium_subscription_count\` int NULL,
+ \`premium_tier\` int NULL,
+ \`public_updates_channel_id\` varchar(255) NULL,
+ \`rules_channel_id\` varchar(255) NULL,
+ \`region\` varchar(255) NULL,
+ \`splash\` varchar(255) NULL,
+ \`system_channel_id\` varchar(255) NULL,
+ \`system_channel_flags\` int NULL,
+ \`unavailable\` tinyint NULL,
+ \`verification_level\` int NULL,
+ \`welcome_screen\` text NOT NULL,
+ \`widget_channel_id\` varchar(255) NULL,
+ \`widget_enabled\` tinyint NULL,
+ \`nsfw_level\` int NULL,
+ \`nsfw\` tinyint NULL,
+ \`parent\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`team_members\` (
+ \`id\` varchar(255) NOT NULL,
+ \`membership_state\` int NOT NULL,
+ \`permissions\` text NOT NULL,
+ \`team_id\` varchar(255) NULL,
+ \`user_id\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`teams\` (
+ \`id\` varchar(255) NOT NULL,
+ \`icon\` varchar(255) NULL,
+ \`name\` varchar(255) NOT NULL,
+ \`owner_user_id\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`applications\` (
+ \`id\` varchar(255) NOT NULL,
+ \`name\` varchar(255) NOT NULL,
+ \`icon\` varchar(255) NULL,
+ \`description\` varchar(255) NOT NULL,
+ \`rpc_origins\` text NULL,
+ \`bot_public\` tinyint NOT NULL,
+ \`bot_require_code_grant\` tinyint NOT NULL,
+ \`terms_of_service_url\` varchar(255) NULL,
+ \`privacy_policy_url\` varchar(255) NULL,
+ \`summary\` varchar(255) NULL,
+ \`verify_key\` varchar(255) NOT NULL,
+ \`primary_sku_id\` varchar(255) NULL,
+ \`slug\` varchar(255) NULL,
+ \`cover_image\` varchar(255) NULL,
+ \`flags\` varchar(255) NOT NULL,
+ \`owner_id\` varchar(255) NULL,
+ \`team_id\` varchar(255) NULL,
+ \`guild_id\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`audit_logs\` (
+ \`id\` varchar(255) NOT NULL,
+ \`user_id\` varchar(255) NULL,
+ \`action_type\` int NOT NULL,
+ \`options\` text NULL,
+ \`changes\` text NOT NULL,
+ \`reason\` varchar(255) NULL,
+ \`target_id\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`categories\` (
+ \`id\` int NOT NULL,
+ \`name\` varchar(255) NULL,
+ \`localizations\` text NOT NULL,
+ \`is_primary\` tinyint NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`rate_limits\` (
+ \`id\` varchar(255) NOT NULL,
+ \`executor_id\` varchar(255) NOT NULL,
+ \`hits\` int NOT NULL,
+ \`blocked\` tinyint NOT NULL,
+ \`expires_at\` datetime NOT NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`sessions\` (
+ \`id\` varchar(255) NOT NULL,
+ \`user_id\` varchar(255) NULL,
+ \`session_id\` varchar(255) NOT NULL,
+ \`activities\` text NULL,
+ \`client_info\` text NOT NULL,
+ \`status\` varchar(255) NOT NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`sticker_packs\` (
+ \`id\` varchar(255) NOT NULL,
+ \`name\` varchar(255) NOT NULL,
+ \`description\` varchar(255) NULL,
+ \`banner_asset_id\` varchar(255) NULL,
+ \`cover_sticker_id\` varchar(255) NULL,
+ \`coverStickerId\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`client_release\` (
+ \`id\` varchar(255) NOT NULL,
+ \`name\` varchar(255) NOT NULL,
+ \`pub_date\` varchar(255) NOT NULL,
+ \`url\` varchar(255) NOT NULL,
+ \`deb_url\` varchar(255) NOT NULL,
+ \`osx_url\` varchar(255) NOT NULL,
+ \`win_url\` varchar(255) NOT NULL,
+ \`notes\` varchar(255) NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`notes\` (
+ \`id\` varchar(255) NOT NULL,
+ \`content\` varchar(255) NOT NULL,
+ \`owner_id\` varchar(255) NULL,
+ \`target_id\` varchar(255) NULL,
+ UNIQUE INDEX \`IDX_74e6689b9568cc965b8bfc9150\` (\`owner_id\`, \`target_id\`),
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`member_roles\` (
+ \`index\` int NOT NULL,
+ \`role_id\` varchar(255) NOT NULL,
+ INDEX \`IDX_5d7ddc8a5f9c167f548625e772\` (\`index\`),
+ INDEX \`IDX_e9080e7a7997a0170026d5139c\` (\`role_id\`),
+ PRIMARY KEY (\`index\`, \`role_id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`message_user_mentions\` (
+ \`messagesId\` varchar(255) NOT NULL,
+ \`usersId\` varchar(255) NOT NULL,
+ INDEX \`IDX_a343387fc560ef378760681c23\` (\`messagesId\`),
+ INDEX \`IDX_b831eb18ceebd28976239b1e2f\` (\`usersId\`),
+ PRIMARY KEY (\`messagesId\`, \`usersId\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`message_role_mentions\` (
+ \`messagesId\` varchar(255) NOT NULL,
+ \`rolesId\` varchar(255) NOT NULL,
+ INDEX \`IDX_a8242cf535337a490b0feaea0b\` (\`messagesId\`),
+ INDEX \`IDX_29d63eb1a458200851bc37d074\` (\`rolesId\`),
+ PRIMARY KEY (\`messagesId\`, \`rolesId\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`message_channel_mentions\` (
+ \`messagesId\` varchar(255) NOT NULL,
+ \`channelsId\` varchar(255) NOT NULL,
+ INDEX \`IDX_2a27102ecd1d81b4582a436092\` (\`messagesId\`),
+ INDEX \`IDX_bdb8c09e1464cabf62105bf4b9\` (\`channelsId\`),
+ PRIMARY KEY (\`messagesId\`, \`channelsId\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`message_stickers\` (
+ \`messagesId\` varchar(255) NOT NULL,
+ \`stickersId\` varchar(255) NOT NULL,
+ INDEX \`IDX_40bb6f23e7cc133292e92829d2\` (\`messagesId\`),
+ INDEX \`IDX_e22a70819d07659c7a71c112a1\` (\`stickersId\`),
+ PRIMARY KEY (\`messagesId\`, \`stickersId\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`relationships\`
+ ADD CONSTRAINT \`FK_9af4194bab1250b1c584ae4f1d7\` FOREIGN KEY (\`from_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`relationships\`
+ ADD CONSTRAINT \`FK_9c7f6b98a9843b76dce1b0c878b\` FOREIGN KEY (\`to_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`connected_accounts\`
+ ADD CONSTRAINT \`FK_f47244225a6a1eac04a3463dd90\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`backup_codes\`
+ ADD CONSTRAINT \`FK_70066ea80d2f4b871beda32633b\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`bans\`
+ ADD CONSTRAINT \`FK_5999e8e449f80a236ff72023559\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`bans\`
+ ADD CONSTRAINT \`FK_9d3ab7dd180ebdd245cdb66ecad\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`bans\`
+ ADD CONSTRAINT \`FK_07ad88c86d1f290d46748410d58\` FOREIGN KEY (\`executor_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`recipients\`
+ ADD CONSTRAINT \`FK_2f18ee1ba667f233ae86c0ea60e\` FOREIGN KEY (\`channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`recipients\`
+ ADD CONSTRAINT \`FK_6157e8b6ba4e6e3089616481fe2\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`roles\`
+ ADD CONSTRAINT \`FK_c32c1ab1c4dc7dcb0278c4b1b8b\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`members\`
+ ADD CONSTRAINT \`FK_28b53062261b996d9c99fa12404\` FOREIGN KEY (\`id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`members\`
+ ADD CONSTRAINT \`FK_16aceddd5b89825b8ed6029ad1c\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`webhooks\`
+ ADD CONSTRAINT \`FK_487a7af59d189f744fe394368fc\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`webhooks\`
+ ADD CONSTRAINT \`FK_df528cf77e82f8032230e7e37d8\` FOREIGN KEY (\`channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`webhooks\`
+ ADD CONSTRAINT \`FK_c3e5305461931763b56aa905f1c\` FOREIGN KEY (\`application_id\`) REFERENCES \`applications\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`webhooks\`
+ ADD CONSTRAINT \`FK_0d523f6f997c86e052c49b1455f\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`webhooks\`
+ ADD CONSTRAINT \`FK_3a285f4f49c40e0706d3018bc9f\` FOREIGN KEY (\`source_guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`stickers\`
+ ADD CONSTRAINT \`FK_e7cfa5cefa6661b3fb8fda8ce69\` FOREIGN KEY (\`pack_id\`) REFERENCES \`sticker_packs\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`stickers\`
+ ADD CONSTRAINT \`FK_193d551d852aca5347ef5c9f205\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`stickers\`
+ ADD CONSTRAINT \`FK_8f4ee73f2bb2325ff980502e158\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`attachments\`
+ ADD CONSTRAINT \`FK_623e10eec51ada466c5038979e3\` FOREIGN KEY (\`message_id\`) REFERENCES \`messages\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\`
+ ADD CONSTRAINT \`FK_86b9109b155eb70c0a2ca3b4b6d\` FOREIGN KEY (\`channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\`
+ ADD CONSTRAINT \`FK_b193588441b085352a4c0109423\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\`
+ ADD CONSTRAINT \`FK_05535bc695e9f7ee104616459d3\` FOREIGN KEY (\`author_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\`
+ ADD CONSTRAINT \`FK_b0525304f2262b7014245351c76\` FOREIGN KEY (\`member_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\`
+ ADD CONSTRAINT \`FK_f83c04bcf1df4e5c0e7a52ed348\` FOREIGN KEY (\`webhook_id\`) REFERENCES \`webhooks\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\`
+ ADD CONSTRAINT \`FK_5d3ec1cb962de6488637fd779d6\` FOREIGN KEY (\`application_id\`) REFERENCES \`applications\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\`
+ ADD CONSTRAINT \`FK_61a92bb65b302a76d9c1fcd3174\` FOREIGN KEY (\`message_reference_id\`) REFERENCES \`messages\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`read_states\`
+ ADD CONSTRAINT \`FK_40da2fca4e0eaf7a23b5bfc5d34\` FOREIGN KEY (\`channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`read_states\`
+ ADD CONSTRAINT \`FK_195f92e4dd1254a4e348c043763\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\`
+ ADD CONSTRAINT \`FK_3f4939aa1461e8af57fea3fb05d\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\`
+ ADD CONSTRAINT \`FK_6a15b051fe5050aa00a4b9ff0f6\` FOREIGN KEY (\`channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\`
+ ADD CONSTRAINT \`FK_15c35422032e0b22b4ada95f48f\` FOREIGN KEY (\`inviter_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\`
+ ADD CONSTRAINT \`FK_11a0d394f8fc649c19ce5f16b59\` FOREIGN KEY (\`target_user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`voice_states\`
+ ADD CONSTRAINT \`FK_03779ef216d4b0358470d9cb748\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`voice_states\`
+ ADD CONSTRAINT \`FK_9f8d389866b40b6657edd026dd4\` FOREIGN KEY (\`channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`voice_states\`
+ ADD CONSTRAINT \`FK_5fe1d5f931a67e85039c640001b\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\`
+ ADD CONSTRAINT \`FK_c253dafe5f3a03ec00cd8fb4581\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\`
+ ADD CONSTRAINT \`FK_3274522d14af40540b1a883fc80\` FOREIGN KEY (\`parent_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\`
+ ADD CONSTRAINT \`FK_3873ed438575cce703ecff4fc7b\` FOREIGN KEY (\`owner_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`emojis\`
+ ADD CONSTRAINT \`FK_4b988e0db89d94cebcf07f598cc\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`emojis\`
+ ADD CONSTRAINT \`FK_fa7ddd5f9a214e28ce596548421\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`templates\`
+ ADD CONSTRAINT \`FK_d7374b7f8f5fbfdececa4fb62e1\` FOREIGN KEY (\`creator_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`templates\`
+ ADD CONSTRAINT \`FK_445d00eaaea0e60a017a5ed0c11\` FOREIGN KEY (\`source_guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\`
+ ADD CONSTRAINT \`FK_f591a66b8019d87b0fe6c12dad6\` FOREIGN KEY (\`afk_channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\`
+ ADD CONSTRAINT \`FK_e2a2f873a64a5cf62526de42325\` FOREIGN KEY (\`template_id\`) REFERENCES \`templates\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\`
+ ADD CONSTRAINT \`FK_fc1a451727e3643ca572a3bb394\` FOREIGN KEY (\`owner_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\`
+ ADD CONSTRAINT \`FK_8d450b016dc8bec35f36729e4b0\` FOREIGN KEY (\`public_updates_channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\`
+ ADD CONSTRAINT \`FK_95828668aa333460582e0ca6396\` FOREIGN KEY (\`rules_channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\`
+ ADD CONSTRAINT \`FK_cfc3d3ad260f8121c95b31a1fce\` FOREIGN KEY (\`system_channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\`
+ ADD CONSTRAINT \`FK_9d1d665379eefde7876a17afa99\` FOREIGN KEY (\`widget_channel_id\`) REFERENCES \`channels\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`team_members\`
+ ADD CONSTRAINT \`FK_fdad7d5768277e60c40e01cdcea\` FOREIGN KEY (\`team_id\`) REFERENCES \`teams\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`team_members\`
+ ADD CONSTRAINT \`FK_c2bf4967c8c2a6b845dadfbf3d4\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`teams\`
+ ADD CONSTRAINT \`FK_13f00abf7cb6096c43ecaf8c108\` FOREIGN KEY (\`owner_user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD CONSTRAINT \`FK_e57508958bf92b9d9d25231b5e8\` FOREIGN KEY (\`owner_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD CONSTRAINT \`FK_a36ed02953077f408d0f3ebc424\` FOREIGN KEY (\`team_id\`) REFERENCES \`teams\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD CONSTRAINT \`FK_e5bf78cdbbe9ba91062d74c5aba\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`audit_logs\`
+ ADD CONSTRAINT \`FK_3cd01cd3ae7aab010310d96ac8e\` FOREIGN KEY (\`target_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`audit_logs\`
+ ADD CONSTRAINT \`FK_bd2726fd31b35443f2245b93ba0\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`sessions\`
+ ADD CONSTRAINT \`FK_085d540d9f418cfbdc7bd55bb19\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`sticker_packs\`
+ ADD CONSTRAINT \`FK_448fafba4355ee1c837bbc865f1\` FOREIGN KEY (\`coverStickerId\`) REFERENCES \`stickers\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`notes\`
+ ADD CONSTRAINT \`FK_f9e103f8ae67cb1787063597925\` FOREIGN KEY (\`owner_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`notes\`
+ ADD CONSTRAINT \`FK_23e08e5b4481711d573e1abecdc\` FOREIGN KEY (\`target_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`member_roles\`
+ ADD CONSTRAINT \`FK_5d7ddc8a5f9c167f548625e772e\` FOREIGN KEY (\`index\`) REFERENCES \`members\`(\`index\`) ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`member_roles\`
+ ADD CONSTRAINT \`FK_e9080e7a7997a0170026d5139c1\` FOREIGN KEY (\`role_id\`) REFERENCES \`roles\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_user_mentions\`
+ ADD CONSTRAINT \`FK_a343387fc560ef378760681c236\` FOREIGN KEY (\`messagesId\`) REFERENCES \`messages\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_user_mentions\`
+ ADD CONSTRAINT \`FK_b831eb18ceebd28976239b1e2f8\` FOREIGN KEY (\`usersId\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_role_mentions\`
+ ADD CONSTRAINT \`FK_a8242cf535337a490b0feaea0b4\` FOREIGN KEY (\`messagesId\`) REFERENCES \`messages\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_role_mentions\`
+ ADD CONSTRAINT \`FK_29d63eb1a458200851bc37d074b\` FOREIGN KEY (\`rolesId\`) REFERENCES \`roles\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_channel_mentions\`
+ ADD CONSTRAINT \`FK_2a27102ecd1d81b4582a4360921\` FOREIGN KEY (\`messagesId\`) REFERENCES \`messages\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_channel_mentions\`
+ ADD CONSTRAINT \`FK_bdb8c09e1464cabf62105bf4b9d\` FOREIGN KEY (\`channelsId\`) REFERENCES \`channels\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_stickers\`
+ ADD CONSTRAINT \`FK_40bb6f23e7cc133292e92829d28\` FOREIGN KEY (\`messagesId\`) REFERENCES \`messages\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_stickers\`
+ ADD CONSTRAINT \`FK_e22a70819d07659c7a71c112a1f\` FOREIGN KEY (\`stickersId\`) REFERENCES \`stickers\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`query-result-cache\` (
+ \`id\` int NOT NULL AUTO_INCREMENT,
+ \`identifier\` varchar(255) NULL,
+ \`time\` bigint NOT NULL,
+ \`duration\` int NOT NULL,
+ \`query\` text NOT NULL,
+ \`result\` text NOT NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ DROP TABLE \`query-result-cache\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_stickers\` DROP FOREIGN KEY \`FK_e22a70819d07659c7a71c112a1f\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_stickers\` DROP FOREIGN KEY \`FK_40bb6f23e7cc133292e92829d28\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_channel_mentions\` DROP FOREIGN KEY \`FK_bdb8c09e1464cabf62105bf4b9d\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_channel_mentions\` DROP FOREIGN KEY \`FK_2a27102ecd1d81b4582a4360921\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_role_mentions\` DROP FOREIGN KEY \`FK_29d63eb1a458200851bc37d074b\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_role_mentions\` DROP FOREIGN KEY \`FK_a8242cf535337a490b0feaea0b4\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_user_mentions\` DROP FOREIGN KEY \`FK_b831eb18ceebd28976239b1e2f8\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`message_user_mentions\` DROP FOREIGN KEY \`FK_a343387fc560ef378760681c236\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`member_roles\` DROP FOREIGN KEY \`FK_e9080e7a7997a0170026d5139c1\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`member_roles\` DROP FOREIGN KEY \`FK_5d7ddc8a5f9c167f548625e772e\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`notes\` DROP FOREIGN KEY \`FK_23e08e5b4481711d573e1abecdc\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`notes\` DROP FOREIGN KEY \`FK_f9e103f8ae67cb1787063597925\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`sticker_packs\` DROP FOREIGN KEY \`FK_448fafba4355ee1c837bbc865f1\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`sessions\` DROP FOREIGN KEY \`FK_085d540d9f418cfbdc7bd55bb19\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`audit_logs\` DROP FOREIGN KEY \`FK_bd2726fd31b35443f2245b93ba0\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`audit_logs\` DROP FOREIGN KEY \`FK_3cd01cd3ae7aab010310d96ac8e\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP FOREIGN KEY \`FK_e5bf78cdbbe9ba91062d74c5aba\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP FOREIGN KEY \`FK_a36ed02953077f408d0f3ebc424\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP FOREIGN KEY \`FK_e57508958bf92b9d9d25231b5e8\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`teams\` DROP FOREIGN KEY \`FK_13f00abf7cb6096c43ecaf8c108\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`team_members\` DROP FOREIGN KEY \`FK_c2bf4967c8c2a6b845dadfbf3d4\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`team_members\` DROP FOREIGN KEY \`FK_fdad7d5768277e60c40e01cdcea\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\` DROP FOREIGN KEY \`FK_9d1d665379eefde7876a17afa99\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\` DROP FOREIGN KEY \`FK_cfc3d3ad260f8121c95b31a1fce\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\` DROP FOREIGN KEY \`FK_95828668aa333460582e0ca6396\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\` DROP FOREIGN KEY \`FK_8d450b016dc8bec35f36729e4b0\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\` DROP FOREIGN KEY \`FK_fc1a451727e3643ca572a3bb394\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\` DROP FOREIGN KEY \`FK_e2a2f873a64a5cf62526de42325\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\` DROP FOREIGN KEY \`FK_f591a66b8019d87b0fe6c12dad6\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`templates\` DROP FOREIGN KEY \`FK_445d00eaaea0e60a017a5ed0c11\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`templates\` DROP FOREIGN KEY \`FK_d7374b7f8f5fbfdececa4fb62e1\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`emojis\` DROP FOREIGN KEY \`FK_fa7ddd5f9a214e28ce596548421\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`emojis\` DROP FOREIGN KEY \`FK_4b988e0db89d94cebcf07f598cc\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\` DROP FOREIGN KEY \`FK_3873ed438575cce703ecff4fc7b\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\` DROP FOREIGN KEY \`FK_3274522d14af40540b1a883fc80\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\` DROP FOREIGN KEY \`FK_c253dafe5f3a03ec00cd8fb4581\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`voice_states\` DROP FOREIGN KEY \`FK_5fe1d5f931a67e85039c640001b\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`voice_states\` DROP FOREIGN KEY \`FK_9f8d389866b40b6657edd026dd4\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`voice_states\` DROP FOREIGN KEY \`FK_03779ef216d4b0358470d9cb748\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_11a0d394f8fc649c19ce5f16b59\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_15c35422032e0b22b4ada95f48f\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_6a15b051fe5050aa00a4b9ff0f6\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_3f4939aa1461e8af57fea3fb05d\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`read_states\` DROP FOREIGN KEY \`FK_195f92e4dd1254a4e348c043763\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`read_states\` DROP FOREIGN KEY \`FK_40da2fca4e0eaf7a23b5bfc5d34\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\` DROP FOREIGN KEY \`FK_61a92bb65b302a76d9c1fcd3174\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\` DROP FOREIGN KEY \`FK_5d3ec1cb962de6488637fd779d6\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\` DROP FOREIGN KEY \`FK_f83c04bcf1df4e5c0e7a52ed348\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\` DROP FOREIGN KEY \`FK_b0525304f2262b7014245351c76\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\` DROP FOREIGN KEY \`FK_05535bc695e9f7ee104616459d3\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\` DROP FOREIGN KEY \`FK_b193588441b085352a4c0109423\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`messages\` DROP FOREIGN KEY \`FK_86b9109b155eb70c0a2ca3b4b6d\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`attachments\` DROP FOREIGN KEY \`FK_623e10eec51ada466c5038979e3\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`stickers\` DROP FOREIGN KEY \`FK_8f4ee73f2bb2325ff980502e158\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`stickers\` DROP FOREIGN KEY \`FK_193d551d852aca5347ef5c9f205\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`stickers\` DROP FOREIGN KEY \`FK_e7cfa5cefa6661b3fb8fda8ce69\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`webhooks\` DROP FOREIGN KEY \`FK_3a285f4f49c40e0706d3018bc9f\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`webhooks\` DROP FOREIGN KEY \`FK_0d523f6f997c86e052c49b1455f\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`webhooks\` DROP FOREIGN KEY \`FK_c3e5305461931763b56aa905f1c\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`webhooks\` DROP FOREIGN KEY \`FK_df528cf77e82f8032230e7e37d8\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`webhooks\` DROP FOREIGN KEY \`FK_487a7af59d189f744fe394368fc\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`members\` DROP FOREIGN KEY \`FK_16aceddd5b89825b8ed6029ad1c\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`members\` DROP FOREIGN KEY \`FK_28b53062261b996d9c99fa12404\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`roles\` DROP FOREIGN KEY \`FK_c32c1ab1c4dc7dcb0278c4b1b8b\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`recipients\` DROP FOREIGN KEY \`FK_6157e8b6ba4e6e3089616481fe2\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`recipients\` DROP FOREIGN KEY \`FK_2f18ee1ba667f233ae86c0ea60e\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`bans\` DROP FOREIGN KEY \`FK_07ad88c86d1f290d46748410d58\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`bans\` DROP FOREIGN KEY \`FK_9d3ab7dd180ebdd245cdb66ecad\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`bans\` DROP FOREIGN KEY \`FK_5999e8e449f80a236ff72023559\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`backup_codes\` DROP FOREIGN KEY \`FK_70066ea80d2f4b871beda32633b\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`connected_accounts\` DROP FOREIGN KEY \`FK_f47244225a6a1eac04a3463dd90\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`relationships\` DROP FOREIGN KEY \`FK_9c7f6b98a9843b76dce1b0c878b\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`relationships\` DROP FOREIGN KEY \`FK_9af4194bab1250b1c584ae4f1d7\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_e22a70819d07659c7a71c112a1\` ON \`message_stickers\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_40bb6f23e7cc133292e92829d2\` ON \`message_stickers\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`message_stickers\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_bdb8c09e1464cabf62105bf4b9\` ON \`message_channel_mentions\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_2a27102ecd1d81b4582a436092\` ON \`message_channel_mentions\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`message_channel_mentions\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_29d63eb1a458200851bc37d074\` ON \`message_role_mentions\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_a8242cf535337a490b0feaea0b\` ON \`message_role_mentions\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`message_role_mentions\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_b831eb18ceebd28976239b1e2f\` ON \`message_user_mentions\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_a343387fc560ef378760681c23\` ON \`message_user_mentions\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`message_user_mentions\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_e9080e7a7997a0170026d5139c\` ON \`member_roles\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_5d7ddc8a5f9c167f548625e772\` ON \`member_roles\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`member_roles\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_74e6689b9568cc965b8bfc9150\` ON \`notes\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`notes\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`client_release\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`sticker_packs\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`sessions\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`rate_limits\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`categories\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`audit_logs\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`applications\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`teams\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`team_members\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`guilds\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_be38737bf339baf63b1daeffb5\` ON \`templates\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`templates\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`emojis\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`channels\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`voice_states\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`invites\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_0abf8b443321bd3cf7f81ee17a\` ON \`read_states\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`read_states\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_3ed7a60fb7dbe04e1ba9332a8b\` ON \`messages\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_05535bc695e9f7ee104616459d\` ON \`messages\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_86b9109b155eb70c0a2ca3b4b6\` ON \`messages\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`messages\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`attachments\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`stickers\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`webhooks\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_bb2bf9386ac443afbbbf9f12d3\` ON \`members\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`members\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`roles\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`recipients\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`bans\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`backup_codes\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`users\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`connected_accounts\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`IDX_a0b2ff0a598df0b0d055934a17\` ON \`relationships\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`relationships\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`config\`
+ `);
+ }
+
+}
diff --git a/src/util/migrations/mariadb/1659921859145-premium_since_as_date.ts b/src/util/migrations/mariadb/1659921859145-premium_since_as_date.ts
new file mode 100644
index 00000000..de173cfe
--- /dev/null
+++ b/src/util/migrations/mariadb/1659921859145-premium_since_as_date.ts
@@ -0,0 +1,26 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class premiumSinceAsDate1659921859145 implements MigrationInterface {
+ name = 'premiumSinceAsDate1659921859145'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE \`members\` DROP COLUMN \`premium_since\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`members\`
+ ADD \`premium_since\` datetime NULL
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE \`members\` DROP COLUMN \`premium_since\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`members\`
+ ADD \`premium_since\` bigint NULL
+ `);
+ }
+
+}
diff --git a/src/util/migrations/mariadb/1660130586602-updated-applications.ts b/src/util/migrations/mariadb/1660130586602-updated-applications.ts
new file mode 100644
index 00000000..ec574416
--- /dev/null
+++ b/src/util/migrations/mariadb/1660130586602-updated-applications.ts
@@ -0,0 +1,185 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class updatedApplications1660130586602 implements MigrationInterface {
+ name = 'updatedApplications1660130586602'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP FOREIGN KEY \`FK_e5bf78cdbbe9ba91062d74c5aba\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`rpc_origins\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`primary_sku_id\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`slug\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`guild_id\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`type\` text NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`hook\` tinyint NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`redirect_uris\` text NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`rpc_application_state\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`store_application_state\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`verification_state\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`interactions_endpoint_url\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`integration_public\` tinyint NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`integration_require_code_grant\` tinyint NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`discoverability_state\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`discovery_eligibility_flags\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`tags\` text NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`install_params\` text NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`bot_user_id\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD UNIQUE INDEX \`IDX_2ce5a55796fe4c2f77ece57a64\` (\`bot_user_id\`)
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` CHANGE \`description\` \`description\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`flags\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`flags\` int NOT NULL
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX \`REL_2ce5a55796fe4c2f77ece57a64\` ON \`applications\` (\`bot_user_id\`)
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD CONSTRAINT \`FK_2ce5a55796fe4c2f77ece57a647\` FOREIGN KEY (\`bot_user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP FOREIGN KEY \`FK_2ce5a55796fe4c2f77ece57a647\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`REL_2ce5a55796fe4c2f77ece57a64\` ON \`applications\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`flags\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`flags\` varchar(255) NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` CHANGE \`description\` \`description\` varchar(255) NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP INDEX \`IDX_2ce5a55796fe4c2f77ece57a64\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`bot_user_id\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`install_params\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`tags\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`discovery_eligibility_flags\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`discoverability_state\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`integration_require_code_grant\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`integration_public\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`interactions_endpoint_url\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`verification_state\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`store_application_state\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`rpc_application_state\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`redirect_uris\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`hook\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\` DROP COLUMN \`type\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`guild_id\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`slug\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`primary_sku_id\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD \`rpc_origins\` text NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`applications\`
+ ADD CONSTRAINT \`FK_e5bf78cdbbe9ba91062d74c5aba\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ }
+
+}
diff --git a/src/util/migrations/mariadb/1660131942703-apps_nullable_team.ts b/src/util/migrations/mariadb/1660131942703-apps_nullable_team.ts
new file mode 100644
index 00000000..ac445772
--- /dev/null
+++ b/src/util/migrations/mariadb/1660131942703-apps_nullable_team.ts
@@ -0,0 +1,18 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class appsNullableTeam1660131942703 implements MigrationInterface {
+ name = 'appsNullableTeam1660131942703'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ DROP INDEX \`IDX_2ce5a55796fe4c2f77ece57a64\` ON \`applications\`
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX \`IDX_2ce5a55796fe4c2f77ece57a64\` ON \`applications\` (\`bot_user_id\`)
+ `);
+ }
+
+}
diff --git a/src/util/migrations/mariadb/1660540527213-sync_migrations.ts b/src/util/migrations/mariadb/1660540527213-sync_migrations.ts
new file mode 100644
index 00000000..8cc1d2f1
--- /dev/null
+++ b/src/util/migrations/mariadb/1660540527213-sync_migrations.ts
@@ -0,0 +1,127 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class syncMigrations1660540527213 implements MigrationInterface {
+ name = 'syncMigrations1660540527213'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_15c35422032e0b22b4ada95f48f\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\` CHANGE \`settings\` \`settingsId\` text NOT NULL
+ `);
+ await queryRunner.query(`
+ CREATE TABLE \`user_settings\` (
+ \`id\` varchar(255) NOT NULL,
+ \`afk_timeout\` int NULL,
+ \`allow_accessibility_detection\` tinyint NULL,
+ \`animate_emoji\` tinyint NULL,
+ \`animate_stickers\` int NULL,
+ \`contact_sync_enabled\` tinyint NULL,
+ \`convert_emoticons\` tinyint NULL,
+ \`custom_status\` text NULL,
+ \`default_guilds_restricted\` tinyint NULL,
+ \`detect_platform_accounts\` tinyint NULL,
+ \`developer_mode\` tinyint NULL,
+ \`disable_games_tab\` tinyint NULL,
+ \`enable_tts_command\` tinyint NULL,
+ \`explicit_content_filter\` int NULL,
+ \`friend_source_flags\` text NULL,
+ \`gateway_connected\` tinyint NULL,
+ \`gif_auto_play\` tinyint NULL,
+ \`guild_folders\` text NULL,
+ \`guild_positions\` text NULL,
+ \`inline_attachment_media\` tinyint NULL,
+ \`inline_embed_media\` tinyint NULL,
+ \`locale\` varchar(255) NULL,
+ \`message_display_compact\` tinyint NULL,
+ \`native_phone_integration_enabled\` tinyint NULL,
+ \`render_embeds\` tinyint NULL,
+ \`render_reactions\` tinyint NULL,
+ \`restricted_guilds\` text NULL,
+ \`show_current_game\` tinyint NULL,
+ \`status\` varchar(255) NULL,
+ \`stream_notifications_enabled\` tinyint NULL,
+ \`theme\` varchar(255) NULL,
+ \`timezone_offset\` int NULL,
+ PRIMARY KEY (\`id\`)
+ ) ENGINE = InnoDB
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\`
+ ADD \`flags\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\`
+ ADD \`default_thread_rate_limit_per_user\` int NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\`
+ ADD \`premium_progress_bar_enabled\` tinyint NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\` DROP COLUMN \`settingsId\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\`
+ ADD \`settingsId\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\`
+ ADD UNIQUE INDEX \`IDX_76ba283779c8441fd5ff819c8c\` (\`settingsId\`)
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX \`REL_76ba283779c8441fd5ff819c8c\` ON \`users\` (\`settingsId\`)
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\`
+ ADD CONSTRAINT \`FK_76ba283779c8441fd5ff819c8cf\` FOREIGN KEY (\`settingsId\`) REFERENCES \`user_settings\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\`
+ ADD CONSTRAINT \`FK_15c35422032e0b22b4ada95f48f\` FOREIGN KEY (\`inviter_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_15c35422032e0b22b4ada95f48f\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\` DROP FOREIGN KEY \`FK_76ba283779c8441fd5ff819c8cf\`
+ `);
+ await queryRunner.query(`
+ DROP INDEX \`REL_76ba283779c8441fd5ff819c8c\` ON \`users\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\` DROP INDEX \`IDX_76ba283779c8441fd5ff819c8c\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\` DROP COLUMN \`settingsId\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\`
+ ADD \`settingsId\` text NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`guilds\` DROP COLUMN \`premium_progress_bar_enabled\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\` DROP COLUMN \`default_thread_rate_limit_per_user\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`channels\` DROP COLUMN \`flags\`
+ `);
+ await queryRunner.query(`
+ DROP TABLE \`user_settings\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\` CHANGE \`settingsId\` \`settings\` text NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`invites\`
+ ADD CONSTRAINT \`FK_15c35422032e0b22b4ada95f48f\` FOREIGN KEY (\`inviter_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ }
+
+}
diff --git a/src/util/migrations/mariadb/1660549252130-fix_nullables.ts b/src/util/migrations/mariadb/1660549252130-fix_nullables.ts
new file mode 100644
index 00000000..c9456b54
--- /dev/null
+++ b/src/util/migrations/mariadb/1660549252130-fix_nullables.ts
@@ -0,0 +1,30 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class fixNullables1660549252130 implements MigrationInterface {
+ name = 'fixNullables1660549252130'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ DROP INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\`
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\` CHANGE \`bio\` \`bio\` varchar(255) NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\` CHANGE \`mfa_enabled\` \`mfa_enabled\` tinyint NULL
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE \`users\` CHANGE \`mfa_enabled\` \`mfa_enabled\` tinyint NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE \`users\` CHANGE \`bio\` \`bio\` varchar(255) NOT NULL
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\` (\`settingsId\`)
+ `);
+ }
+
+}
diff --git a/src/util/migrations/postgres/1659899687168-initial.ts b/src/util/migrations/postgres/1659899687168-initial.ts
new file mode 100644
index 00000000..4ffb897d
--- /dev/null
+++ b/src/util/migrations/postgres/1659899687168-initial.ts
@@ -0,0 +1,1245 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class initial1659899687168 implements MigrationInterface {
+ name = 'initial1659899687168'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "config" (
+ "key" character varying NOT NULL,
+ "value" text,
+ CONSTRAINT "PK_26489c99ddbb4c91631ef5cc791" PRIMARY KEY ("key")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "relationships" (
+ "id" character varying NOT NULL,
+ "from_id" character varying NOT NULL,
+ "to_id" character varying NOT NULL,
+ "nickname" character varying,
+ "type" integer NOT NULL,
+ CONSTRAINT "PK_ba20e2f5cf487408e08e4dcecaf" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_a0b2ff0a598df0b0d055934a17" ON "relationships" ("from_id", "to_id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "connected_accounts" (
+ "id" character varying NOT NULL,
+ "user_id" character varying,
+ "access_token" character varying NOT NULL,
+ "friend_sync" boolean NOT NULL,
+ "name" character varying NOT NULL,
+ "revoked" boolean NOT NULL,
+ "show_activity" boolean NOT NULL,
+ "type" character varying NOT NULL,
+ "verified" boolean NOT NULL,
+ "visibility" integer NOT NULL,
+ CONSTRAINT "PK_70416f1da0be645bb31da01c774" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "users" (
+ "id" character varying NOT NULL,
+ "username" character varying NOT NULL,
+ "discriminator" character varying NOT NULL,
+ "avatar" character varying,
+ "accent_color" integer,
+ "banner" character varying,
+ "phone" character varying,
+ "desktop" boolean NOT NULL,
+ "mobile" boolean NOT NULL,
+ "premium" boolean NOT NULL,
+ "premium_type" integer NOT NULL,
+ "bot" boolean NOT NULL,
+ "bio" character varying NOT NULL,
+ "system" boolean NOT NULL,
+ "nsfw_allowed" boolean NOT NULL,
+ "mfa_enabled" boolean NOT NULL,
+ "totp_secret" character varying,
+ "totp_last_ticket" character varying,
+ "created_at" TIMESTAMP NOT NULL,
+ "premium_since" TIMESTAMP,
+ "verified" boolean NOT NULL,
+ "disabled" boolean NOT NULL,
+ "deleted" boolean NOT NULL,
+ "email" character varying,
+ "flags" character varying NOT NULL,
+ "public_flags" integer NOT NULL,
+ "rights" bigint NOT NULL,
+ "data" text NOT NULL,
+ "fingerprints" text NOT NULL,
+ "settings" text NOT NULL,
+ "extended_settings" text NOT NULL,
+ "notes" text NOT NULL,
+ CONSTRAINT "PK_a3ffb1c0c8416b9fc6f907b7433" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "backup_codes" (
+ "id" character varying NOT NULL,
+ "code" character varying NOT NULL,
+ "consumed" boolean NOT NULL,
+ "expired" boolean NOT NULL,
+ "user_id" character varying,
+ CONSTRAINT "PK_34ab957382dbc57e8fb53f1638f" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "bans" (
+ "id" character varying NOT NULL,
+ "user_id" character varying,
+ "guild_id" character varying,
+ "executor_id" character varying,
+ "ip" character varying NOT NULL,
+ "reason" character varying,
+ CONSTRAINT "PK_a4d6f261bffa4615c62d756566a" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "recipients" (
+ "id" character varying NOT NULL,
+ "channel_id" character varying NOT NULL,
+ "user_id" character varying NOT NULL,
+ "closed" boolean NOT NULL DEFAULT false,
+ CONSTRAINT "PK_de8fc5a9c364568f294798fe1e9" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "roles" (
+ "id" character varying NOT NULL,
+ "guild_id" character varying,
+ "color" integer NOT NULL,
+ "hoist" boolean NOT NULL,
+ "managed" boolean NOT NULL,
+ "mentionable" boolean NOT NULL,
+ "name" character varying NOT NULL,
+ "permissions" character varying NOT NULL,
+ "position" integer NOT NULL,
+ "icon" character varying,
+ "unicode_emoji" character varying,
+ "tags" text,
+ CONSTRAINT "PK_c1433d71a4838793a49dcad46ab" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "members" (
+ "index" SERIAL NOT NULL,
+ "id" character varying NOT NULL,
+ "guild_id" character varying NOT NULL,
+ "nick" character varying,
+ "joined_at" TIMESTAMP NOT NULL,
+ "premium_since" bigint,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "pending" boolean NOT NULL,
+ "settings" text NOT NULL,
+ "last_message_id" character varying,
+ "joined_by" character varying,
+ CONSTRAINT "PK_b4a6b8c2478e5df990909c6cf6a" PRIMARY KEY ("index")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_bb2bf9386ac443afbbbf9f12d3" ON "members" ("id", "guild_id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "webhooks" (
+ "id" character varying NOT NULL,
+ "type" integer NOT NULL,
+ "name" character varying,
+ "avatar" character varying,
+ "token" character varying,
+ "guild_id" character varying,
+ "channel_id" character varying,
+ "application_id" character varying,
+ "user_id" character varying,
+ "source_guild_id" character varying,
+ CONSTRAINT "PK_9e8795cfc899ab7bdaa831e8527" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "stickers" (
+ "id" character varying NOT NULL,
+ "name" character varying NOT NULL,
+ "description" character varying,
+ "available" boolean,
+ "tags" character varying,
+ "pack_id" character varying,
+ "guild_id" character varying,
+ "user_id" character varying,
+ "type" integer NOT NULL,
+ "format_type" integer NOT NULL,
+ CONSTRAINT "PK_e1dafa4063a5532645cc2810374" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "attachments" (
+ "id" character varying NOT NULL,
+ "filename" character varying NOT NULL,
+ "size" integer NOT NULL,
+ "url" character varying NOT NULL,
+ "proxy_url" character varying NOT NULL,
+ "height" integer,
+ "width" integer,
+ "content_type" character varying,
+ "message_id" character varying,
+ CONSTRAINT "PK_5e1f050bcff31e3084a1d662412" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "messages" (
+ "id" character varying NOT NULL,
+ "channel_id" character varying,
+ "guild_id" character varying,
+ "author_id" character varying,
+ "member_id" character varying,
+ "webhook_id" character varying,
+ "application_id" character varying,
+ "content" character varying,
+ "timestamp" TIMESTAMP NOT NULL DEFAULT now(),
+ "edited_timestamp" TIMESTAMP,
+ "tts" boolean,
+ "mention_everyone" boolean,
+ "embeds" text NOT NULL,
+ "reactions" text NOT NULL,
+ "nonce" text,
+ "pinned" boolean,
+ "type" integer NOT NULL,
+ "activity" text,
+ "flags" character varying,
+ "message_reference" text,
+ "interaction" text,
+ "components" text,
+ "message_reference_id" character varying,
+ CONSTRAINT "PK_18325f38ae6de43878487eff986" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_86b9109b155eb70c0a2ca3b4b6" ON "messages" ("channel_id")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_05535bc695e9f7ee104616459d" ON "messages" ("author_id")
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_3ed7a60fb7dbe04e1ba9332a8b" ON "messages" ("channel_id", "id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "read_states" (
+ "id" character varying NOT NULL,
+ "channel_id" character varying NOT NULL,
+ "user_id" character varying NOT NULL,
+ "last_message_id" character varying,
+ "public_ack" character varying,
+ "notifications_cursor" character varying,
+ "last_pin_timestamp" TIMESTAMP,
+ "mention_count" integer,
+ CONSTRAINT "PK_e6956a804978f01b713b1ed58e2" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_0abf8b443321bd3cf7f81ee17a" ON "read_states" ("channel_id", "user_id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "invites" (
+ "code" character varying NOT NULL,
+ "temporary" boolean NOT NULL,
+ "uses" integer NOT NULL,
+ "max_uses" integer NOT NULL,
+ "max_age" integer NOT NULL,
+ "created_at" TIMESTAMP NOT NULL,
+ "expires_at" TIMESTAMP NOT NULL,
+ "guild_id" character varying,
+ "channel_id" character varying,
+ "inviter_id" character varying,
+ "target_user_id" character varying,
+ "target_user_type" integer,
+ "vanity_url" boolean,
+ CONSTRAINT "PK_33fd8a248db1cd832baa8aa25bf" PRIMARY KEY ("code")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "voice_states" (
+ "id" character varying NOT NULL,
+ "guild_id" character varying,
+ "channel_id" character varying,
+ "user_id" character varying,
+ "session_id" character varying NOT NULL,
+ "token" character varying,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "self_deaf" boolean NOT NULL,
+ "self_mute" boolean NOT NULL,
+ "self_stream" boolean,
+ "self_video" boolean NOT NULL,
+ "suppress" boolean NOT NULL,
+ "request_to_speak_timestamp" TIMESTAMP,
+ CONSTRAINT "PK_ada09a50c134fad1369b510e3ce" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "channels" (
+ "id" character varying NOT NULL,
+ "created_at" TIMESTAMP NOT NULL,
+ "name" character varying,
+ "icon" text,
+ "type" integer NOT NULL,
+ "last_message_id" character varying,
+ "guild_id" character varying,
+ "parent_id" character varying,
+ "owner_id" character varying,
+ "last_pin_timestamp" integer,
+ "default_auto_archive_duration" integer,
+ "position" integer,
+ "permission_overwrites" text,
+ "video_quality_mode" integer,
+ "bitrate" integer,
+ "user_limit" integer,
+ "nsfw" boolean,
+ "rate_limit_per_user" integer,
+ "topic" character varying,
+ "retention_policy_id" character varying,
+ CONSTRAINT "PK_bc603823f3f741359c2339389f9" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "emojis" (
+ "id" character varying NOT NULL,
+ "animated" boolean NOT NULL,
+ "available" boolean NOT NULL,
+ "guild_id" character varying NOT NULL,
+ "user_id" character varying,
+ "managed" boolean NOT NULL,
+ "name" character varying NOT NULL,
+ "require_colons" boolean NOT NULL,
+ "roles" text NOT NULL,
+ "groups" text,
+ CONSTRAINT "PK_9adb96a675f555c6169bad7ba62" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "templates" (
+ "id" character varying NOT NULL,
+ "code" character varying NOT NULL,
+ "name" character varying NOT NULL,
+ "description" character varying,
+ "usage_count" integer,
+ "creator_id" character varying,
+ "created_at" TIMESTAMP NOT NULL,
+ "updated_at" TIMESTAMP NOT NULL,
+ "source_guild_id" character varying,
+ "serialized_source_guild" text NOT NULL,
+ CONSTRAINT "UQ_be38737bf339baf63b1daeffb55" UNIQUE ("code"),
+ CONSTRAINT "PK_515948649ce0bbbe391de702ae5" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "guilds" (
+ "id" character varying NOT NULL,
+ "afk_channel_id" character varying,
+ "afk_timeout" integer,
+ "banner" character varying,
+ "default_message_notifications" integer,
+ "description" character varying,
+ "discovery_splash" character varying,
+ "explicit_content_filter" integer,
+ "features" text NOT NULL,
+ "primary_category_id" integer,
+ "icon" character varying,
+ "large" boolean,
+ "max_members" integer,
+ "max_presences" integer,
+ "max_video_channel_users" integer,
+ "member_count" integer,
+ "presence_count" integer,
+ "template_id" character varying,
+ "mfa_level" integer,
+ "name" character varying NOT NULL,
+ "owner_id" character varying,
+ "preferred_locale" character varying,
+ "premium_subscription_count" integer,
+ "premium_tier" integer,
+ "public_updates_channel_id" character varying,
+ "rules_channel_id" character varying,
+ "region" character varying,
+ "splash" character varying,
+ "system_channel_id" character varying,
+ "system_channel_flags" integer,
+ "unavailable" boolean,
+ "verification_level" integer,
+ "welcome_screen" text NOT NULL,
+ "widget_channel_id" character varying,
+ "widget_enabled" boolean,
+ "nsfw_level" integer,
+ "nsfw" boolean,
+ "parent" character varying,
+ CONSTRAINT "PK_e7e7f2a51bd6d96a9ac2aa560f9" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "team_members" (
+ "id" character varying NOT NULL,
+ "membership_state" integer NOT NULL,
+ "permissions" text NOT NULL,
+ "team_id" character varying,
+ "user_id" character varying,
+ CONSTRAINT "PK_ca3eae89dcf20c9fd95bf7460aa" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "teams" (
+ "id" character varying NOT NULL,
+ "icon" character varying,
+ "name" character varying NOT NULL,
+ "owner_user_id" character varying,
+ CONSTRAINT "PK_7e5523774a38b08a6236d322403" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" character varying NOT NULL,
+ "name" character varying NOT NULL,
+ "icon" character varying,
+ "description" character varying NOT NULL,
+ "rpc_origins" text,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" character varying,
+ "privacy_policy_url" character varying,
+ "summary" character varying,
+ "verify_key" character varying NOT NULL,
+ "primary_sku_id" character varying,
+ "slug" character varying,
+ "cover_image" character varying,
+ "flags" character varying NOT NULL,
+ "owner_id" character varying,
+ "team_id" character varying,
+ "guild_id" character varying,
+ CONSTRAINT "PK_938c0a27255637bde919591888f" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "audit_logs" (
+ "id" character varying NOT NULL,
+ "user_id" character varying,
+ "action_type" integer NOT NULL,
+ "options" text,
+ "changes" text NOT NULL,
+ "reason" character varying,
+ "target_id" character varying,
+ CONSTRAINT "PK_1bb179d048bbc581caa3b013439" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "categories" (
+ "id" integer NOT NULL,
+ "name" character varying,
+ "localizations" text NOT NULL,
+ "is_primary" boolean,
+ CONSTRAINT "PK_24dbc6126a28ff948da33e97d3b" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "rate_limits" (
+ "id" character varying NOT NULL,
+ "executor_id" character varying NOT NULL,
+ "hits" integer NOT NULL,
+ "blocked" boolean NOT NULL,
+ "expires_at" TIMESTAMP NOT NULL,
+ CONSTRAINT "PK_3b4449f1f5fc167d921ee619f65" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "sessions" (
+ "id" character varying NOT NULL,
+ "user_id" character varying,
+ "session_id" character varying NOT NULL,
+ "activities" text,
+ "client_info" text NOT NULL,
+ "status" character varying NOT NULL,
+ CONSTRAINT "PK_3238ef96f18b355b671619111bc" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "sticker_packs" (
+ "id" character varying NOT NULL,
+ "name" character varying NOT NULL,
+ "description" character varying,
+ "banner_asset_id" character varying,
+ "cover_sticker_id" character varying,
+ "coverStickerId" character varying,
+ CONSTRAINT "PK_a27381efea0f876f5d3233af655" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "client_release" (
+ "id" character varying NOT NULL,
+ "name" character varying NOT NULL,
+ "pub_date" character varying NOT NULL,
+ "url" character varying NOT NULL,
+ "deb_url" character varying NOT NULL,
+ "osx_url" character varying NOT NULL,
+ "win_url" character varying NOT NULL,
+ "notes" character varying,
+ CONSTRAINT "PK_4c4ea258342d2d6ba1be0a71a43" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "notes" (
+ "id" character varying NOT NULL,
+ "content" character varying NOT NULL,
+ "owner_id" character varying,
+ "target_id" character varying,
+ CONSTRAINT "UQ_74e6689b9568cc965b8bfc9150b" UNIQUE ("owner_id", "target_id"),
+ CONSTRAINT "PK_af6206538ea96c4e77e9f400c3d" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "member_roles" (
+ "index" integer NOT NULL,
+ "role_id" character varying NOT NULL,
+ CONSTRAINT "PK_951c1d72a0fd1da8760b4a1fd66" PRIMARY KEY ("index", "role_id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_5d7ddc8a5f9c167f548625e772" ON "member_roles" ("index")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_e9080e7a7997a0170026d5139c" ON "member_roles" ("role_id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_user_mentions" (
+ "messagesId" character varying NOT NULL,
+ "usersId" character varying NOT NULL,
+ CONSTRAINT "PK_9b9b6e245ad47a48dbd7605d4fb" PRIMARY KEY ("messagesId", "usersId")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_a343387fc560ef378760681c23" ON "message_user_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_b831eb18ceebd28976239b1e2f" ON "message_user_mentions" ("usersId")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_role_mentions" (
+ "messagesId" character varying NOT NULL,
+ "rolesId" character varying NOT NULL,
+ CONSTRAINT "PK_74dba92cc300452a6e14b83ed44" PRIMARY KEY ("messagesId", "rolesId")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_a8242cf535337a490b0feaea0b" ON "message_role_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_29d63eb1a458200851bc37d074" ON "message_role_mentions" ("rolesId")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_channel_mentions" (
+ "messagesId" character varying NOT NULL,
+ "channelsId" character varying NOT NULL,
+ CONSTRAINT "PK_85cb45351497cd9d06a79ced65e" PRIMARY KEY ("messagesId", "channelsId")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_2a27102ecd1d81b4582a436092" ON "message_channel_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_bdb8c09e1464cabf62105bf4b9" ON "message_channel_mentions" ("channelsId")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_stickers" (
+ "messagesId" character varying NOT NULL,
+ "stickersId" character varying NOT NULL,
+ CONSTRAINT "PK_ed820c4093d0b8cd1d2bcf66087" PRIMARY KEY ("messagesId", "stickersId")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_40bb6f23e7cc133292e92829d2" ON "message_stickers" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_e22a70819d07659c7a71c112a1" ON "message_stickers" ("stickersId")
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "relationships"
+ ADD CONSTRAINT "FK_9af4194bab1250b1c584ae4f1d7" FOREIGN KEY ("from_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "relationships"
+ ADD CONSTRAINT "FK_9c7f6b98a9843b76dce1b0c878b" FOREIGN KEY ("to_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "connected_accounts"
+ ADD CONSTRAINT "FK_f47244225a6a1eac04a3463dd90" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "backup_codes"
+ ADD CONSTRAINT "FK_70066ea80d2f4b871beda32633b" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "bans"
+ ADD CONSTRAINT "FK_5999e8e449f80a236ff72023559" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "bans"
+ ADD CONSTRAINT "FK_9d3ab7dd180ebdd245cdb66ecad" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "bans"
+ ADD CONSTRAINT "FK_07ad88c86d1f290d46748410d58" FOREIGN KEY ("executor_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "recipients"
+ ADD CONSTRAINT "FK_2f18ee1ba667f233ae86c0ea60e" FOREIGN KEY ("channel_id") REFERENCES "channels"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "recipients"
+ ADD CONSTRAINT "FK_6157e8b6ba4e6e3089616481fe2" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "roles"
+ ADD CONSTRAINT "FK_c32c1ab1c4dc7dcb0278c4b1b8b" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "members"
+ ADD CONSTRAINT "FK_28b53062261b996d9c99fa12404" FOREIGN KEY ("id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "members"
+ ADD CONSTRAINT "FK_16aceddd5b89825b8ed6029ad1c" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "webhooks"
+ ADD CONSTRAINT "FK_487a7af59d189f744fe394368fc" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "webhooks"
+ ADD CONSTRAINT "FK_df528cf77e82f8032230e7e37d8" FOREIGN KEY ("channel_id") REFERENCES "channels"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "webhooks"
+ ADD CONSTRAINT "FK_c3e5305461931763b56aa905f1c" FOREIGN KEY ("application_id") REFERENCES "applications"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "webhooks"
+ ADD CONSTRAINT "FK_0d523f6f997c86e052c49b1455f" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "webhooks"
+ ADD CONSTRAINT "FK_3a285f4f49c40e0706d3018bc9f" FOREIGN KEY ("source_guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "stickers"
+ ADD CONSTRAINT "FK_e7cfa5cefa6661b3fb8fda8ce69" FOREIGN KEY ("pack_id") REFERENCES "sticker_packs"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "stickers"
+ ADD CONSTRAINT "FK_193d551d852aca5347ef5c9f205" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "stickers"
+ ADD CONSTRAINT "FK_8f4ee73f2bb2325ff980502e158" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "attachments"
+ ADD CONSTRAINT "FK_623e10eec51ada466c5038979e3" FOREIGN KEY ("message_id") REFERENCES "messages"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages"
+ ADD CONSTRAINT "FK_86b9109b155eb70c0a2ca3b4b6d" FOREIGN KEY ("channel_id") REFERENCES "channels"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages"
+ ADD CONSTRAINT "FK_b193588441b085352a4c0109423" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages"
+ ADD CONSTRAINT "FK_05535bc695e9f7ee104616459d3" FOREIGN KEY ("author_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages"
+ ADD CONSTRAINT "FK_b0525304f2262b7014245351c76" FOREIGN KEY ("member_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages"
+ ADD CONSTRAINT "FK_f83c04bcf1df4e5c0e7a52ed348" FOREIGN KEY ("webhook_id") REFERENCES "webhooks"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages"
+ ADD CONSTRAINT "FK_5d3ec1cb962de6488637fd779d6" FOREIGN KEY ("application_id") REFERENCES "applications"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages"
+ ADD CONSTRAINT "FK_61a92bb65b302a76d9c1fcd3174" FOREIGN KEY ("message_reference_id") REFERENCES "messages"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "read_states"
+ ADD CONSTRAINT "FK_40da2fca4e0eaf7a23b5bfc5d34" FOREIGN KEY ("channel_id") REFERENCES "channels"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "read_states"
+ ADD CONSTRAINT "FK_195f92e4dd1254a4e348c043763" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites"
+ ADD CONSTRAINT "FK_3f4939aa1461e8af57fea3fb05d" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites"
+ ADD CONSTRAINT "FK_6a15b051fe5050aa00a4b9ff0f6" FOREIGN KEY ("channel_id") REFERENCES "channels"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites"
+ ADD CONSTRAINT "FK_15c35422032e0b22b4ada95f48f" FOREIGN KEY ("inviter_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites"
+ ADD CONSTRAINT "FK_11a0d394f8fc649c19ce5f16b59" FOREIGN KEY ("target_user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "voice_states"
+ ADD CONSTRAINT "FK_03779ef216d4b0358470d9cb748" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "voice_states"
+ ADD CONSTRAINT "FK_9f8d389866b40b6657edd026dd4" FOREIGN KEY ("channel_id") REFERENCES "channels"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "voice_states"
+ ADD CONSTRAINT "FK_5fe1d5f931a67e85039c640001b" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "channels"
+ ADD CONSTRAINT "FK_c253dafe5f3a03ec00cd8fb4581" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "channels"
+ ADD CONSTRAINT "FK_3274522d14af40540b1a883fc80" FOREIGN KEY ("parent_id") REFERENCES "channels"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "channels"
+ ADD CONSTRAINT "FK_3873ed438575cce703ecff4fc7b" FOREIGN KEY ("owner_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "emojis"
+ ADD CONSTRAINT "FK_4b988e0db89d94cebcf07f598cc" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "emojis"
+ ADD CONSTRAINT "FK_fa7ddd5f9a214e28ce596548421" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "templates"
+ ADD CONSTRAINT "FK_d7374b7f8f5fbfdececa4fb62e1" FOREIGN KEY ("creator_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "templates"
+ ADD CONSTRAINT "FK_445d00eaaea0e60a017a5ed0c11" FOREIGN KEY ("source_guild_id") REFERENCES "guilds"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ ADD CONSTRAINT "FK_f591a66b8019d87b0fe6c12dad6" FOREIGN KEY ("afk_channel_id") REFERENCES "channels"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ ADD CONSTRAINT "FK_e2a2f873a64a5cf62526de42325" FOREIGN KEY ("template_id") REFERENCES "templates"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ ADD CONSTRAINT "FK_fc1a451727e3643ca572a3bb394" FOREIGN KEY ("owner_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ ADD CONSTRAINT "FK_8d450b016dc8bec35f36729e4b0" FOREIGN KEY ("public_updates_channel_id") REFERENCES "channels"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ ADD CONSTRAINT "FK_95828668aa333460582e0ca6396" FOREIGN KEY ("rules_channel_id") REFERENCES "channels"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ ADD CONSTRAINT "FK_cfc3d3ad260f8121c95b31a1fce" FOREIGN KEY ("system_channel_id") REFERENCES "channels"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ ADD CONSTRAINT "FK_9d1d665379eefde7876a17afa99" FOREIGN KEY ("widget_channel_id") REFERENCES "channels"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "team_members"
+ ADD CONSTRAINT "FK_fdad7d5768277e60c40e01cdcea" FOREIGN KEY ("team_id") REFERENCES "teams"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "team_members"
+ ADD CONSTRAINT "FK_c2bf4967c8c2a6b845dadfbf3d4" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "teams"
+ ADD CONSTRAINT "FK_13f00abf7cb6096c43ecaf8c108" FOREIGN KEY ("owner_user_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD CONSTRAINT "FK_e5bf78cdbbe9ba91062d74c5aba" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "audit_logs"
+ ADD CONSTRAINT "FK_3cd01cd3ae7aab010310d96ac8e" FOREIGN KEY ("target_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "audit_logs"
+ ADD CONSTRAINT "FK_bd2726fd31b35443f2245b93ba0" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "sessions"
+ ADD CONSTRAINT "FK_085d540d9f418cfbdc7bd55bb19" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "sticker_packs"
+ ADD CONSTRAINT "FK_448fafba4355ee1c837bbc865f1" FOREIGN KEY ("coverStickerId") REFERENCES "stickers"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "notes"
+ ADD CONSTRAINT "FK_f9e103f8ae67cb1787063597925" FOREIGN KEY ("owner_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "notes"
+ ADD CONSTRAINT "FK_23e08e5b4481711d573e1abecdc" FOREIGN KEY ("target_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "member_roles"
+ ADD CONSTRAINT "FK_5d7ddc8a5f9c167f548625e772e" FOREIGN KEY ("index") REFERENCES "members"("index") ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "member_roles"
+ ADD CONSTRAINT "FK_e9080e7a7997a0170026d5139c1" FOREIGN KEY ("role_id") REFERENCES "roles"("id") ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_user_mentions"
+ ADD CONSTRAINT "FK_a343387fc560ef378760681c236" FOREIGN KEY ("messagesId") REFERENCES "messages"("id") ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_user_mentions"
+ ADD CONSTRAINT "FK_b831eb18ceebd28976239b1e2f8" FOREIGN KEY ("usersId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_role_mentions"
+ ADD CONSTRAINT "FK_a8242cf535337a490b0feaea0b4" FOREIGN KEY ("messagesId") REFERENCES "messages"("id") ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_role_mentions"
+ ADD CONSTRAINT "FK_29d63eb1a458200851bc37d074b" FOREIGN KEY ("rolesId") REFERENCES "roles"("id") ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_channel_mentions"
+ ADD CONSTRAINT "FK_2a27102ecd1d81b4582a4360921" FOREIGN KEY ("messagesId") REFERENCES "messages"("id") ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_channel_mentions"
+ ADD CONSTRAINT "FK_bdb8c09e1464cabf62105bf4b9d" FOREIGN KEY ("channelsId") REFERENCES "channels"("id") ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_stickers"
+ ADD CONSTRAINT "FK_40bb6f23e7cc133292e92829d28" FOREIGN KEY ("messagesId") REFERENCES "messages"("id") ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_stickers"
+ ADD CONSTRAINT "FK_e22a70819d07659c7a71c112a1f" FOREIGN KEY ("stickersId") REFERENCES "stickers"("id") ON DELETE CASCADE ON UPDATE CASCADE
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "query-result-cache" (
+ "id" SERIAL NOT NULL,
+ "identifier" character varying,
+ "time" bigint NOT NULL,
+ "duration" integer NOT NULL,
+ "query" text NOT NULL,
+ "result" text NOT NULL,
+ CONSTRAINT "PK_6a98f758d8bfd010e7e10ffd3d3" PRIMARY KEY ("id")
+ )
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ DROP TABLE "query-result-cache"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_stickers" DROP CONSTRAINT "FK_e22a70819d07659c7a71c112a1f"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_stickers" DROP CONSTRAINT "FK_40bb6f23e7cc133292e92829d28"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_channel_mentions" DROP CONSTRAINT "FK_bdb8c09e1464cabf62105bf4b9d"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_channel_mentions" DROP CONSTRAINT "FK_2a27102ecd1d81b4582a4360921"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_role_mentions" DROP CONSTRAINT "FK_29d63eb1a458200851bc37d074b"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_role_mentions" DROP CONSTRAINT "FK_a8242cf535337a490b0feaea0b4"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_user_mentions" DROP CONSTRAINT "FK_b831eb18ceebd28976239b1e2f8"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_user_mentions" DROP CONSTRAINT "FK_a343387fc560ef378760681c236"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "member_roles" DROP CONSTRAINT "FK_e9080e7a7997a0170026d5139c1"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "member_roles" DROP CONSTRAINT "FK_5d7ddc8a5f9c167f548625e772e"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "notes" DROP CONSTRAINT "FK_23e08e5b4481711d573e1abecdc"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "notes" DROP CONSTRAINT "FK_f9e103f8ae67cb1787063597925"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "sticker_packs" DROP CONSTRAINT "FK_448fafba4355ee1c837bbc865f1"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "sessions" DROP CONSTRAINT "FK_085d540d9f418cfbdc7bd55bb19"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "audit_logs" DROP CONSTRAINT "FK_bd2726fd31b35443f2245b93ba0"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "audit_logs" DROP CONSTRAINT "FK_3cd01cd3ae7aab010310d96ac8e"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP CONSTRAINT "FK_e5bf78cdbbe9ba91062d74c5aba"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP CONSTRAINT "FK_a36ed02953077f408d0f3ebc424"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "teams" DROP CONSTRAINT "FK_13f00abf7cb6096c43ecaf8c108"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "team_members" DROP CONSTRAINT "FK_c2bf4967c8c2a6b845dadfbf3d4"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "team_members" DROP CONSTRAINT "FK_fdad7d5768277e60c40e01cdcea"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds" DROP CONSTRAINT "FK_9d1d665379eefde7876a17afa99"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds" DROP CONSTRAINT "FK_cfc3d3ad260f8121c95b31a1fce"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds" DROP CONSTRAINT "FK_95828668aa333460582e0ca6396"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds" DROP CONSTRAINT "FK_8d450b016dc8bec35f36729e4b0"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds" DROP CONSTRAINT "FK_fc1a451727e3643ca572a3bb394"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds" DROP CONSTRAINT "FK_e2a2f873a64a5cf62526de42325"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds" DROP CONSTRAINT "FK_f591a66b8019d87b0fe6c12dad6"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "templates" DROP CONSTRAINT "FK_445d00eaaea0e60a017a5ed0c11"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "templates" DROP CONSTRAINT "FK_d7374b7f8f5fbfdececa4fb62e1"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "emojis" DROP CONSTRAINT "FK_fa7ddd5f9a214e28ce596548421"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "emojis" DROP CONSTRAINT "FK_4b988e0db89d94cebcf07f598cc"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "channels" DROP CONSTRAINT "FK_3873ed438575cce703ecff4fc7b"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "channels" DROP CONSTRAINT "FK_3274522d14af40540b1a883fc80"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "channels" DROP CONSTRAINT "FK_c253dafe5f3a03ec00cd8fb4581"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "voice_states" DROP CONSTRAINT "FK_5fe1d5f931a67e85039c640001b"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "voice_states" DROP CONSTRAINT "FK_9f8d389866b40b6657edd026dd4"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "voice_states" DROP CONSTRAINT "FK_03779ef216d4b0358470d9cb748"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites" DROP CONSTRAINT "FK_11a0d394f8fc649c19ce5f16b59"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites" DROP CONSTRAINT "FK_15c35422032e0b22b4ada95f48f"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites" DROP CONSTRAINT "FK_6a15b051fe5050aa00a4b9ff0f6"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites" DROP CONSTRAINT "FK_3f4939aa1461e8af57fea3fb05d"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "read_states" DROP CONSTRAINT "FK_195f92e4dd1254a4e348c043763"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "read_states" DROP CONSTRAINT "FK_40da2fca4e0eaf7a23b5bfc5d34"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages" DROP CONSTRAINT "FK_61a92bb65b302a76d9c1fcd3174"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages" DROP CONSTRAINT "FK_5d3ec1cb962de6488637fd779d6"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages" DROP CONSTRAINT "FK_f83c04bcf1df4e5c0e7a52ed348"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages" DROP CONSTRAINT "FK_b0525304f2262b7014245351c76"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages" DROP CONSTRAINT "FK_05535bc695e9f7ee104616459d3"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages" DROP CONSTRAINT "FK_b193588441b085352a4c0109423"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages" DROP CONSTRAINT "FK_86b9109b155eb70c0a2ca3b4b6d"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "attachments" DROP CONSTRAINT "FK_623e10eec51ada466c5038979e3"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "stickers" DROP CONSTRAINT "FK_8f4ee73f2bb2325ff980502e158"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "stickers" DROP CONSTRAINT "FK_193d551d852aca5347ef5c9f205"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "stickers" DROP CONSTRAINT "FK_e7cfa5cefa6661b3fb8fda8ce69"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "webhooks" DROP CONSTRAINT "FK_3a285f4f49c40e0706d3018bc9f"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "webhooks" DROP CONSTRAINT "FK_0d523f6f997c86e052c49b1455f"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "webhooks" DROP CONSTRAINT "FK_c3e5305461931763b56aa905f1c"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "webhooks" DROP CONSTRAINT "FK_df528cf77e82f8032230e7e37d8"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "webhooks" DROP CONSTRAINT "FK_487a7af59d189f744fe394368fc"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "members" DROP CONSTRAINT "FK_16aceddd5b89825b8ed6029ad1c"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "members" DROP CONSTRAINT "FK_28b53062261b996d9c99fa12404"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "roles" DROP CONSTRAINT "FK_c32c1ab1c4dc7dcb0278c4b1b8b"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "recipients" DROP CONSTRAINT "FK_6157e8b6ba4e6e3089616481fe2"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "recipients" DROP CONSTRAINT "FK_2f18ee1ba667f233ae86c0ea60e"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "bans" DROP CONSTRAINT "FK_07ad88c86d1f290d46748410d58"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "bans" DROP CONSTRAINT "FK_9d3ab7dd180ebdd245cdb66ecad"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "bans" DROP CONSTRAINT "FK_5999e8e449f80a236ff72023559"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "backup_codes" DROP CONSTRAINT "FK_70066ea80d2f4b871beda32633b"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "connected_accounts" DROP CONSTRAINT "FK_f47244225a6a1eac04a3463dd90"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "relationships" DROP CONSTRAINT "FK_9c7f6b98a9843b76dce1b0c878b"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "relationships" DROP CONSTRAINT "FK_9af4194bab1250b1c584ae4f1d7"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_e22a70819d07659c7a71c112a1"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_40bb6f23e7cc133292e92829d2"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_stickers"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_bdb8c09e1464cabf62105bf4b9"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_2a27102ecd1d81b4582a436092"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_channel_mentions"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_29d63eb1a458200851bc37d074"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_a8242cf535337a490b0feaea0b"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_role_mentions"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_b831eb18ceebd28976239b1e2f"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_a343387fc560ef378760681c23"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_user_mentions"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_e9080e7a7997a0170026d5139c"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_5d7ddc8a5f9c167f548625e772"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "member_roles"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "notes"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "client_release"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "sticker_packs"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "sessions"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "rate_limits"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "categories"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "audit_logs"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "teams"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "team_members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "guilds"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "templates"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "emojis"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "channels"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "voice_states"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "invites"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_0abf8b443321bd3cf7f81ee17a"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "read_states"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_3ed7a60fb7dbe04e1ba9332a8b"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_05535bc695e9f7ee104616459d"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_86b9109b155eb70c0a2ca3b4b6"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "messages"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "attachments"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "stickers"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "webhooks"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_bb2bf9386ac443afbbbf9f12d3"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "roles"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "recipients"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "bans"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "backup_codes"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "users"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "connected_accounts"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "public"."IDX_a0b2ff0a598df0b0d055934a17"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "relationships"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "config"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/postgres/1659921826567-premium_since_as_date.ts b/src/util/migrations/postgres/1659921826567-premium_since_as_date.ts
new file mode 100644
index 00000000..ac1e2edb
--- /dev/null
+++ b/src/util/migrations/postgres/1659921826567-premium_since_as_date.ts
@@ -0,0 +1,26 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class premiumSinceAsDate1659921826567 implements MigrationInterface {
+ name = 'premiumSinceAsDate1659921826567'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "members" DROP COLUMN "premium_since"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "members"
+ ADD "premium_since" TIMESTAMP
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "members" DROP COLUMN "premium_since"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "members"
+ ADD "premium_since" bigint
+ `);
+ }
+
+}
diff --git a/src/util/migrations/postgres/1660130561959-updated-applications.ts b/src/util/migrations/postgres/1660130561959-updated-applications.ts
new file mode 100644
index 00000000..8fab54c7
--- /dev/null
+++ b/src/util/migrations/postgres/1660130561959-updated-applications.ts
@@ -0,0 +1,182 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class updatedApplications1660130561959 implements MigrationInterface {
+ name = 'updatedApplications1660130561959'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP CONSTRAINT "FK_e5bf78cdbbe9ba91062d74c5aba"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "rpc_origins"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "primary_sku_id"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "slug"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "guild_id"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "type" text
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "hook" boolean NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "redirect_uris" text
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "rpc_application_state" integer
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "store_application_state" integer
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "verification_state" integer
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "interactions_endpoint_url" character varying
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "integration_public" boolean
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "integration_require_code_grant" boolean
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "discoverability_state" integer
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "discovery_eligibility_flags" integer
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "tags" text
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "install_params" text
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "bot_user_id" character varying
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD CONSTRAINT "UQ_2ce5a55796fe4c2f77ece57a647" UNIQUE ("bot_user_id")
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ALTER COLUMN "description" DROP NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "flags"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "flags" integer NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD CONSTRAINT "FK_2ce5a55796fe4c2f77ece57a647" FOREIGN KEY ("bot_user_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP CONSTRAINT "FK_2ce5a55796fe4c2f77ece57a647"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "flags"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "flags" character varying NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ALTER COLUMN "description"
+ SET NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP CONSTRAINT "UQ_2ce5a55796fe4c2f77ece57a647"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "bot_user_id"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "install_params"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "tags"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "discovery_eligibility_flags"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "discoverability_state"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "integration_require_code_grant"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "integration_public"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "interactions_endpoint_url"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "verification_state"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "store_application_state"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "rpc_application_state"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "redirect_uris"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "hook"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications" DROP COLUMN "type"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "guild_id" character varying
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "slug" character varying
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "primary_sku_id" character varying
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD "rpc_origins" text
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ ADD CONSTRAINT "FK_e5bf78cdbbe9ba91062d74c5aba" FOREIGN KEY ("guild_id") REFERENCES "guilds"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ }
+
+}
diff --git a/src/util/migrations/postgres/1660257815436-CodeCleanup2.ts b/src/util/migrations/postgres/1660257815436-CodeCleanup2.ts
new file mode 100644
index 00000000..511c2f5a
--- /dev/null
+++ b/src/util/migrations/postgres/1660257815436-CodeCleanup2.ts
@@ -0,0 +1,59 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class CodeCleanup21660257815436 implements MigrationInterface {
+ name = 'CodeCleanup21660257815436'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "user_settings" (
+ "id" character varying NOT NULL,
+ "afk_timeout" integer,
+ "allow_accessibility_detection" boolean,
+ "animate_emoji" boolean,
+ "animate_stickers" integer,
+ "contact_sync_enabled" boolean,
+ "convert_emoticons" boolean,
+ "custom_status" text,
+ "default_guilds_restricted" boolean,
+ "detect_platform_accounts" boolean,
+ "developer_mode" boolean,
+ "disable_games_tab" boolean,
+ "enable_tts_command" boolean,
+ "explicit_content_filter" integer,
+ "friend_source_flags" text,
+ "gateway_connected" boolean,
+ "gif_auto_play" boolean,
+ "guild_folders" text,
+ "guild_positions" text,
+ "inline_attachment_media" boolean,
+ "inline_embed_media" boolean,
+ "locale" character varying,
+ "message_display_compact" boolean,
+ "native_phone_integration_enabled" boolean,
+ "render_embeds" boolean,
+ "render_reactions" boolean,
+ "restricted_guilds" text,
+ "show_current_game" boolean,
+ "status" character varying,
+ "stream_notifications_enabled" boolean,
+ "theme" character varying,
+ "timezone_offset" integer,
+ CONSTRAINT "PK_00f004f5922a0744d174530d639" PRIMARY KEY ("id")
+ )
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ ADD "premium_progress_bar_enabled" boolean
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "guilds" DROP COLUMN "premium_progress_bar_enabled"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "user_settings"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/postgres/1660258372154-CodeCleanup3.ts b/src/util/migrations/postgres/1660258372154-CodeCleanup3.ts
new file mode 100644
index 00000000..e2823a54
--- /dev/null
+++ b/src/util/migrations/postgres/1660258372154-CodeCleanup3.ts
@@ -0,0 +1,19 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class CodeCleanup31660258372154 implements MigrationInterface {
+ name = 'CodeCleanup31660258372154'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "users" DROP COLUMN "settings"
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ ADD "settings" text NOT NULL
+ `);
+ }
+
+}
diff --git a/src/util/migrations/postgres/1660260565996-CodeCleanup4.ts b/src/util/migrations/postgres/1660260565996-CodeCleanup4.ts
new file mode 100644
index 00000000..0aaf7197
--- /dev/null
+++ b/src/util/migrations/postgres/1660260565996-CodeCleanup4.ts
@@ -0,0 +1,33 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class CodeCleanup41660260565996 implements MigrationInterface {
+ name = 'CodeCleanup41660260565996'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ ADD "settingsId" character varying
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ ADD CONSTRAINT "UQ_76ba283779c8441fd5ff819c8cf" UNIQUE ("settingsId")
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ ADD CONSTRAINT "FK_76ba283779c8441fd5ff819c8cf" FOREIGN KEY ("settingsId") REFERENCES "user_settings"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "users" DROP CONSTRAINT "FK_76ba283779c8441fd5ff819c8cf"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "users" DROP CONSTRAINT "UQ_76ba283779c8441fd5ff819c8cf"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "users" DROP COLUMN "settingsId"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/postgres/1660265907544-CodeCleanup5.ts b/src/util/migrations/postgres/1660265907544-CodeCleanup5.ts
new file mode 100644
index 00000000..157d686a
--- /dev/null
+++ b/src/util/migrations/postgres/1660265907544-CodeCleanup5.ts
@@ -0,0 +1,26 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class CodeCleanup51660265907544 implements MigrationInterface {
+ name = 'CodeCleanup51660265907544'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "channels"
+ ADD "flags" integer
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "channels"
+ ADD "default_thread_rate_limit_per_user" integer
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "channels" DROP COLUMN "default_thread_rate_limit_per_user"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "channels" DROP COLUMN "flags"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/postgres/1660416055566-InvitersAreDeletable.ts b/src/util/migrations/postgres/1660416055566-InvitersAreDeletable.ts
new file mode 100644
index 00000000..e6101318
--- /dev/null
+++ b/src/util/migrations/postgres/1660416055566-InvitersAreDeletable.ts
@@ -0,0 +1,26 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class InvitersAreDeletable1660416055566 implements MigrationInterface {
+ name = 'InvitersAreDeletable1660416055566'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "invites" DROP CONSTRAINT "FK_15c35422032e0b22b4ada95f48f"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites"
+ ADD CONSTRAINT "FK_15c35422032e0b22b4ada95f48f" FOREIGN KEY ("inviter_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "invites" DROP CONSTRAINT "FK_15c35422032e0b22b4ada95f48f"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites"
+ ADD CONSTRAINT "FK_15c35422032e0b22b4ada95f48f" FOREIGN KEY ("inviter_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ `);
+ }
+
+}
diff --git a/src/util/migrations/postgres/1660549242936-fix_nullables.ts b/src/util/migrations/postgres/1660549242936-fix_nullables.ts
new file mode 100644
index 00000000..b9a0194d
--- /dev/null
+++ b/src/util/migrations/postgres/1660549242936-fix_nullables.ts
@@ -0,0 +1,30 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class fixNullables1660549242936 implements MigrationInterface {
+ name = 'fixNullables1660549242936'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ ALTER COLUMN "bio" DROP NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ ALTER COLUMN "mfa_enabled" DROP NOT NULL
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ ALTER COLUMN "mfa_enabled"
+ SET NOT NULL
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ ALTER COLUMN "bio"
+ SET NOT NULL
+ `);
+ }
+
+}
diff --git a/src/util/migrations/sqlite/1659899662635-initial.ts b/src/util/migrations/sqlite/1659899662635-initial.ts
new file mode 100644
index 00000000..f82e7b0d
--- /dev/null
+++ b/src/util/migrations/sqlite/1659899662635-initial.ts
@@ -0,0 +1,3529 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class initial1659899662635 implements MigrationInterface {
+ name = 'initial1659899662635'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "config" ("key" varchar PRIMARY KEY NOT NULL, "value" text)
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "relationships" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "from_id" varchar NOT NULL,
+ "to_id" varchar NOT NULL,
+ "nickname" varchar,
+ "type" integer NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_a0b2ff0a598df0b0d055934a17" ON "relationships" ("from_id", "to_id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "connected_accounts" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "access_token" varchar NOT NULL,
+ "friend_sync" boolean NOT NULL,
+ "name" varchar NOT NULL,
+ "revoked" boolean NOT NULL,
+ "show_activity" boolean NOT NULL,
+ "type" varchar NOT NULL,
+ "verified" boolean NOT NULL,
+ "visibility" integer NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "users" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "username" varchar NOT NULL,
+ "discriminator" varchar NOT NULL,
+ "avatar" varchar,
+ "accent_color" integer,
+ "banner" varchar,
+ "phone" varchar,
+ "desktop" boolean NOT NULL,
+ "mobile" boolean NOT NULL,
+ "premium" boolean NOT NULL,
+ "premium_type" integer NOT NULL,
+ "bot" boolean NOT NULL,
+ "bio" varchar NOT NULL,
+ "system" boolean NOT NULL,
+ "nsfw_allowed" boolean NOT NULL,
+ "mfa_enabled" boolean NOT NULL,
+ "totp_secret" varchar,
+ "totp_last_ticket" varchar,
+ "created_at" datetime NOT NULL,
+ "premium_since" datetime,
+ "verified" boolean NOT NULL,
+ "disabled" boolean NOT NULL,
+ "deleted" boolean NOT NULL,
+ "email" varchar,
+ "flags" varchar NOT NULL,
+ "public_flags" integer NOT NULL,
+ "rights" bigint NOT NULL,
+ "data" text NOT NULL,
+ "fingerprints" text NOT NULL,
+ "settings" text NOT NULL,
+ "extended_settings" text NOT NULL,
+ "notes" text NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "backup_codes" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "code" varchar NOT NULL,
+ "consumed" boolean NOT NULL,
+ "expired" boolean NOT NULL,
+ "user_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "bans" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "guild_id" varchar,
+ "executor_id" varchar,
+ "ip" varchar NOT NULL,
+ "reason" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "recipients" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "channel_id" varchar NOT NULL,
+ "user_id" varchar NOT NULL,
+ "closed" boolean NOT NULL DEFAULT (0)
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "roles" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "guild_id" varchar,
+ "color" integer NOT NULL,
+ "hoist" boolean NOT NULL,
+ "managed" boolean NOT NULL,
+ "mentionable" boolean NOT NULL,
+ "name" varchar NOT NULL,
+ "permissions" varchar NOT NULL,
+ "position" integer NOT NULL,
+ "icon" varchar,
+ "unicode_emoji" varchar,
+ "tags" text
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "members" (
+ "index" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
+ "id" varchar NOT NULL,
+ "guild_id" varchar NOT NULL,
+ "nick" varchar,
+ "joined_at" datetime NOT NULL,
+ "premium_since" bigint,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "pending" boolean NOT NULL,
+ "settings" text NOT NULL,
+ "last_message_id" varchar,
+ "joined_by" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_bb2bf9386ac443afbbbf9f12d3" ON "members" ("id", "guild_id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "webhooks" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "type" integer NOT NULL,
+ "name" varchar,
+ "avatar" varchar,
+ "token" varchar,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "application_id" varchar,
+ "user_id" varchar,
+ "source_guild_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "stickers" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "description" varchar,
+ "available" boolean,
+ "tags" varchar,
+ "pack_id" varchar,
+ "guild_id" varchar,
+ "user_id" varchar,
+ "type" integer NOT NULL,
+ "format_type" integer NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "attachments" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "filename" varchar NOT NULL,
+ "size" integer NOT NULL,
+ "url" varchar NOT NULL,
+ "proxy_url" varchar NOT NULL,
+ "height" integer,
+ "width" integer,
+ "content_type" varchar,
+ "message_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "messages" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "channel_id" varchar,
+ "guild_id" varchar,
+ "author_id" varchar,
+ "member_id" varchar,
+ "webhook_id" varchar,
+ "application_id" varchar,
+ "content" varchar,
+ "timestamp" datetime NOT NULL DEFAULT (datetime('now')),
+ "edited_timestamp" datetime,
+ "tts" boolean,
+ "mention_everyone" boolean,
+ "embeds" text NOT NULL,
+ "reactions" text NOT NULL,
+ "nonce" text,
+ "pinned" boolean,
+ "type" integer NOT NULL,
+ "activity" text,
+ "flags" varchar,
+ "message_reference" text,
+ "interaction" text,
+ "components" text,
+ "message_reference_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_86b9109b155eb70c0a2ca3b4b6" ON "messages" ("channel_id")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_05535bc695e9f7ee104616459d" ON "messages" ("author_id")
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_3ed7a60fb7dbe04e1ba9332a8b" ON "messages" ("channel_id", "id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "read_states" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "channel_id" varchar NOT NULL,
+ "user_id" varchar NOT NULL,
+ "last_message_id" varchar,
+ "public_ack" varchar,
+ "notifications_cursor" varchar,
+ "last_pin_timestamp" datetime,
+ "mention_count" integer
+ )
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_0abf8b443321bd3cf7f81ee17a" ON "read_states" ("channel_id", "user_id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "invites" (
+ "code" varchar PRIMARY KEY NOT NULL,
+ "temporary" boolean NOT NULL,
+ "uses" integer NOT NULL,
+ "max_uses" integer NOT NULL,
+ "max_age" integer NOT NULL,
+ "created_at" datetime NOT NULL,
+ "expires_at" datetime NOT NULL,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "inviter_id" varchar,
+ "target_user_id" varchar,
+ "target_user_type" integer,
+ "vanity_url" boolean
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "voice_states" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "user_id" varchar,
+ "session_id" varchar NOT NULL,
+ "token" varchar,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "self_deaf" boolean NOT NULL,
+ "self_mute" boolean NOT NULL,
+ "self_stream" boolean,
+ "self_video" boolean NOT NULL,
+ "suppress" boolean NOT NULL,
+ "request_to_speak_timestamp" datetime
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "channels" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "created_at" datetime NOT NULL,
+ "name" varchar,
+ "icon" text,
+ "type" integer NOT NULL,
+ "last_message_id" varchar,
+ "guild_id" varchar,
+ "parent_id" varchar,
+ "owner_id" varchar,
+ "last_pin_timestamp" integer,
+ "default_auto_archive_duration" integer,
+ "position" integer,
+ "permission_overwrites" text,
+ "video_quality_mode" integer,
+ "bitrate" integer,
+ "user_limit" integer,
+ "nsfw" boolean,
+ "rate_limit_per_user" integer,
+ "topic" varchar,
+ "retention_policy_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "emojis" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "animated" boolean NOT NULL,
+ "available" boolean NOT NULL,
+ "guild_id" varchar NOT NULL,
+ "user_id" varchar,
+ "managed" boolean NOT NULL,
+ "name" varchar NOT NULL,
+ "require_colons" boolean NOT NULL,
+ "roles" text NOT NULL,
+ "groups" text
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "templates" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "code" varchar NOT NULL,
+ "name" varchar NOT NULL,
+ "description" varchar,
+ "usage_count" integer,
+ "creator_id" varchar,
+ "created_at" datetime NOT NULL,
+ "updated_at" datetime NOT NULL,
+ "source_guild_id" varchar,
+ "serialized_source_guild" text NOT NULL,
+ CONSTRAINT "UQ_be38737bf339baf63b1daeffb55" UNIQUE ("code")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "guilds" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "afk_channel_id" varchar,
+ "afk_timeout" integer,
+ "banner" varchar,
+ "default_message_notifications" integer,
+ "description" varchar,
+ "discovery_splash" varchar,
+ "explicit_content_filter" integer,
+ "features" text NOT NULL,
+ "primary_category_id" integer,
+ "icon" varchar,
+ "large" boolean,
+ "max_members" integer,
+ "max_presences" integer,
+ "max_video_channel_users" integer,
+ "member_count" integer,
+ "presence_count" integer,
+ "template_id" varchar,
+ "mfa_level" integer,
+ "name" varchar NOT NULL,
+ "owner_id" varchar,
+ "preferred_locale" varchar,
+ "premium_subscription_count" integer,
+ "premium_tier" integer,
+ "public_updates_channel_id" varchar,
+ "rules_channel_id" varchar,
+ "region" varchar,
+ "splash" varchar,
+ "system_channel_id" varchar,
+ "system_channel_flags" integer,
+ "unavailable" boolean,
+ "verification_level" integer,
+ "welcome_screen" text NOT NULL,
+ "widget_channel_id" varchar,
+ "widget_enabled" boolean,
+ "nsfw_level" integer,
+ "nsfw" boolean,
+ "parent" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "team_members" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "membership_state" integer NOT NULL,
+ "permissions" text NOT NULL,
+ "team_id" varchar,
+ "user_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "teams" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "icon" varchar,
+ "name" varchar NOT NULL,
+ "owner_user_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "rpc_origins" text,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "primary_sku_id" varchar,
+ "slug" varchar,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "guild_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "audit_logs" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "action_type" integer NOT NULL,
+ "options" text,
+ "changes" text NOT NULL,
+ "reason" varchar,
+ "target_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "categories" (
+ "id" integer PRIMARY KEY NOT NULL,
+ "name" varchar,
+ "localizations" text NOT NULL,
+ "is_primary" boolean
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "rate_limits" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "executor_id" varchar NOT NULL,
+ "hits" integer NOT NULL,
+ "blocked" boolean NOT NULL,
+ "expires_at" datetime NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "sessions" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "session_id" varchar NOT NULL,
+ "activities" text,
+ "client_info" text NOT NULL,
+ "status" varchar NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "sticker_packs" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "description" varchar,
+ "banner_asset_id" varchar,
+ "cover_sticker_id" varchar,
+ "coverStickerId" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "client_release" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "pub_date" varchar NOT NULL,
+ "url" varchar NOT NULL,
+ "deb_url" varchar NOT NULL,
+ "osx_url" varchar NOT NULL,
+ "win_url" varchar NOT NULL,
+ "notes" varchar
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "notes" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "content" varchar NOT NULL,
+ "owner_id" varchar,
+ "target_id" varchar,
+ CONSTRAINT "UQ_74e6689b9568cc965b8bfc9150b" UNIQUE ("owner_id", "target_id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "member_roles" (
+ "index" integer NOT NULL,
+ "role_id" varchar NOT NULL,
+ PRIMARY KEY ("index", "role_id")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_5d7ddc8a5f9c167f548625e772" ON "member_roles" ("index")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_e9080e7a7997a0170026d5139c" ON "member_roles" ("role_id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_user_mentions" (
+ "messagesId" varchar NOT NULL,
+ "usersId" varchar NOT NULL,
+ PRIMARY KEY ("messagesId", "usersId")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_a343387fc560ef378760681c23" ON "message_user_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_b831eb18ceebd28976239b1e2f" ON "message_user_mentions" ("usersId")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_role_mentions" (
+ "messagesId" varchar NOT NULL,
+ "rolesId" varchar NOT NULL,
+ PRIMARY KEY ("messagesId", "rolesId")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_a8242cf535337a490b0feaea0b" ON "message_role_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_29d63eb1a458200851bc37d074" ON "message_role_mentions" ("rolesId")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_channel_mentions" (
+ "messagesId" varchar NOT NULL,
+ "channelsId" varchar NOT NULL,
+ PRIMARY KEY ("messagesId", "channelsId")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_2a27102ecd1d81b4582a436092" ON "message_channel_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_bdb8c09e1464cabf62105bf4b9" ON "message_channel_mentions" ("channelsId")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_stickers" (
+ "messagesId" varchar NOT NULL,
+ "stickersId" varchar NOT NULL,
+ PRIMARY KEY ("messagesId", "stickersId")
+ )
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_40bb6f23e7cc133292e92829d2" ON "message_stickers" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_e22a70819d07659c7a71c112a1" ON "message_stickers" ("stickersId")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_a0b2ff0a598df0b0d055934a17"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_relationships" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "from_id" varchar NOT NULL,
+ "to_id" varchar NOT NULL,
+ "nickname" varchar,
+ "type" integer NOT NULL,
+ CONSTRAINT "FK_9af4194bab1250b1c584ae4f1d7" FOREIGN KEY ("from_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_9c7f6b98a9843b76dce1b0c878b" FOREIGN KEY ("to_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_relationships"("id", "from_id", "to_id", "nickname", "type")
+ SELECT "id",
+ "from_id",
+ "to_id",
+ "nickname",
+ "type"
+ FROM "relationships"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "relationships"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_relationships"
+ RENAME TO "relationships"
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_a0b2ff0a598df0b0d055934a17" ON "relationships" ("from_id", "to_id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_connected_accounts" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "access_token" varchar NOT NULL,
+ "friend_sync" boolean NOT NULL,
+ "name" varchar NOT NULL,
+ "revoked" boolean NOT NULL,
+ "show_activity" boolean NOT NULL,
+ "type" varchar NOT NULL,
+ "verified" boolean NOT NULL,
+ "visibility" integer NOT NULL,
+ CONSTRAINT "FK_f47244225a6a1eac04a3463dd90" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_connected_accounts"(
+ "id",
+ "user_id",
+ "access_token",
+ "friend_sync",
+ "name",
+ "revoked",
+ "show_activity",
+ "type",
+ "verified",
+ "visibility"
+ )
+ SELECT "id",
+ "user_id",
+ "access_token",
+ "friend_sync",
+ "name",
+ "revoked",
+ "show_activity",
+ "type",
+ "verified",
+ "visibility"
+ FROM "connected_accounts"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "connected_accounts"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_connected_accounts"
+ RENAME TO "connected_accounts"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_backup_codes" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "code" varchar NOT NULL,
+ "consumed" boolean NOT NULL,
+ "expired" boolean NOT NULL,
+ "user_id" varchar,
+ CONSTRAINT "FK_70066ea80d2f4b871beda32633b" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_backup_codes"("id", "code", "consumed", "expired", "user_id")
+ SELECT "id",
+ "code",
+ "consumed",
+ "expired",
+ "user_id"
+ FROM "backup_codes"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "backup_codes"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_backup_codes"
+ RENAME TO "backup_codes"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_bans" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "guild_id" varchar,
+ "executor_id" varchar,
+ "ip" varchar NOT NULL,
+ "reason" varchar,
+ CONSTRAINT "FK_5999e8e449f80a236ff72023559" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_9d3ab7dd180ebdd245cdb66ecad" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_07ad88c86d1f290d46748410d58" FOREIGN KEY ("executor_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_bans"(
+ "id",
+ "user_id",
+ "guild_id",
+ "executor_id",
+ "ip",
+ "reason"
+ )
+ SELECT "id",
+ "user_id",
+ "guild_id",
+ "executor_id",
+ "ip",
+ "reason"
+ FROM "bans"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "bans"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_bans"
+ RENAME TO "bans"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_recipients" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "channel_id" varchar NOT NULL,
+ "user_id" varchar NOT NULL,
+ "closed" boolean NOT NULL DEFAULT (0),
+ CONSTRAINT "FK_2f18ee1ba667f233ae86c0ea60e" FOREIGN KEY ("channel_id") REFERENCES "channels" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_6157e8b6ba4e6e3089616481fe2" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_recipients"("id", "channel_id", "user_id", "closed")
+ SELECT "id",
+ "channel_id",
+ "user_id",
+ "closed"
+ FROM "recipients"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "recipients"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_recipients"
+ RENAME TO "recipients"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_roles" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "guild_id" varchar,
+ "color" integer NOT NULL,
+ "hoist" boolean NOT NULL,
+ "managed" boolean NOT NULL,
+ "mentionable" boolean NOT NULL,
+ "name" varchar NOT NULL,
+ "permissions" varchar NOT NULL,
+ "position" integer NOT NULL,
+ "icon" varchar,
+ "unicode_emoji" varchar,
+ "tags" text,
+ CONSTRAINT "FK_c32c1ab1c4dc7dcb0278c4b1b8b" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_roles"(
+ "id",
+ "guild_id",
+ "color",
+ "hoist",
+ "managed",
+ "mentionable",
+ "name",
+ "permissions",
+ "position",
+ "icon",
+ "unicode_emoji",
+ "tags"
+ )
+ SELECT "id",
+ "guild_id",
+ "color",
+ "hoist",
+ "managed",
+ "mentionable",
+ "name",
+ "permissions",
+ "position",
+ "icon",
+ "unicode_emoji",
+ "tags"
+ FROM "roles"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "roles"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_roles"
+ RENAME TO "roles"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_bb2bf9386ac443afbbbf9f12d3"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_members" (
+ "index" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
+ "id" varchar NOT NULL,
+ "guild_id" varchar NOT NULL,
+ "nick" varchar,
+ "joined_at" datetime NOT NULL,
+ "premium_since" bigint,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "pending" boolean NOT NULL,
+ "settings" text NOT NULL,
+ "last_message_id" varchar,
+ "joined_by" varchar,
+ CONSTRAINT "FK_28b53062261b996d9c99fa12404" FOREIGN KEY ("id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_16aceddd5b89825b8ed6029ad1c" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_members"(
+ "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ )
+ SELECT "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ FROM "members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "members"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_members"
+ RENAME TO "members"
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_bb2bf9386ac443afbbbf9f12d3" ON "members" ("id", "guild_id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_webhooks" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "type" integer NOT NULL,
+ "name" varchar,
+ "avatar" varchar,
+ "token" varchar,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "application_id" varchar,
+ "user_id" varchar,
+ "source_guild_id" varchar,
+ CONSTRAINT "FK_487a7af59d189f744fe394368fc" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_df528cf77e82f8032230e7e37d8" FOREIGN KEY ("channel_id") REFERENCES "channels" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_c3e5305461931763b56aa905f1c" FOREIGN KEY ("application_id") REFERENCES "applications" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_0d523f6f997c86e052c49b1455f" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_3a285f4f49c40e0706d3018bc9f" FOREIGN KEY ("source_guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_webhooks"(
+ "id",
+ "type",
+ "name",
+ "avatar",
+ "token",
+ "guild_id",
+ "channel_id",
+ "application_id",
+ "user_id",
+ "source_guild_id"
+ )
+ SELECT "id",
+ "type",
+ "name",
+ "avatar",
+ "token",
+ "guild_id",
+ "channel_id",
+ "application_id",
+ "user_id",
+ "source_guild_id"
+ FROM "webhooks"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "webhooks"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_webhooks"
+ RENAME TO "webhooks"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_stickers" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "description" varchar,
+ "available" boolean,
+ "tags" varchar,
+ "pack_id" varchar,
+ "guild_id" varchar,
+ "user_id" varchar,
+ "type" integer NOT NULL,
+ "format_type" integer NOT NULL,
+ CONSTRAINT "FK_e7cfa5cefa6661b3fb8fda8ce69" FOREIGN KEY ("pack_id") REFERENCES "sticker_packs" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_193d551d852aca5347ef5c9f205" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_8f4ee73f2bb2325ff980502e158" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_stickers"(
+ "id",
+ "name",
+ "description",
+ "available",
+ "tags",
+ "pack_id",
+ "guild_id",
+ "user_id",
+ "type",
+ "format_type"
+ )
+ SELECT "id",
+ "name",
+ "description",
+ "available",
+ "tags",
+ "pack_id",
+ "guild_id",
+ "user_id",
+ "type",
+ "format_type"
+ FROM "stickers"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "stickers"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_stickers"
+ RENAME TO "stickers"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_attachments" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "filename" varchar NOT NULL,
+ "size" integer NOT NULL,
+ "url" varchar NOT NULL,
+ "proxy_url" varchar NOT NULL,
+ "height" integer,
+ "width" integer,
+ "content_type" varchar,
+ "message_id" varchar,
+ CONSTRAINT "FK_623e10eec51ada466c5038979e3" FOREIGN KEY ("message_id") REFERENCES "messages" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_attachments"(
+ "id",
+ "filename",
+ "size",
+ "url",
+ "proxy_url",
+ "height",
+ "width",
+ "content_type",
+ "message_id"
+ )
+ SELECT "id",
+ "filename",
+ "size",
+ "url",
+ "proxy_url",
+ "height",
+ "width",
+ "content_type",
+ "message_id"
+ FROM "attachments"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "attachments"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_attachments"
+ RENAME TO "attachments"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_86b9109b155eb70c0a2ca3b4b6"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_05535bc695e9f7ee104616459d"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_3ed7a60fb7dbe04e1ba9332a8b"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_messages" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "channel_id" varchar,
+ "guild_id" varchar,
+ "author_id" varchar,
+ "member_id" varchar,
+ "webhook_id" varchar,
+ "application_id" varchar,
+ "content" varchar,
+ "timestamp" datetime NOT NULL DEFAULT (datetime('now')),
+ "edited_timestamp" datetime,
+ "tts" boolean,
+ "mention_everyone" boolean,
+ "embeds" text NOT NULL,
+ "reactions" text NOT NULL,
+ "nonce" text,
+ "pinned" boolean,
+ "type" integer NOT NULL,
+ "activity" text,
+ "flags" varchar,
+ "message_reference" text,
+ "interaction" text,
+ "components" text,
+ "message_reference_id" varchar,
+ CONSTRAINT "FK_86b9109b155eb70c0a2ca3b4b6d" FOREIGN KEY ("channel_id") REFERENCES "channels" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_b193588441b085352a4c0109423" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_05535bc695e9f7ee104616459d3" FOREIGN KEY ("author_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_b0525304f2262b7014245351c76" FOREIGN KEY ("member_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_f83c04bcf1df4e5c0e7a52ed348" FOREIGN KEY ("webhook_id") REFERENCES "webhooks" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_5d3ec1cb962de6488637fd779d6" FOREIGN KEY ("application_id") REFERENCES "applications" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_61a92bb65b302a76d9c1fcd3174" FOREIGN KEY ("message_reference_id") REFERENCES "messages" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_messages"(
+ "id",
+ "channel_id",
+ "guild_id",
+ "author_id",
+ "member_id",
+ "webhook_id",
+ "application_id",
+ "content",
+ "timestamp",
+ "edited_timestamp",
+ "tts",
+ "mention_everyone",
+ "embeds",
+ "reactions",
+ "nonce",
+ "pinned",
+ "type",
+ "activity",
+ "flags",
+ "message_reference",
+ "interaction",
+ "components",
+ "message_reference_id"
+ )
+ SELECT "id",
+ "channel_id",
+ "guild_id",
+ "author_id",
+ "member_id",
+ "webhook_id",
+ "application_id",
+ "content",
+ "timestamp",
+ "edited_timestamp",
+ "tts",
+ "mention_everyone",
+ "embeds",
+ "reactions",
+ "nonce",
+ "pinned",
+ "type",
+ "activity",
+ "flags",
+ "message_reference",
+ "interaction",
+ "components",
+ "message_reference_id"
+ FROM "messages"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "messages"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_messages"
+ RENAME TO "messages"
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_86b9109b155eb70c0a2ca3b4b6" ON "messages" ("channel_id")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_05535bc695e9f7ee104616459d" ON "messages" ("author_id")
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_3ed7a60fb7dbe04e1ba9332a8b" ON "messages" ("channel_id", "id")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_0abf8b443321bd3cf7f81ee17a"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_read_states" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "channel_id" varchar NOT NULL,
+ "user_id" varchar NOT NULL,
+ "last_message_id" varchar,
+ "public_ack" varchar,
+ "notifications_cursor" varchar,
+ "last_pin_timestamp" datetime,
+ "mention_count" integer,
+ CONSTRAINT "FK_40da2fca4e0eaf7a23b5bfc5d34" FOREIGN KEY ("channel_id") REFERENCES "channels" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_195f92e4dd1254a4e348c043763" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_read_states"(
+ "id",
+ "channel_id",
+ "user_id",
+ "last_message_id",
+ "public_ack",
+ "notifications_cursor",
+ "last_pin_timestamp",
+ "mention_count"
+ )
+ SELECT "id",
+ "channel_id",
+ "user_id",
+ "last_message_id",
+ "public_ack",
+ "notifications_cursor",
+ "last_pin_timestamp",
+ "mention_count"
+ FROM "read_states"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "read_states"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_read_states"
+ RENAME TO "read_states"
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_0abf8b443321bd3cf7f81ee17a" ON "read_states" ("channel_id", "user_id")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_invites" (
+ "code" varchar PRIMARY KEY NOT NULL,
+ "temporary" boolean NOT NULL,
+ "uses" integer NOT NULL,
+ "max_uses" integer NOT NULL,
+ "max_age" integer NOT NULL,
+ "created_at" datetime NOT NULL,
+ "expires_at" datetime NOT NULL,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "inviter_id" varchar,
+ "target_user_id" varchar,
+ "target_user_type" integer,
+ "vanity_url" boolean,
+ CONSTRAINT "FK_3f4939aa1461e8af57fea3fb05d" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_6a15b051fe5050aa00a4b9ff0f6" FOREIGN KEY ("channel_id") REFERENCES "channels" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_15c35422032e0b22b4ada95f48f" FOREIGN KEY ("inviter_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_11a0d394f8fc649c19ce5f16b59" FOREIGN KEY ("target_user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_invites"(
+ "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ )
+ SELECT "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ FROM "invites"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "invites"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_invites"
+ RENAME TO "invites"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_voice_states" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "user_id" varchar,
+ "session_id" varchar NOT NULL,
+ "token" varchar,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "self_deaf" boolean NOT NULL,
+ "self_mute" boolean NOT NULL,
+ "self_stream" boolean,
+ "self_video" boolean NOT NULL,
+ "suppress" boolean NOT NULL,
+ "request_to_speak_timestamp" datetime,
+ CONSTRAINT "FK_03779ef216d4b0358470d9cb748" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_9f8d389866b40b6657edd026dd4" FOREIGN KEY ("channel_id") REFERENCES "channels" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_5fe1d5f931a67e85039c640001b" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_voice_states"(
+ "id",
+ "guild_id",
+ "channel_id",
+ "user_id",
+ "session_id",
+ "token",
+ "deaf",
+ "mute",
+ "self_deaf",
+ "self_mute",
+ "self_stream",
+ "self_video",
+ "suppress",
+ "request_to_speak_timestamp"
+ )
+ SELECT "id",
+ "guild_id",
+ "channel_id",
+ "user_id",
+ "session_id",
+ "token",
+ "deaf",
+ "mute",
+ "self_deaf",
+ "self_mute",
+ "self_stream",
+ "self_video",
+ "suppress",
+ "request_to_speak_timestamp"
+ FROM "voice_states"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "voice_states"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_voice_states"
+ RENAME TO "voice_states"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_channels" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "created_at" datetime NOT NULL,
+ "name" varchar,
+ "icon" text,
+ "type" integer NOT NULL,
+ "last_message_id" varchar,
+ "guild_id" varchar,
+ "parent_id" varchar,
+ "owner_id" varchar,
+ "last_pin_timestamp" integer,
+ "default_auto_archive_duration" integer,
+ "position" integer,
+ "permission_overwrites" text,
+ "video_quality_mode" integer,
+ "bitrate" integer,
+ "user_limit" integer,
+ "nsfw" boolean,
+ "rate_limit_per_user" integer,
+ "topic" varchar,
+ "retention_policy_id" varchar,
+ CONSTRAINT "FK_c253dafe5f3a03ec00cd8fb4581" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_3274522d14af40540b1a883fc80" FOREIGN KEY ("parent_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_3873ed438575cce703ecff4fc7b" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_channels"(
+ "id",
+ "created_at",
+ "name",
+ "icon",
+ "type",
+ "last_message_id",
+ "guild_id",
+ "parent_id",
+ "owner_id",
+ "last_pin_timestamp",
+ "default_auto_archive_duration",
+ "position",
+ "permission_overwrites",
+ "video_quality_mode",
+ "bitrate",
+ "user_limit",
+ "nsfw",
+ "rate_limit_per_user",
+ "topic",
+ "retention_policy_id"
+ )
+ SELECT "id",
+ "created_at",
+ "name",
+ "icon",
+ "type",
+ "last_message_id",
+ "guild_id",
+ "parent_id",
+ "owner_id",
+ "last_pin_timestamp",
+ "default_auto_archive_duration",
+ "position",
+ "permission_overwrites",
+ "video_quality_mode",
+ "bitrate",
+ "user_limit",
+ "nsfw",
+ "rate_limit_per_user",
+ "topic",
+ "retention_policy_id"
+ FROM "channels"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "channels"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_channels"
+ RENAME TO "channels"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_emojis" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "animated" boolean NOT NULL,
+ "available" boolean NOT NULL,
+ "guild_id" varchar NOT NULL,
+ "user_id" varchar,
+ "managed" boolean NOT NULL,
+ "name" varchar NOT NULL,
+ "require_colons" boolean NOT NULL,
+ "roles" text NOT NULL,
+ "groups" text,
+ CONSTRAINT "FK_4b988e0db89d94cebcf07f598cc" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_fa7ddd5f9a214e28ce596548421" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_emojis"(
+ "id",
+ "animated",
+ "available",
+ "guild_id",
+ "user_id",
+ "managed",
+ "name",
+ "require_colons",
+ "roles",
+ "groups"
+ )
+ SELECT "id",
+ "animated",
+ "available",
+ "guild_id",
+ "user_id",
+ "managed",
+ "name",
+ "require_colons",
+ "roles",
+ "groups"
+ FROM "emojis"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "emojis"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_emojis"
+ RENAME TO "emojis"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_templates" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "code" varchar NOT NULL,
+ "name" varchar NOT NULL,
+ "description" varchar,
+ "usage_count" integer,
+ "creator_id" varchar,
+ "created_at" datetime NOT NULL,
+ "updated_at" datetime NOT NULL,
+ "source_guild_id" varchar,
+ "serialized_source_guild" text NOT NULL,
+ CONSTRAINT "UQ_be38737bf339baf63b1daeffb55" UNIQUE ("code"),
+ CONSTRAINT "FK_d7374b7f8f5fbfdececa4fb62e1" FOREIGN KEY ("creator_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_445d00eaaea0e60a017a5ed0c11" FOREIGN KEY ("source_guild_id") REFERENCES "guilds" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_templates"(
+ "id",
+ "code",
+ "name",
+ "description",
+ "usage_count",
+ "creator_id",
+ "created_at",
+ "updated_at",
+ "source_guild_id",
+ "serialized_source_guild"
+ )
+ SELECT "id",
+ "code",
+ "name",
+ "description",
+ "usage_count",
+ "creator_id",
+ "created_at",
+ "updated_at",
+ "source_guild_id",
+ "serialized_source_guild"
+ FROM "templates"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "templates"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_templates"
+ RENAME TO "templates"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_guilds" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "afk_channel_id" varchar,
+ "afk_timeout" integer,
+ "banner" varchar,
+ "default_message_notifications" integer,
+ "description" varchar,
+ "discovery_splash" varchar,
+ "explicit_content_filter" integer,
+ "features" text NOT NULL,
+ "primary_category_id" integer,
+ "icon" varchar,
+ "large" boolean,
+ "max_members" integer,
+ "max_presences" integer,
+ "max_video_channel_users" integer,
+ "member_count" integer,
+ "presence_count" integer,
+ "template_id" varchar,
+ "mfa_level" integer,
+ "name" varchar NOT NULL,
+ "owner_id" varchar,
+ "preferred_locale" varchar,
+ "premium_subscription_count" integer,
+ "premium_tier" integer,
+ "public_updates_channel_id" varchar,
+ "rules_channel_id" varchar,
+ "region" varchar,
+ "splash" varchar,
+ "system_channel_id" varchar,
+ "system_channel_flags" integer,
+ "unavailable" boolean,
+ "verification_level" integer,
+ "welcome_screen" text NOT NULL,
+ "widget_channel_id" varchar,
+ "widget_enabled" boolean,
+ "nsfw_level" integer,
+ "nsfw" boolean,
+ "parent" varchar,
+ CONSTRAINT "FK_f591a66b8019d87b0fe6c12dad6" FOREIGN KEY ("afk_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e2a2f873a64a5cf62526de42325" FOREIGN KEY ("template_id") REFERENCES "templates" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_fc1a451727e3643ca572a3bb394" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_8d450b016dc8bec35f36729e4b0" FOREIGN KEY ("public_updates_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_95828668aa333460582e0ca6396" FOREIGN KEY ("rules_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_cfc3d3ad260f8121c95b31a1fce" FOREIGN KEY ("system_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_9d1d665379eefde7876a17afa99" FOREIGN KEY ("widget_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_guilds"(
+ "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent"
+ )
+ SELECT "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent"
+ FROM "guilds"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "guilds"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_guilds"
+ RENAME TO "guilds"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_team_members" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "membership_state" integer NOT NULL,
+ "permissions" text NOT NULL,
+ "team_id" varchar,
+ "user_id" varchar,
+ CONSTRAINT "FK_fdad7d5768277e60c40e01cdcea" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_c2bf4967c8c2a6b845dadfbf3d4" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_team_members"(
+ "id",
+ "membership_state",
+ "permissions",
+ "team_id",
+ "user_id"
+ )
+ SELECT "id",
+ "membership_state",
+ "permissions",
+ "team_id",
+ "user_id"
+ FROM "team_members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "team_members"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_team_members"
+ RENAME TO "team_members"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_teams" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "icon" varchar,
+ "name" varchar NOT NULL,
+ "owner_user_id" varchar,
+ CONSTRAINT "FK_13f00abf7cb6096c43ecaf8c108" FOREIGN KEY ("owner_user_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_teams"("id", "icon", "name", "owner_user_id")
+ SELECT "id",
+ "icon",
+ "name",
+ "owner_user_id"
+ FROM "teams"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "teams"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_teams"
+ RENAME TO "teams"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "rpc_origins" text,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "primary_sku_id" varchar,
+ "slug" varchar,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "guild_id" varchar,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e5bf78cdbbe9ba91062d74c5aba" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ FROM "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_applications"
+ RENAME TO "applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_audit_logs" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "action_type" integer NOT NULL,
+ "options" text,
+ "changes" text NOT NULL,
+ "reason" varchar,
+ "target_id" varchar,
+ CONSTRAINT "FK_3cd01cd3ae7aab010310d96ac8e" FOREIGN KEY ("target_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_bd2726fd31b35443f2245b93ba0" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_audit_logs"(
+ "id",
+ "user_id",
+ "action_type",
+ "options",
+ "changes",
+ "reason",
+ "target_id"
+ )
+ SELECT "id",
+ "user_id",
+ "action_type",
+ "options",
+ "changes",
+ "reason",
+ "target_id"
+ FROM "audit_logs"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "audit_logs"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_audit_logs"
+ RENAME TO "audit_logs"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_sessions" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "session_id" varchar NOT NULL,
+ "activities" text,
+ "client_info" text NOT NULL,
+ "status" varchar NOT NULL,
+ CONSTRAINT "FK_085d540d9f418cfbdc7bd55bb19" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_sessions"(
+ "id",
+ "user_id",
+ "session_id",
+ "activities",
+ "client_info",
+ "status"
+ )
+ SELECT "id",
+ "user_id",
+ "session_id",
+ "activities",
+ "client_info",
+ "status"
+ FROM "sessions"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "sessions"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_sessions"
+ RENAME TO "sessions"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_sticker_packs" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "description" varchar,
+ "banner_asset_id" varchar,
+ "cover_sticker_id" varchar,
+ "coverStickerId" varchar,
+ CONSTRAINT "FK_448fafba4355ee1c837bbc865f1" FOREIGN KEY ("coverStickerId") REFERENCES "stickers" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_sticker_packs"(
+ "id",
+ "name",
+ "description",
+ "banner_asset_id",
+ "cover_sticker_id",
+ "coverStickerId"
+ )
+ SELECT "id",
+ "name",
+ "description",
+ "banner_asset_id",
+ "cover_sticker_id",
+ "coverStickerId"
+ FROM "sticker_packs"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "sticker_packs"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_sticker_packs"
+ RENAME TO "sticker_packs"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_notes" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "content" varchar NOT NULL,
+ "owner_id" varchar,
+ "target_id" varchar,
+ CONSTRAINT "UQ_74e6689b9568cc965b8bfc9150b" UNIQUE ("owner_id", "target_id"),
+ CONSTRAINT "FK_f9e103f8ae67cb1787063597925" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_23e08e5b4481711d573e1abecdc" FOREIGN KEY ("target_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_notes"("id", "content", "owner_id", "target_id")
+ SELECT "id",
+ "content",
+ "owner_id",
+ "target_id"
+ FROM "notes"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "notes"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_notes"
+ RENAME TO "notes"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_5d7ddc8a5f9c167f548625e772"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_e9080e7a7997a0170026d5139c"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_member_roles" (
+ "index" integer NOT NULL,
+ "role_id" varchar NOT NULL,
+ CONSTRAINT "FK_5d7ddc8a5f9c167f548625e772e" FOREIGN KEY ("index") REFERENCES "members" ("index") ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT "FK_e9080e7a7997a0170026d5139c1" FOREIGN KEY ("role_id") REFERENCES "roles" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ PRIMARY KEY ("index", "role_id")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_member_roles"("index", "role_id")
+ SELECT "index",
+ "role_id"
+ FROM "member_roles"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "member_roles"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_member_roles"
+ RENAME TO "member_roles"
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_5d7ddc8a5f9c167f548625e772" ON "member_roles" ("index")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_e9080e7a7997a0170026d5139c" ON "member_roles" ("role_id")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_a343387fc560ef378760681c23"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_b831eb18ceebd28976239b1e2f"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_message_user_mentions" (
+ "messagesId" varchar NOT NULL,
+ "usersId" varchar NOT NULL,
+ CONSTRAINT "FK_a343387fc560ef378760681c236" FOREIGN KEY ("messagesId") REFERENCES "messages" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT "FK_b831eb18ceebd28976239b1e2f8" FOREIGN KEY ("usersId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ PRIMARY KEY ("messagesId", "usersId")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_message_user_mentions"("messagesId", "usersId")
+ SELECT "messagesId",
+ "usersId"
+ FROM "message_user_mentions"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_user_mentions"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_message_user_mentions"
+ RENAME TO "message_user_mentions"
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_a343387fc560ef378760681c23" ON "message_user_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_b831eb18ceebd28976239b1e2f" ON "message_user_mentions" ("usersId")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_a8242cf535337a490b0feaea0b"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_29d63eb1a458200851bc37d074"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_message_role_mentions" (
+ "messagesId" varchar NOT NULL,
+ "rolesId" varchar NOT NULL,
+ CONSTRAINT "FK_a8242cf535337a490b0feaea0b4" FOREIGN KEY ("messagesId") REFERENCES "messages" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT "FK_29d63eb1a458200851bc37d074b" FOREIGN KEY ("rolesId") REFERENCES "roles" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ PRIMARY KEY ("messagesId", "rolesId")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_message_role_mentions"("messagesId", "rolesId")
+ SELECT "messagesId",
+ "rolesId"
+ FROM "message_role_mentions"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_role_mentions"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_message_role_mentions"
+ RENAME TO "message_role_mentions"
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_a8242cf535337a490b0feaea0b" ON "message_role_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_29d63eb1a458200851bc37d074" ON "message_role_mentions" ("rolesId")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_2a27102ecd1d81b4582a436092"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_bdb8c09e1464cabf62105bf4b9"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_message_channel_mentions" (
+ "messagesId" varchar NOT NULL,
+ "channelsId" varchar NOT NULL,
+ CONSTRAINT "FK_2a27102ecd1d81b4582a4360921" FOREIGN KEY ("messagesId") REFERENCES "messages" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT "FK_bdb8c09e1464cabf62105bf4b9d" FOREIGN KEY ("channelsId") REFERENCES "channels" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ PRIMARY KEY ("messagesId", "channelsId")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_message_channel_mentions"("messagesId", "channelsId")
+ SELECT "messagesId",
+ "channelsId"
+ FROM "message_channel_mentions"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_channel_mentions"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_message_channel_mentions"
+ RENAME TO "message_channel_mentions"
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_2a27102ecd1d81b4582a436092" ON "message_channel_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_bdb8c09e1464cabf62105bf4b9" ON "message_channel_mentions" ("channelsId")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_40bb6f23e7cc133292e92829d2"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_e22a70819d07659c7a71c112a1"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_message_stickers" (
+ "messagesId" varchar NOT NULL,
+ "stickersId" varchar NOT NULL,
+ CONSTRAINT "FK_40bb6f23e7cc133292e92829d28" FOREIGN KEY ("messagesId") REFERENCES "messages" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT "FK_e22a70819d07659c7a71c112a1f" FOREIGN KEY ("stickersId") REFERENCES "stickers" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ PRIMARY KEY ("messagesId", "stickersId")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_message_stickers"("messagesId", "stickersId")
+ SELECT "messagesId",
+ "stickersId"
+ FROM "message_stickers"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_stickers"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_message_stickers"
+ RENAME TO "message_stickers"
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_40bb6f23e7cc133292e92829d2" ON "message_stickers" ("messagesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_e22a70819d07659c7a71c112a1" ON "message_stickers" ("stickersId")
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "query-result-cache" (
+ "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
+ "identifier" varchar,
+ "time" bigint NOT NULL,
+ "duration" integer NOT NULL,
+ "query" text NOT NULL,
+ "result" text NOT NULL
+ )
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ DROP TABLE "query-result-cache"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_e22a70819d07659c7a71c112a1"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_40bb6f23e7cc133292e92829d2"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_stickers"
+ RENAME TO "temporary_message_stickers"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_stickers" (
+ "messagesId" varchar NOT NULL,
+ "stickersId" varchar NOT NULL,
+ PRIMARY KEY ("messagesId", "stickersId")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "message_stickers"("messagesId", "stickersId")
+ SELECT "messagesId",
+ "stickersId"
+ FROM "temporary_message_stickers"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_message_stickers"
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_e22a70819d07659c7a71c112a1" ON "message_stickers" ("stickersId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_40bb6f23e7cc133292e92829d2" ON "message_stickers" ("messagesId")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_bdb8c09e1464cabf62105bf4b9"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_2a27102ecd1d81b4582a436092"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_channel_mentions"
+ RENAME TO "temporary_message_channel_mentions"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_channel_mentions" (
+ "messagesId" varchar NOT NULL,
+ "channelsId" varchar NOT NULL,
+ PRIMARY KEY ("messagesId", "channelsId")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "message_channel_mentions"("messagesId", "channelsId")
+ SELECT "messagesId",
+ "channelsId"
+ FROM "temporary_message_channel_mentions"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_message_channel_mentions"
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_bdb8c09e1464cabf62105bf4b9" ON "message_channel_mentions" ("channelsId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_2a27102ecd1d81b4582a436092" ON "message_channel_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_29d63eb1a458200851bc37d074"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_a8242cf535337a490b0feaea0b"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_role_mentions"
+ RENAME TO "temporary_message_role_mentions"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_role_mentions" (
+ "messagesId" varchar NOT NULL,
+ "rolesId" varchar NOT NULL,
+ PRIMARY KEY ("messagesId", "rolesId")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "message_role_mentions"("messagesId", "rolesId")
+ SELECT "messagesId",
+ "rolesId"
+ FROM "temporary_message_role_mentions"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_message_role_mentions"
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_29d63eb1a458200851bc37d074" ON "message_role_mentions" ("rolesId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_a8242cf535337a490b0feaea0b" ON "message_role_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_b831eb18ceebd28976239b1e2f"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_a343387fc560ef378760681c23"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "message_user_mentions"
+ RENAME TO "temporary_message_user_mentions"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "message_user_mentions" (
+ "messagesId" varchar NOT NULL,
+ "usersId" varchar NOT NULL,
+ PRIMARY KEY ("messagesId", "usersId")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "message_user_mentions"("messagesId", "usersId")
+ SELECT "messagesId",
+ "usersId"
+ FROM "temporary_message_user_mentions"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_message_user_mentions"
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_b831eb18ceebd28976239b1e2f" ON "message_user_mentions" ("usersId")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_a343387fc560ef378760681c23" ON "message_user_mentions" ("messagesId")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_e9080e7a7997a0170026d5139c"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_5d7ddc8a5f9c167f548625e772"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "member_roles"
+ RENAME TO "temporary_member_roles"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "member_roles" (
+ "index" integer NOT NULL,
+ "role_id" varchar NOT NULL,
+ PRIMARY KEY ("index", "role_id")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "member_roles"("index", "role_id")
+ SELECT "index",
+ "role_id"
+ FROM "temporary_member_roles"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_member_roles"
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_e9080e7a7997a0170026d5139c" ON "member_roles" ("role_id")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_5d7ddc8a5f9c167f548625e772" ON "member_roles" ("index")
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "notes"
+ RENAME TO "temporary_notes"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "notes" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "content" varchar NOT NULL,
+ "owner_id" varchar,
+ "target_id" varchar,
+ CONSTRAINT "UQ_74e6689b9568cc965b8bfc9150b" UNIQUE ("owner_id", "target_id")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "notes"("id", "content", "owner_id", "target_id")
+ SELECT "id",
+ "content",
+ "owner_id",
+ "target_id"
+ FROM "temporary_notes"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_notes"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "sticker_packs"
+ RENAME TO "temporary_sticker_packs"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "sticker_packs" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "description" varchar,
+ "banner_asset_id" varchar,
+ "cover_sticker_id" varchar,
+ "coverStickerId" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "sticker_packs"(
+ "id",
+ "name",
+ "description",
+ "banner_asset_id",
+ "cover_sticker_id",
+ "coverStickerId"
+ )
+ SELECT "id",
+ "name",
+ "description",
+ "banner_asset_id",
+ "cover_sticker_id",
+ "coverStickerId"
+ FROM "temporary_sticker_packs"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_sticker_packs"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "sessions"
+ RENAME TO "temporary_sessions"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "sessions" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "session_id" varchar NOT NULL,
+ "activities" text,
+ "client_info" text NOT NULL,
+ "status" varchar NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "sessions"(
+ "id",
+ "user_id",
+ "session_id",
+ "activities",
+ "client_info",
+ "status"
+ )
+ SELECT "id",
+ "user_id",
+ "session_id",
+ "activities",
+ "client_info",
+ "status"
+ FROM "temporary_sessions"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_sessions"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "audit_logs"
+ RENAME TO "temporary_audit_logs"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "audit_logs" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "action_type" integer NOT NULL,
+ "options" text,
+ "changes" text NOT NULL,
+ "reason" varchar,
+ "target_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "audit_logs"(
+ "id",
+ "user_id",
+ "action_type",
+ "options",
+ "changes",
+ "reason",
+ "target_id"
+ )
+ SELECT "id",
+ "user_id",
+ "action_type",
+ "options",
+ "changes",
+ "reason",
+ "target_id"
+ FROM "temporary_audit_logs"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_audit_logs"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ RENAME TO "temporary_applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "rpc_origins" text,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "primary_sku_id" varchar,
+ "slug" varchar,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "guild_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ FROM "temporary_applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "teams"
+ RENAME TO "temporary_teams"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "teams" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "icon" varchar,
+ "name" varchar NOT NULL,
+ "owner_user_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "teams"("id", "icon", "name", "owner_user_id")
+ SELECT "id",
+ "icon",
+ "name",
+ "owner_user_id"
+ FROM "temporary_teams"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_teams"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "team_members"
+ RENAME TO "temporary_team_members"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "team_members" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "membership_state" integer NOT NULL,
+ "permissions" text NOT NULL,
+ "team_id" varchar,
+ "user_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "team_members"(
+ "id",
+ "membership_state",
+ "permissions",
+ "team_id",
+ "user_id"
+ )
+ SELECT "id",
+ "membership_state",
+ "permissions",
+ "team_id",
+ "user_id"
+ FROM "temporary_team_members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_team_members"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ RENAME TO "temporary_guilds"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "guilds" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "afk_channel_id" varchar,
+ "afk_timeout" integer,
+ "banner" varchar,
+ "default_message_notifications" integer,
+ "description" varchar,
+ "discovery_splash" varchar,
+ "explicit_content_filter" integer,
+ "features" text NOT NULL,
+ "primary_category_id" integer,
+ "icon" varchar,
+ "large" boolean,
+ "max_members" integer,
+ "max_presences" integer,
+ "max_video_channel_users" integer,
+ "member_count" integer,
+ "presence_count" integer,
+ "template_id" varchar,
+ "mfa_level" integer,
+ "name" varchar NOT NULL,
+ "owner_id" varchar,
+ "preferred_locale" varchar,
+ "premium_subscription_count" integer,
+ "premium_tier" integer,
+ "public_updates_channel_id" varchar,
+ "rules_channel_id" varchar,
+ "region" varchar,
+ "splash" varchar,
+ "system_channel_id" varchar,
+ "system_channel_flags" integer,
+ "unavailable" boolean,
+ "verification_level" integer,
+ "welcome_screen" text NOT NULL,
+ "widget_channel_id" varchar,
+ "widget_enabled" boolean,
+ "nsfw_level" integer,
+ "nsfw" boolean,
+ "parent" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "guilds"(
+ "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent"
+ )
+ SELECT "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent"
+ FROM "temporary_guilds"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_guilds"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "templates"
+ RENAME TO "temporary_templates"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "templates" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "code" varchar NOT NULL,
+ "name" varchar NOT NULL,
+ "description" varchar,
+ "usage_count" integer,
+ "creator_id" varchar,
+ "created_at" datetime NOT NULL,
+ "updated_at" datetime NOT NULL,
+ "source_guild_id" varchar,
+ "serialized_source_guild" text NOT NULL,
+ CONSTRAINT "UQ_be38737bf339baf63b1daeffb55" UNIQUE ("code")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "templates"(
+ "id",
+ "code",
+ "name",
+ "description",
+ "usage_count",
+ "creator_id",
+ "created_at",
+ "updated_at",
+ "source_guild_id",
+ "serialized_source_guild"
+ )
+ SELECT "id",
+ "code",
+ "name",
+ "description",
+ "usage_count",
+ "creator_id",
+ "created_at",
+ "updated_at",
+ "source_guild_id",
+ "serialized_source_guild"
+ FROM "temporary_templates"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_templates"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "emojis"
+ RENAME TO "temporary_emojis"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "emojis" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "animated" boolean NOT NULL,
+ "available" boolean NOT NULL,
+ "guild_id" varchar NOT NULL,
+ "user_id" varchar,
+ "managed" boolean NOT NULL,
+ "name" varchar NOT NULL,
+ "require_colons" boolean NOT NULL,
+ "roles" text NOT NULL,
+ "groups" text
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "emojis"(
+ "id",
+ "animated",
+ "available",
+ "guild_id",
+ "user_id",
+ "managed",
+ "name",
+ "require_colons",
+ "roles",
+ "groups"
+ )
+ SELECT "id",
+ "animated",
+ "available",
+ "guild_id",
+ "user_id",
+ "managed",
+ "name",
+ "require_colons",
+ "roles",
+ "groups"
+ FROM "temporary_emojis"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_emojis"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "channels"
+ RENAME TO "temporary_channels"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "channels" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "created_at" datetime NOT NULL,
+ "name" varchar,
+ "icon" text,
+ "type" integer NOT NULL,
+ "last_message_id" varchar,
+ "guild_id" varchar,
+ "parent_id" varchar,
+ "owner_id" varchar,
+ "last_pin_timestamp" integer,
+ "default_auto_archive_duration" integer,
+ "position" integer,
+ "permission_overwrites" text,
+ "video_quality_mode" integer,
+ "bitrate" integer,
+ "user_limit" integer,
+ "nsfw" boolean,
+ "rate_limit_per_user" integer,
+ "topic" varchar,
+ "retention_policy_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "channels"(
+ "id",
+ "created_at",
+ "name",
+ "icon",
+ "type",
+ "last_message_id",
+ "guild_id",
+ "parent_id",
+ "owner_id",
+ "last_pin_timestamp",
+ "default_auto_archive_duration",
+ "position",
+ "permission_overwrites",
+ "video_quality_mode",
+ "bitrate",
+ "user_limit",
+ "nsfw",
+ "rate_limit_per_user",
+ "topic",
+ "retention_policy_id"
+ )
+ SELECT "id",
+ "created_at",
+ "name",
+ "icon",
+ "type",
+ "last_message_id",
+ "guild_id",
+ "parent_id",
+ "owner_id",
+ "last_pin_timestamp",
+ "default_auto_archive_duration",
+ "position",
+ "permission_overwrites",
+ "video_quality_mode",
+ "bitrate",
+ "user_limit",
+ "nsfw",
+ "rate_limit_per_user",
+ "topic",
+ "retention_policy_id"
+ FROM "temporary_channels"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_channels"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "voice_states"
+ RENAME TO "temporary_voice_states"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "voice_states" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "user_id" varchar,
+ "session_id" varchar NOT NULL,
+ "token" varchar,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "self_deaf" boolean NOT NULL,
+ "self_mute" boolean NOT NULL,
+ "self_stream" boolean,
+ "self_video" boolean NOT NULL,
+ "suppress" boolean NOT NULL,
+ "request_to_speak_timestamp" datetime
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "voice_states"(
+ "id",
+ "guild_id",
+ "channel_id",
+ "user_id",
+ "session_id",
+ "token",
+ "deaf",
+ "mute",
+ "self_deaf",
+ "self_mute",
+ "self_stream",
+ "self_video",
+ "suppress",
+ "request_to_speak_timestamp"
+ )
+ SELECT "id",
+ "guild_id",
+ "channel_id",
+ "user_id",
+ "session_id",
+ "token",
+ "deaf",
+ "mute",
+ "self_deaf",
+ "self_mute",
+ "self_stream",
+ "self_video",
+ "suppress",
+ "request_to_speak_timestamp"
+ FROM "temporary_voice_states"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_voice_states"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites"
+ RENAME TO "temporary_invites"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "invites" (
+ "code" varchar PRIMARY KEY NOT NULL,
+ "temporary" boolean NOT NULL,
+ "uses" integer NOT NULL,
+ "max_uses" integer NOT NULL,
+ "max_age" integer NOT NULL,
+ "created_at" datetime NOT NULL,
+ "expires_at" datetime NOT NULL,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "inviter_id" varchar,
+ "target_user_id" varchar,
+ "target_user_type" integer,
+ "vanity_url" boolean
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "invites"(
+ "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ )
+ SELECT "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ FROM "temporary_invites"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_invites"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_0abf8b443321bd3cf7f81ee17a"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "read_states"
+ RENAME TO "temporary_read_states"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "read_states" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "channel_id" varchar NOT NULL,
+ "user_id" varchar NOT NULL,
+ "last_message_id" varchar,
+ "public_ack" varchar,
+ "notifications_cursor" varchar,
+ "last_pin_timestamp" datetime,
+ "mention_count" integer
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "read_states"(
+ "id",
+ "channel_id",
+ "user_id",
+ "last_message_id",
+ "public_ack",
+ "notifications_cursor",
+ "last_pin_timestamp",
+ "mention_count"
+ )
+ SELECT "id",
+ "channel_id",
+ "user_id",
+ "last_message_id",
+ "public_ack",
+ "notifications_cursor",
+ "last_pin_timestamp",
+ "mention_count"
+ FROM "temporary_read_states"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_read_states"
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_0abf8b443321bd3cf7f81ee17a" ON "read_states" ("channel_id", "user_id")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_3ed7a60fb7dbe04e1ba9332a8b"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_05535bc695e9f7ee104616459d"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_86b9109b155eb70c0a2ca3b4b6"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "messages"
+ RENAME TO "temporary_messages"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "messages" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "channel_id" varchar,
+ "guild_id" varchar,
+ "author_id" varchar,
+ "member_id" varchar,
+ "webhook_id" varchar,
+ "application_id" varchar,
+ "content" varchar,
+ "timestamp" datetime NOT NULL DEFAULT (datetime('now')),
+ "edited_timestamp" datetime,
+ "tts" boolean,
+ "mention_everyone" boolean,
+ "embeds" text NOT NULL,
+ "reactions" text NOT NULL,
+ "nonce" text,
+ "pinned" boolean,
+ "type" integer NOT NULL,
+ "activity" text,
+ "flags" varchar,
+ "message_reference" text,
+ "interaction" text,
+ "components" text,
+ "message_reference_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "messages"(
+ "id",
+ "channel_id",
+ "guild_id",
+ "author_id",
+ "member_id",
+ "webhook_id",
+ "application_id",
+ "content",
+ "timestamp",
+ "edited_timestamp",
+ "tts",
+ "mention_everyone",
+ "embeds",
+ "reactions",
+ "nonce",
+ "pinned",
+ "type",
+ "activity",
+ "flags",
+ "message_reference",
+ "interaction",
+ "components",
+ "message_reference_id"
+ )
+ SELECT "id",
+ "channel_id",
+ "guild_id",
+ "author_id",
+ "member_id",
+ "webhook_id",
+ "application_id",
+ "content",
+ "timestamp",
+ "edited_timestamp",
+ "tts",
+ "mention_everyone",
+ "embeds",
+ "reactions",
+ "nonce",
+ "pinned",
+ "type",
+ "activity",
+ "flags",
+ "message_reference",
+ "interaction",
+ "components",
+ "message_reference_id"
+ FROM "temporary_messages"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_messages"
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_3ed7a60fb7dbe04e1ba9332a8b" ON "messages" ("channel_id", "id")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_05535bc695e9f7ee104616459d" ON "messages" ("author_id")
+ `);
+ await queryRunner.query(`
+ CREATE INDEX "IDX_86b9109b155eb70c0a2ca3b4b6" ON "messages" ("channel_id")
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "attachments"
+ RENAME TO "temporary_attachments"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "attachments" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "filename" varchar NOT NULL,
+ "size" integer NOT NULL,
+ "url" varchar NOT NULL,
+ "proxy_url" varchar NOT NULL,
+ "height" integer,
+ "width" integer,
+ "content_type" varchar,
+ "message_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "attachments"(
+ "id",
+ "filename",
+ "size",
+ "url",
+ "proxy_url",
+ "height",
+ "width",
+ "content_type",
+ "message_id"
+ )
+ SELECT "id",
+ "filename",
+ "size",
+ "url",
+ "proxy_url",
+ "height",
+ "width",
+ "content_type",
+ "message_id"
+ FROM "temporary_attachments"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_attachments"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "stickers"
+ RENAME TO "temporary_stickers"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "stickers" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "description" varchar,
+ "available" boolean,
+ "tags" varchar,
+ "pack_id" varchar,
+ "guild_id" varchar,
+ "user_id" varchar,
+ "type" integer NOT NULL,
+ "format_type" integer NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "stickers"(
+ "id",
+ "name",
+ "description",
+ "available",
+ "tags",
+ "pack_id",
+ "guild_id",
+ "user_id",
+ "type",
+ "format_type"
+ )
+ SELECT "id",
+ "name",
+ "description",
+ "available",
+ "tags",
+ "pack_id",
+ "guild_id",
+ "user_id",
+ "type",
+ "format_type"
+ FROM "temporary_stickers"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_stickers"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "webhooks"
+ RENAME TO "temporary_webhooks"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "webhooks" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "type" integer NOT NULL,
+ "name" varchar,
+ "avatar" varchar,
+ "token" varchar,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "application_id" varchar,
+ "user_id" varchar,
+ "source_guild_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "webhooks"(
+ "id",
+ "type",
+ "name",
+ "avatar",
+ "token",
+ "guild_id",
+ "channel_id",
+ "application_id",
+ "user_id",
+ "source_guild_id"
+ )
+ SELECT "id",
+ "type",
+ "name",
+ "avatar",
+ "token",
+ "guild_id",
+ "channel_id",
+ "application_id",
+ "user_id",
+ "source_guild_id"
+ FROM "temporary_webhooks"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_webhooks"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_bb2bf9386ac443afbbbf9f12d3"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "members"
+ RENAME TO "temporary_members"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "members" (
+ "index" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
+ "id" varchar NOT NULL,
+ "guild_id" varchar NOT NULL,
+ "nick" varchar,
+ "joined_at" datetime NOT NULL,
+ "premium_since" bigint,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "pending" boolean NOT NULL,
+ "settings" text NOT NULL,
+ "last_message_id" varchar,
+ "joined_by" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "members"(
+ "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ )
+ SELECT "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ FROM "temporary_members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_members"
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_bb2bf9386ac443afbbbf9f12d3" ON "members" ("id", "guild_id")
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "roles"
+ RENAME TO "temporary_roles"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "roles" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "guild_id" varchar,
+ "color" integer NOT NULL,
+ "hoist" boolean NOT NULL,
+ "managed" boolean NOT NULL,
+ "mentionable" boolean NOT NULL,
+ "name" varchar NOT NULL,
+ "permissions" varchar NOT NULL,
+ "position" integer NOT NULL,
+ "icon" varchar,
+ "unicode_emoji" varchar,
+ "tags" text
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "roles"(
+ "id",
+ "guild_id",
+ "color",
+ "hoist",
+ "managed",
+ "mentionable",
+ "name",
+ "permissions",
+ "position",
+ "icon",
+ "unicode_emoji",
+ "tags"
+ )
+ SELECT "id",
+ "guild_id",
+ "color",
+ "hoist",
+ "managed",
+ "mentionable",
+ "name",
+ "permissions",
+ "position",
+ "icon",
+ "unicode_emoji",
+ "tags"
+ FROM "temporary_roles"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_roles"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "recipients"
+ RENAME TO "temporary_recipients"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "recipients" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "channel_id" varchar NOT NULL,
+ "user_id" varchar NOT NULL,
+ "closed" boolean NOT NULL DEFAULT (0)
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "recipients"("id", "channel_id", "user_id", "closed")
+ SELECT "id",
+ "channel_id",
+ "user_id",
+ "closed"
+ FROM "temporary_recipients"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_recipients"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "bans"
+ RENAME TO "temporary_bans"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "bans" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "guild_id" varchar,
+ "executor_id" varchar,
+ "ip" varchar NOT NULL,
+ "reason" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "bans"(
+ "id",
+ "user_id",
+ "guild_id",
+ "executor_id",
+ "ip",
+ "reason"
+ )
+ SELECT "id",
+ "user_id",
+ "guild_id",
+ "executor_id",
+ "ip",
+ "reason"
+ FROM "temporary_bans"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_bans"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "backup_codes"
+ RENAME TO "temporary_backup_codes"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "backup_codes" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "code" varchar NOT NULL,
+ "consumed" boolean NOT NULL,
+ "expired" boolean NOT NULL,
+ "user_id" varchar
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "backup_codes"("id", "code", "consumed", "expired", "user_id")
+ SELECT "id",
+ "code",
+ "consumed",
+ "expired",
+ "user_id"
+ FROM "temporary_backup_codes"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_backup_codes"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "connected_accounts"
+ RENAME TO "temporary_connected_accounts"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "connected_accounts" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar,
+ "access_token" varchar NOT NULL,
+ "friend_sync" boolean NOT NULL,
+ "name" varchar NOT NULL,
+ "revoked" boolean NOT NULL,
+ "show_activity" boolean NOT NULL,
+ "type" varchar NOT NULL,
+ "verified" boolean NOT NULL,
+ "visibility" integer NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "connected_accounts"(
+ "id",
+ "user_id",
+ "access_token",
+ "friend_sync",
+ "name",
+ "revoked",
+ "show_activity",
+ "type",
+ "verified",
+ "visibility"
+ )
+ SELECT "id",
+ "user_id",
+ "access_token",
+ "friend_sync",
+ "name",
+ "revoked",
+ "show_activity",
+ "type",
+ "verified",
+ "visibility"
+ FROM "temporary_connected_accounts"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_connected_accounts"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_a0b2ff0a598df0b0d055934a17"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "relationships"
+ RENAME TO "temporary_relationships"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "relationships" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "from_id" varchar NOT NULL,
+ "to_id" varchar NOT NULL,
+ "nickname" varchar,
+ "type" integer NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "relationships"("id", "from_id", "to_id", "nickname", "type")
+ SELECT "id",
+ "from_id",
+ "to_id",
+ "nickname",
+ "type"
+ FROM "temporary_relationships"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_relationships"
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_a0b2ff0a598df0b0d055934a17" ON "relationships" ("from_id", "to_id")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_e22a70819d07659c7a71c112a1"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_40bb6f23e7cc133292e92829d2"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_stickers"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_bdb8c09e1464cabf62105bf4b9"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_2a27102ecd1d81b4582a436092"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_channel_mentions"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_29d63eb1a458200851bc37d074"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_a8242cf535337a490b0feaea0b"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_role_mentions"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_b831eb18ceebd28976239b1e2f"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_a343387fc560ef378760681c23"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "message_user_mentions"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_e9080e7a7997a0170026d5139c"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_5d7ddc8a5f9c167f548625e772"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "member_roles"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "notes"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "client_release"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "sticker_packs"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "sessions"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "rate_limits"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "categories"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "audit_logs"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "teams"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "team_members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "guilds"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "templates"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "emojis"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "channels"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "voice_states"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "invites"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_0abf8b443321bd3cf7f81ee17a"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "read_states"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_3ed7a60fb7dbe04e1ba9332a8b"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_05535bc695e9f7ee104616459d"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_86b9109b155eb70c0a2ca3b4b6"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "messages"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "attachments"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "stickers"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "webhooks"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_bb2bf9386ac443afbbbf9f12d3"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "roles"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "recipients"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "bans"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "backup_codes"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "users"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "connected_accounts"
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_a0b2ff0a598df0b0d055934a17"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "relationships"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "config"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/sqlite/1659921722863-premium_since_as_date.ts b/src/util/migrations/sqlite/1659921722863-premium_since_as_date.ts
new file mode 100644
index 00000000..788be625
--- /dev/null
+++ b/src/util/migrations/sqlite/1659921722863-premium_since_as_date.ts
@@ -0,0 +1,252 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class premiumSinceAsDate1659921722863 implements MigrationInterface {
+ name = 'premiumSinceAsDate1659921722863'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ DROP INDEX "IDX_bb2bf9386ac443afbbbf9f12d3"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_members" (
+ "index" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
+ "id" varchar NOT NULL,
+ "guild_id" varchar NOT NULL,
+ "nick" varchar,
+ "joined_at" datetime NOT NULL,
+ "premium_since" bigint,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "pending" boolean NOT NULL,
+ "settings" text NOT NULL,
+ "last_message_id" varchar,
+ "joined_by" varchar,
+ CONSTRAINT "FK_16aceddd5b89825b8ed6029ad1c" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_28b53062261b996d9c99fa12404" FOREIGN KEY ("id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_members"(
+ "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ )
+ SELECT "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ FROM "members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "members"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_members"
+ RENAME TO "members"
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_bb2bf9386ac443afbbbf9f12d3" ON "members" ("id", "guild_id")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_bb2bf9386ac443afbbbf9f12d3"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_members" (
+ "index" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
+ "id" varchar NOT NULL,
+ "guild_id" varchar NOT NULL,
+ "nick" varchar,
+ "joined_at" datetime NOT NULL,
+ "premium_since" datetime,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "pending" boolean NOT NULL,
+ "settings" text NOT NULL,
+ "last_message_id" varchar,
+ "joined_by" varchar,
+ CONSTRAINT "FK_16aceddd5b89825b8ed6029ad1c" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_28b53062261b996d9c99fa12404" FOREIGN KEY ("id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_members"(
+ "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ )
+ SELECT "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ FROM "members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "members"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_members"
+ RENAME TO "members"
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_bb2bf9386ac443afbbbf9f12d3" ON "members" ("id", "guild_id")
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ DROP INDEX "IDX_bb2bf9386ac443afbbbf9f12d3"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "members"
+ RENAME TO "temporary_members"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "members" (
+ "index" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
+ "id" varchar NOT NULL,
+ "guild_id" varchar NOT NULL,
+ "nick" varchar,
+ "joined_at" datetime NOT NULL,
+ "premium_since" bigint,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "pending" boolean NOT NULL,
+ "settings" text NOT NULL,
+ "last_message_id" varchar,
+ "joined_by" varchar,
+ CONSTRAINT "FK_16aceddd5b89825b8ed6029ad1c" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_28b53062261b996d9c99fa12404" FOREIGN KEY ("id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "members"(
+ "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ )
+ SELECT "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ FROM "temporary_members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_members"
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_bb2bf9386ac443afbbbf9f12d3" ON "members" ("id", "guild_id")
+ `);
+ await queryRunner.query(`
+ DROP INDEX "IDX_bb2bf9386ac443afbbbf9f12d3"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "members"
+ RENAME TO "temporary_members"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "members" (
+ "index" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
+ "id" varchar NOT NULL,
+ "guild_id" varchar NOT NULL,
+ "nick" varchar,
+ "joined_at" datetime NOT NULL,
+ "premium_since" bigint,
+ "deaf" boolean NOT NULL,
+ "mute" boolean NOT NULL,
+ "pending" boolean NOT NULL,
+ "settings" text NOT NULL,
+ "last_message_id" varchar,
+ "joined_by" varchar,
+ CONSTRAINT "FK_16aceddd5b89825b8ed6029ad1c" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_28b53062261b996d9c99fa12404" FOREIGN KEY ("id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "members"(
+ "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ )
+ SELECT "index",
+ "id",
+ "guild_id",
+ "nick",
+ "joined_at",
+ "premium_since",
+ "deaf",
+ "mute",
+ "pending",
+ "settings",
+ "last_message_id",
+ "joined_by"
+ FROM "temporary_members"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_members"
+ `);
+ await queryRunner.query(`
+ CREATE UNIQUE INDEX "IDX_bb2bf9386ac443afbbbf9f12d3" ON "members" ("id", "guild_id")
+ `);
+ }
+
+}
diff --git a/src/util/migrations/sqlite/1660130536131-updated-applications.ts b/src/util/migrations/sqlite/1660130536131-updated-applications.ts
new file mode 100644
index 00000000..b8cbcc33
--- /dev/null
+++ b/src/util/migrations/sqlite/1660130536131-updated-applications.ts
@@ -0,0 +1,829 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class updatedApplications1660130536131 implements MigrationInterface {
+ name = 'updatedApplications1660130536131'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "temporary_applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "rpc_origins" text,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "primary_sku_id" varchar,
+ "slug" varchar,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "guild_id" varchar,
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ FROM "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_applications"
+ RENAME TO "applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ FROM "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_applications"
+ RENAME TO "applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "type" text,
+ "hook" boolean NOT NULL,
+ "redirect_uris" text,
+ "rpc_application_state" integer,
+ "store_application_state" integer,
+ "verification_state" integer,
+ "interactions_endpoint_url" varchar,
+ "integration_public" boolean,
+ "integration_require_code_grant" boolean,
+ "discoverability_state" integer,
+ "discovery_eligibility_flags" integer,
+ "tags" text,
+ "install_params" text,
+ "bot_user_id" varchar,
+ CONSTRAINT "UQ_b7f6e13565e920916d902e1f431" UNIQUE ("bot_user_id"),
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ FROM "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_applications"
+ RENAME TO "applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" integer NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "type" text,
+ "hook" boolean NOT NULL,
+ "redirect_uris" text,
+ "rpc_application_state" integer,
+ "store_application_state" integer,
+ "verification_state" integer,
+ "interactions_endpoint_url" varchar,
+ "integration_public" boolean,
+ "integration_require_code_grant" boolean,
+ "discoverability_state" integer,
+ "discovery_eligibility_flags" integer,
+ "tags" text,
+ "install_params" text,
+ "bot_user_id" varchar,
+ CONSTRAINT "UQ_b7f6e13565e920916d902e1f431" UNIQUE ("bot_user_id"),
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ FROM "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_applications"
+ RENAME TO "applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" integer NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "type" text,
+ "hook" boolean NOT NULL,
+ "redirect_uris" text,
+ "rpc_application_state" integer,
+ "store_application_state" integer,
+ "verification_state" integer,
+ "interactions_endpoint_url" varchar,
+ "integration_public" boolean,
+ "integration_require_code_grant" boolean,
+ "discoverability_state" integer,
+ "discovery_eligibility_flags" integer,
+ "tags" text,
+ "install_params" text,
+ "bot_user_id" varchar,
+ CONSTRAINT "UQ_b7f6e13565e920916d902e1f431" UNIQUE ("bot_user_id"),
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_2ce5a55796fe4c2f77ece57a647" FOREIGN KEY ("bot_user_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ FROM "applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_applications"
+ RENAME TO "applications"
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ RENAME TO "temporary_applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" integer NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "type" text,
+ "hook" boolean NOT NULL,
+ "redirect_uris" text,
+ "rpc_application_state" integer,
+ "store_application_state" integer,
+ "verification_state" integer,
+ "interactions_endpoint_url" varchar,
+ "integration_public" boolean,
+ "integration_require_code_grant" boolean,
+ "discoverability_state" integer,
+ "discovery_eligibility_flags" integer,
+ "tags" text,
+ "install_params" text,
+ "bot_user_id" varchar,
+ CONSTRAINT "UQ_b7f6e13565e920916d902e1f431" UNIQUE ("bot_user_id"),
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ FROM "temporary_applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ RENAME TO "temporary_applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "type" text,
+ "hook" boolean NOT NULL,
+ "redirect_uris" text,
+ "rpc_application_state" integer,
+ "store_application_state" integer,
+ "verification_state" integer,
+ "interactions_endpoint_url" varchar,
+ "integration_public" boolean,
+ "integration_require_code_grant" boolean,
+ "discoverability_state" integer,
+ "discovery_eligibility_flags" integer,
+ "tags" text,
+ "install_params" text,
+ "bot_user_id" varchar,
+ CONSTRAINT "UQ_b7f6e13565e920916d902e1f431" UNIQUE ("bot_user_id"),
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "type",
+ "hook",
+ "redirect_uris",
+ "rpc_application_state",
+ "store_application_state",
+ "verification_state",
+ "interactions_endpoint_url",
+ "integration_public",
+ "integration_require_code_grant",
+ "discoverability_state",
+ "discovery_eligibility_flags",
+ "tags",
+ "install_params",
+ "bot_user_id"
+ FROM "temporary_applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ RENAME TO "temporary_applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ FROM "temporary_applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ RENAME TO "temporary_applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "rpc_origins" text,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "primary_sku_id" varchar,
+ "slug" varchar,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "guild_id" varchar,
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id"
+ FROM "temporary_applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_applications"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "applications"
+ RENAME TO "temporary_applications"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "applications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "name" varchar NOT NULL,
+ "icon" varchar,
+ "description" varchar NOT NULL,
+ "rpc_origins" text,
+ "bot_public" boolean NOT NULL,
+ "bot_require_code_grant" boolean NOT NULL,
+ "terms_of_service_url" varchar,
+ "privacy_policy_url" varchar,
+ "summary" varchar,
+ "verify_key" varchar NOT NULL,
+ "primary_sku_id" varchar,
+ "slug" varchar,
+ "cover_image" varchar,
+ "flags" varchar NOT NULL,
+ "owner_id" varchar,
+ "team_id" varchar,
+ "guild_id" varchar,
+ CONSTRAINT "FK_e5bf78cdbbe9ba91062d74c5aba" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_a36ed02953077f408d0f3ebc424" FOREIGN KEY ("team_id") REFERENCES "teams" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "applications"(
+ "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ )
+ SELECT "id",
+ "name",
+ "icon",
+ "description",
+ "rpc_origins",
+ "bot_public",
+ "bot_require_code_grant",
+ "terms_of_service_url",
+ "privacy_policy_url",
+ "summary",
+ "verify_key",
+ "primary_sku_id",
+ "slug",
+ "cover_image",
+ "flags",
+ "owner_id",
+ "team_id",
+ "guild_id"
+ FROM "temporary_applications"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_applications"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/sqlite/1660257576211-CodeCleanup1.ts b/src/util/migrations/sqlite/1660257576211-CodeCleanup1.ts
new file mode 100644
index 00000000..5a61db0d
--- /dev/null
+++ b/src/util/migrations/sqlite/1660257576211-CodeCleanup1.ts
@@ -0,0 +1,326 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class CodeCleanup11660257576211 implements MigrationInterface {
+ name = 'CodeCleanup11660257576211'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "user_settings" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "afk_timeout" integer,
+ "allow_accessibility_detection" boolean,
+ "animate_emoji" boolean,
+ "animate_stickers" integer,
+ "contact_sync_enabled" boolean,
+ "convert_emoticons" boolean,
+ "custom_status" text,
+ "default_guilds_restricted" boolean,
+ "detect_platform_accounts" boolean,
+ "developer_mode" boolean,
+ "disable_games_tab" boolean,
+ "enable_tts_command" boolean,
+ "explicit_content_filter" integer,
+ "friend_source_flags" text,
+ "gateway_connected" boolean,
+ "gif_auto_play" boolean,
+ "guild_folders" text,
+ "guild_positions" text,
+ "inline_attachment_media" boolean,
+ "inline_embed_media" boolean,
+ "locale" varchar,
+ "message_display_compact" boolean,
+ "native_phone_integration_enabled" boolean,
+ "render_embeds" boolean,
+ "render_reactions" boolean,
+ "restricted_guilds" text,
+ "show_current_game" boolean,
+ "status" varchar,
+ "stream_notifications_enabled" boolean,
+ "theme" varchar,
+ "timezone_offset" integer
+ )
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_guilds" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "afk_channel_id" varchar,
+ "afk_timeout" integer,
+ "banner" varchar,
+ "default_message_notifications" integer,
+ "description" varchar,
+ "discovery_splash" varchar,
+ "explicit_content_filter" integer,
+ "features" text NOT NULL,
+ "primary_category_id" integer,
+ "icon" varchar,
+ "large" boolean,
+ "max_members" integer,
+ "max_presences" integer,
+ "max_video_channel_users" integer,
+ "member_count" integer,
+ "presence_count" integer,
+ "template_id" varchar,
+ "mfa_level" integer,
+ "name" varchar NOT NULL,
+ "owner_id" varchar,
+ "preferred_locale" varchar,
+ "premium_subscription_count" integer,
+ "premium_tier" integer,
+ "public_updates_channel_id" varchar,
+ "rules_channel_id" varchar,
+ "region" varchar,
+ "splash" varchar,
+ "system_channel_id" varchar,
+ "system_channel_flags" integer,
+ "unavailable" boolean,
+ "verification_level" integer,
+ "welcome_screen" text NOT NULL,
+ "widget_channel_id" varchar,
+ "widget_enabled" boolean,
+ "nsfw_level" integer,
+ "nsfw" boolean,
+ "parent" varchar,
+ "premium_progress_bar_enabled" boolean NOT NULL,
+ CONSTRAINT "FK_9d1d665379eefde7876a17afa99" FOREIGN KEY ("widget_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_cfc3d3ad260f8121c95b31a1fce" FOREIGN KEY ("system_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_95828668aa333460582e0ca6396" FOREIGN KEY ("rules_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_8d450b016dc8bec35f36729e4b0" FOREIGN KEY ("public_updates_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_fc1a451727e3643ca572a3bb394" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e2a2f873a64a5cf62526de42325" FOREIGN KEY ("template_id") REFERENCES "templates" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_f591a66b8019d87b0fe6c12dad6" FOREIGN KEY ("afk_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_guilds"(
+ "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent"
+ )
+ SELECT "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent"
+ FROM "guilds"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "guilds"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_guilds"
+ RENAME TO "guilds"
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ RENAME TO "temporary_guilds"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "guilds" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "afk_channel_id" varchar,
+ "afk_timeout" integer,
+ "banner" varchar,
+ "default_message_notifications" integer,
+ "description" varchar,
+ "discovery_splash" varchar,
+ "explicit_content_filter" integer,
+ "features" text NOT NULL,
+ "primary_category_id" integer,
+ "icon" varchar,
+ "large" boolean,
+ "max_members" integer,
+ "max_presences" integer,
+ "max_video_channel_users" integer,
+ "member_count" integer,
+ "presence_count" integer,
+ "template_id" varchar,
+ "mfa_level" integer,
+ "name" varchar NOT NULL,
+ "owner_id" varchar,
+ "preferred_locale" varchar,
+ "premium_subscription_count" integer,
+ "premium_tier" integer,
+ "public_updates_channel_id" varchar,
+ "rules_channel_id" varchar,
+ "region" varchar,
+ "splash" varchar,
+ "system_channel_id" varchar,
+ "system_channel_flags" integer,
+ "unavailable" boolean,
+ "verification_level" integer,
+ "welcome_screen" text NOT NULL,
+ "widget_channel_id" varchar,
+ "widget_enabled" boolean,
+ "nsfw_level" integer,
+ "nsfw" boolean,
+ "parent" varchar,
+ CONSTRAINT "FK_9d1d665379eefde7876a17afa99" FOREIGN KEY ("widget_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_cfc3d3ad260f8121c95b31a1fce" FOREIGN KEY ("system_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_95828668aa333460582e0ca6396" FOREIGN KEY ("rules_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_8d450b016dc8bec35f36729e4b0" FOREIGN KEY ("public_updates_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_fc1a451727e3643ca572a3bb394" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e2a2f873a64a5cf62526de42325" FOREIGN KEY ("template_id") REFERENCES "templates" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_f591a66b8019d87b0fe6c12dad6" FOREIGN KEY ("afk_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "guilds"(
+ "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent"
+ )
+ SELECT "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent"
+ FROM "temporary_guilds"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_guilds"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "user_settings"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/sqlite/1660257795259-CodeCleanup2.ts b/src/util/migrations/sqlite/1660257795259-CodeCleanup2.ts
new file mode 100644
index 00000000..53698256
--- /dev/null
+++ b/src/util/migrations/sqlite/1660257795259-CodeCleanup2.ts
@@ -0,0 +1,572 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class CodeCleanup21660257795259 implements MigrationInterface {
+ name = 'CodeCleanup21660257795259'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "temporary_guilds" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "afk_channel_id" varchar,
+ "afk_timeout" integer,
+ "banner" varchar,
+ "default_message_notifications" integer,
+ "description" varchar,
+ "discovery_splash" varchar,
+ "explicit_content_filter" integer,
+ "features" text NOT NULL,
+ "primary_category_id" integer,
+ "icon" varchar,
+ "large" boolean,
+ "max_members" integer,
+ "max_presences" integer,
+ "max_video_channel_users" integer,
+ "member_count" integer,
+ "presence_count" integer,
+ "template_id" varchar,
+ "mfa_level" integer,
+ "name" varchar NOT NULL,
+ "owner_id" varchar,
+ "preferred_locale" varchar,
+ "premium_subscription_count" integer,
+ "premium_tier" integer,
+ "public_updates_channel_id" varchar,
+ "rules_channel_id" varchar,
+ "region" varchar,
+ "splash" varchar,
+ "system_channel_id" varchar,
+ "system_channel_flags" integer,
+ "unavailable" boolean,
+ "verification_level" integer,
+ "welcome_screen" text NOT NULL,
+ "widget_channel_id" varchar,
+ "widget_enabled" boolean,
+ "nsfw_level" integer,
+ "nsfw" boolean,
+ "parent" varchar,
+ "premium_progress_bar_enabled" boolean NOT NULL,
+ CONSTRAINT "FK_f591a66b8019d87b0fe6c12dad6" FOREIGN KEY ("afk_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e2a2f873a64a5cf62526de42325" FOREIGN KEY ("template_id") REFERENCES "templates" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_fc1a451727e3643ca572a3bb394" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_8d450b016dc8bec35f36729e4b0" FOREIGN KEY ("public_updates_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_95828668aa333460582e0ca6396" FOREIGN KEY ("rules_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_cfc3d3ad260f8121c95b31a1fce" FOREIGN KEY ("system_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_9d1d665379eefde7876a17afa99" FOREIGN KEY ("widget_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_guilds"(
+ "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent",
+ "premium_progress_bar_enabled"
+ )
+ SELECT "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent",
+ "premium_progress_bar_enabled"
+ FROM "guilds"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "guilds"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_guilds"
+ RENAME TO "guilds"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_guilds" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "afk_channel_id" varchar,
+ "afk_timeout" integer,
+ "banner" varchar,
+ "default_message_notifications" integer,
+ "description" varchar,
+ "discovery_splash" varchar,
+ "explicit_content_filter" integer,
+ "features" text NOT NULL,
+ "primary_category_id" integer,
+ "icon" varchar,
+ "large" boolean,
+ "max_members" integer,
+ "max_presences" integer,
+ "max_video_channel_users" integer,
+ "member_count" integer,
+ "presence_count" integer,
+ "template_id" varchar,
+ "mfa_level" integer,
+ "name" varchar NOT NULL,
+ "owner_id" varchar,
+ "preferred_locale" varchar,
+ "premium_subscription_count" integer,
+ "premium_tier" integer,
+ "public_updates_channel_id" varchar,
+ "rules_channel_id" varchar,
+ "region" varchar,
+ "splash" varchar,
+ "system_channel_id" varchar,
+ "system_channel_flags" integer,
+ "unavailable" boolean,
+ "verification_level" integer,
+ "welcome_screen" text NOT NULL,
+ "widget_channel_id" varchar,
+ "widget_enabled" boolean,
+ "nsfw_level" integer,
+ "nsfw" boolean,
+ "parent" varchar,
+ "premium_progress_bar_enabled" boolean,
+ CONSTRAINT "FK_f591a66b8019d87b0fe6c12dad6" FOREIGN KEY ("afk_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e2a2f873a64a5cf62526de42325" FOREIGN KEY ("template_id") REFERENCES "templates" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_fc1a451727e3643ca572a3bb394" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_8d450b016dc8bec35f36729e4b0" FOREIGN KEY ("public_updates_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_95828668aa333460582e0ca6396" FOREIGN KEY ("rules_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_cfc3d3ad260f8121c95b31a1fce" FOREIGN KEY ("system_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_9d1d665379eefde7876a17afa99" FOREIGN KEY ("widget_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_guilds"(
+ "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent",
+ "premium_progress_bar_enabled"
+ )
+ SELECT "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent",
+ "premium_progress_bar_enabled"
+ FROM "guilds"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "guilds"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_guilds"
+ RENAME TO "guilds"
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ RENAME TO "temporary_guilds"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "guilds" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "afk_channel_id" varchar,
+ "afk_timeout" integer,
+ "banner" varchar,
+ "default_message_notifications" integer,
+ "description" varchar,
+ "discovery_splash" varchar,
+ "explicit_content_filter" integer,
+ "features" text NOT NULL,
+ "primary_category_id" integer,
+ "icon" varchar,
+ "large" boolean,
+ "max_members" integer,
+ "max_presences" integer,
+ "max_video_channel_users" integer,
+ "member_count" integer,
+ "presence_count" integer,
+ "template_id" varchar,
+ "mfa_level" integer,
+ "name" varchar NOT NULL,
+ "owner_id" varchar,
+ "preferred_locale" varchar,
+ "premium_subscription_count" integer,
+ "premium_tier" integer,
+ "public_updates_channel_id" varchar,
+ "rules_channel_id" varchar,
+ "region" varchar,
+ "splash" varchar,
+ "system_channel_id" varchar,
+ "system_channel_flags" integer,
+ "unavailable" boolean,
+ "verification_level" integer,
+ "welcome_screen" text NOT NULL,
+ "widget_channel_id" varchar,
+ "widget_enabled" boolean,
+ "nsfw_level" integer,
+ "nsfw" boolean,
+ "parent" varchar,
+ "premium_progress_bar_enabled" boolean NOT NULL,
+ CONSTRAINT "FK_f591a66b8019d87b0fe6c12dad6" FOREIGN KEY ("afk_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e2a2f873a64a5cf62526de42325" FOREIGN KEY ("template_id") REFERENCES "templates" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_fc1a451727e3643ca572a3bb394" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_8d450b016dc8bec35f36729e4b0" FOREIGN KEY ("public_updates_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_95828668aa333460582e0ca6396" FOREIGN KEY ("rules_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_cfc3d3ad260f8121c95b31a1fce" FOREIGN KEY ("system_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_9d1d665379eefde7876a17afa99" FOREIGN KEY ("widget_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "guilds"(
+ "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent",
+ "premium_progress_bar_enabled"
+ )
+ SELECT "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent",
+ "premium_progress_bar_enabled"
+ FROM "temporary_guilds"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_guilds"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "guilds"
+ RENAME TO "temporary_guilds"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "guilds" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "afk_channel_id" varchar,
+ "afk_timeout" integer,
+ "banner" varchar,
+ "default_message_notifications" integer,
+ "description" varchar,
+ "discovery_splash" varchar,
+ "explicit_content_filter" integer,
+ "features" text NOT NULL,
+ "primary_category_id" integer,
+ "icon" varchar,
+ "large" boolean,
+ "max_members" integer,
+ "max_presences" integer,
+ "max_video_channel_users" integer,
+ "member_count" integer,
+ "presence_count" integer,
+ "template_id" varchar,
+ "mfa_level" integer,
+ "name" varchar NOT NULL,
+ "owner_id" varchar,
+ "preferred_locale" varchar,
+ "premium_subscription_count" integer,
+ "premium_tier" integer,
+ "public_updates_channel_id" varchar,
+ "rules_channel_id" varchar,
+ "region" varchar,
+ "splash" varchar,
+ "system_channel_id" varchar,
+ "system_channel_flags" integer,
+ "unavailable" boolean,
+ "verification_level" integer,
+ "welcome_screen" text NOT NULL,
+ "widget_channel_id" varchar,
+ "widget_enabled" boolean,
+ "nsfw_level" integer,
+ "nsfw" boolean,
+ "parent" varchar,
+ "premium_progress_bar_enabled" boolean NOT NULL,
+ CONSTRAINT "FK_f591a66b8019d87b0fe6c12dad6" FOREIGN KEY ("afk_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_e2a2f873a64a5cf62526de42325" FOREIGN KEY ("template_id") REFERENCES "templates" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_fc1a451727e3643ca572a3bb394" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_8d450b016dc8bec35f36729e4b0" FOREIGN KEY ("public_updates_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_95828668aa333460582e0ca6396" FOREIGN KEY ("rules_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_cfc3d3ad260f8121c95b31a1fce" FOREIGN KEY ("system_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_9d1d665379eefde7876a17afa99" FOREIGN KEY ("widget_channel_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "guilds"(
+ "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent",
+ "premium_progress_bar_enabled"
+ )
+ SELECT "id",
+ "afk_channel_id",
+ "afk_timeout",
+ "banner",
+ "default_message_notifications",
+ "description",
+ "discovery_splash",
+ "explicit_content_filter",
+ "features",
+ "primary_category_id",
+ "icon",
+ "large",
+ "max_members",
+ "max_presences",
+ "max_video_channel_users",
+ "member_count",
+ "presence_count",
+ "template_id",
+ "mfa_level",
+ "name",
+ "owner_id",
+ "preferred_locale",
+ "premium_subscription_count",
+ "premium_tier",
+ "public_updates_channel_id",
+ "rules_channel_id",
+ "region",
+ "splash",
+ "system_channel_id",
+ "system_channel_flags",
+ "unavailable",
+ "verification_level",
+ "welcome_screen",
+ "widget_channel_id",
+ "widget_enabled",
+ "nsfw_level",
+ "nsfw",
+ "parent",
+ "premium_progress_bar_enabled"
+ FROM "temporary_guilds"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_guilds"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/sqlite/1660258351379-CodeCleanup3.ts b/src/util/migrations/sqlite/1660258351379-CodeCleanup3.ts
new file mode 100644
index 00000000..13fba6dd
--- /dev/null
+++ b/src/util/migrations/sqlite/1660258351379-CodeCleanup3.ts
@@ -0,0 +1,231 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class CodeCleanup31660258351379 implements MigrationInterface {
+ name = 'CodeCleanup31660258351379'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "temporary_users" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "username" varchar NOT NULL,
+ "discriminator" varchar NOT NULL,
+ "avatar" varchar,
+ "accent_color" integer,
+ "banner" varchar,
+ "phone" varchar,
+ "desktop" boolean NOT NULL,
+ "mobile" boolean NOT NULL,
+ "premium" boolean NOT NULL,
+ "premium_type" integer NOT NULL,
+ "bot" boolean NOT NULL,
+ "bio" varchar NOT NULL,
+ "system" boolean NOT NULL,
+ "nsfw_allowed" boolean NOT NULL,
+ "mfa_enabled" boolean NOT NULL,
+ "totp_secret" varchar,
+ "totp_last_ticket" varchar,
+ "created_at" datetime NOT NULL,
+ "premium_since" datetime,
+ "verified" boolean NOT NULL,
+ "disabled" boolean NOT NULL,
+ "deleted" boolean NOT NULL,
+ "email" varchar,
+ "flags" varchar NOT NULL,
+ "public_flags" integer NOT NULL,
+ "rights" bigint NOT NULL,
+ "data" text NOT NULL,
+ "fingerprints" text NOT NULL,
+ "extended_settings" text NOT NULL,
+ "notes" text NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_users"(
+ "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes"
+ )
+ SELECT "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes"
+ FROM "users"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "users"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_users"
+ RENAME TO "users"
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ RENAME TO "temporary_users"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "users" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "username" varchar NOT NULL,
+ "discriminator" varchar NOT NULL,
+ "avatar" varchar,
+ "accent_color" integer,
+ "banner" varchar,
+ "phone" varchar,
+ "desktop" boolean NOT NULL,
+ "mobile" boolean NOT NULL,
+ "premium" boolean NOT NULL,
+ "premium_type" integer NOT NULL,
+ "bot" boolean NOT NULL,
+ "bio" varchar NOT NULL,
+ "system" boolean NOT NULL,
+ "nsfw_allowed" boolean NOT NULL,
+ "mfa_enabled" boolean NOT NULL,
+ "totp_secret" varchar,
+ "totp_last_ticket" varchar,
+ "created_at" datetime NOT NULL,
+ "premium_since" datetime,
+ "verified" boolean NOT NULL,
+ "disabled" boolean NOT NULL,
+ "deleted" boolean NOT NULL,
+ "email" varchar,
+ "flags" varchar NOT NULL,
+ "public_flags" integer NOT NULL,
+ "rights" bigint NOT NULL,
+ "data" text NOT NULL,
+ "fingerprints" text NOT NULL,
+ "settings" text NOT NULL,
+ "extended_settings" text NOT NULL,
+ "notes" text NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "users"(
+ "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes"
+ )
+ SELECT "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes"
+ FROM "temporary_users"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_users"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/sqlite/1660260672914-CodeCleanup4.ts b/src/util/migrations/sqlite/1660260672914-CodeCleanup4.ts
new file mode 100644
index 00000000..33f4df03
--- /dev/null
+++ b/src/util/migrations/sqlite/1660260672914-CodeCleanup4.ts
@@ -0,0 +1,459 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class CodeCleanup41660260672914 implements MigrationInterface {
+ name = 'CodeCleanup41660260672914'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "temporary_users" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "username" varchar NOT NULL,
+ "discriminator" varchar NOT NULL,
+ "avatar" varchar,
+ "accent_color" integer,
+ "banner" varchar,
+ "phone" varchar,
+ "desktop" boolean NOT NULL,
+ "mobile" boolean NOT NULL,
+ "premium" boolean NOT NULL,
+ "premium_type" integer NOT NULL,
+ "bot" boolean NOT NULL,
+ "bio" varchar NOT NULL,
+ "system" boolean NOT NULL,
+ "nsfw_allowed" boolean NOT NULL,
+ "mfa_enabled" boolean NOT NULL,
+ "totp_secret" varchar,
+ "totp_last_ticket" varchar,
+ "created_at" datetime NOT NULL,
+ "premium_since" datetime,
+ "verified" boolean NOT NULL,
+ "disabled" boolean NOT NULL,
+ "deleted" boolean NOT NULL,
+ "email" varchar,
+ "flags" varchar NOT NULL,
+ "public_flags" integer NOT NULL,
+ "rights" bigint NOT NULL,
+ "data" text NOT NULL,
+ "fingerprints" text NOT NULL,
+ "extended_settings" text NOT NULL,
+ "notes" text NOT NULL,
+ "settingsId" varchar,
+ CONSTRAINT "UQ_b1dd13b6ed980004a795ca184a6" UNIQUE ("settingsId")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_users"(
+ "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes"
+ )
+ SELECT "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes"
+ FROM "users"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "users"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_users"
+ RENAME TO "users"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_users" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "username" varchar NOT NULL,
+ "discriminator" varchar NOT NULL,
+ "avatar" varchar,
+ "accent_color" integer,
+ "banner" varchar,
+ "phone" varchar,
+ "desktop" boolean NOT NULL,
+ "mobile" boolean NOT NULL,
+ "premium" boolean NOT NULL,
+ "premium_type" integer NOT NULL,
+ "bot" boolean NOT NULL,
+ "bio" varchar NOT NULL,
+ "system" boolean NOT NULL,
+ "nsfw_allowed" boolean NOT NULL,
+ "mfa_enabled" boolean NOT NULL,
+ "totp_secret" varchar,
+ "totp_last_ticket" varchar,
+ "created_at" datetime NOT NULL,
+ "premium_since" datetime,
+ "verified" boolean NOT NULL,
+ "disabled" boolean NOT NULL,
+ "deleted" boolean NOT NULL,
+ "email" varchar,
+ "flags" varchar NOT NULL,
+ "public_flags" integer NOT NULL,
+ "rights" bigint NOT NULL,
+ "data" text NOT NULL,
+ "fingerprints" text NOT NULL,
+ "extended_settings" text NOT NULL,
+ "notes" text NOT NULL,
+ "settingsId" varchar,
+ CONSTRAINT "UQ_b1dd13b6ed980004a795ca184a6" UNIQUE ("settingsId"),
+ CONSTRAINT "FK_76ba283779c8441fd5ff819c8cf" FOREIGN KEY ("settingsId") REFERENCES "user_settings" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_users"(
+ "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes",
+ "settingsId"
+ )
+ SELECT "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes",
+ "settingsId"
+ FROM "users"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "users"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_users"
+ RENAME TO "users"
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ RENAME TO "temporary_users"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "users" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "username" varchar NOT NULL,
+ "discriminator" varchar NOT NULL,
+ "avatar" varchar,
+ "accent_color" integer,
+ "banner" varchar,
+ "phone" varchar,
+ "desktop" boolean NOT NULL,
+ "mobile" boolean NOT NULL,
+ "premium" boolean NOT NULL,
+ "premium_type" integer NOT NULL,
+ "bot" boolean NOT NULL,
+ "bio" varchar NOT NULL,
+ "system" boolean NOT NULL,
+ "nsfw_allowed" boolean NOT NULL,
+ "mfa_enabled" boolean NOT NULL,
+ "totp_secret" varchar,
+ "totp_last_ticket" varchar,
+ "created_at" datetime NOT NULL,
+ "premium_since" datetime,
+ "verified" boolean NOT NULL,
+ "disabled" boolean NOT NULL,
+ "deleted" boolean NOT NULL,
+ "email" varchar,
+ "flags" varchar NOT NULL,
+ "public_flags" integer NOT NULL,
+ "rights" bigint NOT NULL,
+ "data" text NOT NULL,
+ "fingerprints" text NOT NULL,
+ "extended_settings" text NOT NULL,
+ "notes" text NOT NULL,
+ "settingsId" varchar,
+ CONSTRAINT "UQ_b1dd13b6ed980004a795ca184a6" UNIQUE ("settingsId")
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "users"(
+ "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes",
+ "settingsId"
+ )
+ SELECT "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes",
+ "settingsId"
+ FROM "temporary_users"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_users"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ RENAME TO "temporary_users"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "users" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "username" varchar NOT NULL,
+ "discriminator" varchar NOT NULL,
+ "avatar" varchar,
+ "accent_color" integer,
+ "banner" varchar,
+ "phone" varchar,
+ "desktop" boolean NOT NULL,
+ "mobile" boolean NOT NULL,
+ "premium" boolean NOT NULL,
+ "premium_type" integer NOT NULL,
+ "bot" boolean NOT NULL,
+ "bio" varchar NOT NULL,
+ "system" boolean NOT NULL,
+ "nsfw_allowed" boolean NOT NULL,
+ "mfa_enabled" boolean NOT NULL,
+ "totp_secret" varchar,
+ "totp_last_ticket" varchar,
+ "created_at" datetime NOT NULL,
+ "premium_since" datetime,
+ "verified" boolean NOT NULL,
+ "disabled" boolean NOT NULL,
+ "deleted" boolean NOT NULL,
+ "email" varchar,
+ "flags" varchar NOT NULL,
+ "public_flags" integer NOT NULL,
+ "rights" bigint NOT NULL,
+ "data" text NOT NULL,
+ "fingerprints" text NOT NULL,
+ "extended_settings" text NOT NULL,
+ "notes" text NOT NULL
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "users"(
+ "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes"
+ )
+ SELECT "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes"
+ FROM "temporary_users"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_users"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/sqlite/1660416010862-InvitersAreDeletable.ts b/src/util/migrations/sqlite/1660416010862-InvitersAreDeletable.ts
new file mode 100644
index 00000000..9b29e119
--- /dev/null
+++ b/src/util/migrations/sqlite/1660416010862-InvitersAreDeletable.ts
@@ -0,0 +1,246 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class InvitersAreDeletable1660416010862 implements MigrationInterface {
+ name = 'InvitersAreDeletable1660416010862'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "temporary_invites" (
+ "code" varchar PRIMARY KEY NOT NULL,
+ "temporary" boolean NOT NULL,
+ "uses" integer NOT NULL,
+ "max_uses" integer NOT NULL,
+ "max_age" integer NOT NULL,
+ "created_at" datetime NOT NULL,
+ "expires_at" datetime NOT NULL,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "inviter_id" varchar,
+ "target_user_id" varchar,
+ "target_user_type" integer,
+ "vanity_url" boolean,
+ CONSTRAINT "FK_11a0d394f8fc649c19ce5f16b59" FOREIGN KEY ("target_user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_6a15b051fe5050aa00a4b9ff0f6" FOREIGN KEY ("channel_id") REFERENCES "channels" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_3f4939aa1461e8af57fea3fb05d" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_invites"(
+ "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ )
+ SELECT "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ FROM "invites"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "invites"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_invites"
+ RENAME TO "invites"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "temporary_invites" (
+ "code" varchar PRIMARY KEY NOT NULL,
+ "temporary" boolean NOT NULL,
+ "uses" integer NOT NULL,
+ "max_uses" integer NOT NULL,
+ "max_age" integer NOT NULL,
+ "created_at" datetime NOT NULL,
+ "expires_at" datetime NOT NULL,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "inviter_id" varchar,
+ "target_user_id" varchar,
+ "target_user_type" integer,
+ "vanity_url" boolean,
+ CONSTRAINT "FK_11a0d394f8fc649c19ce5f16b59" FOREIGN KEY ("target_user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_6a15b051fe5050aa00a4b9ff0f6" FOREIGN KEY ("channel_id") REFERENCES "channels" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_3f4939aa1461e8af57fea3fb05d" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_15c35422032e0b22b4ada95f48f" FOREIGN KEY ("inviter_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_invites"(
+ "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ )
+ SELECT "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ FROM "invites"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "invites"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_invites"
+ RENAME TO "invites"
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "invites"
+ RENAME TO "temporary_invites"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "invites" (
+ "code" varchar PRIMARY KEY NOT NULL,
+ "temporary" boolean NOT NULL,
+ "uses" integer NOT NULL,
+ "max_uses" integer NOT NULL,
+ "max_age" integer NOT NULL,
+ "created_at" datetime NOT NULL,
+ "expires_at" datetime NOT NULL,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "inviter_id" varchar,
+ "target_user_id" varchar,
+ "target_user_type" integer,
+ "vanity_url" boolean,
+ CONSTRAINT "FK_11a0d394f8fc649c19ce5f16b59" FOREIGN KEY ("target_user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_6a15b051fe5050aa00a4b9ff0f6" FOREIGN KEY ("channel_id") REFERENCES "channels" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_3f4939aa1461e8af57fea3fb05d" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "invites"(
+ "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ )
+ SELECT "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ FROM "temporary_invites"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_invites"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "invites"
+ RENAME TO "temporary_invites"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "invites" (
+ "code" varchar PRIMARY KEY NOT NULL,
+ "temporary" boolean NOT NULL,
+ "uses" integer NOT NULL,
+ "max_uses" integer NOT NULL,
+ "max_age" integer NOT NULL,
+ "created_at" datetime NOT NULL,
+ "expires_at" datetime NOT NULL,
+ "guild_id" varchar,
+ "channel_id" varchar,
+ "inviter_id" varchar,
+ "target_user_id" varchar,
+ "target_user_type" integer,
+ "vanity_url" boolean,
+ CONSTRAINT "FK_11a0d394f8fc649c19ce5f16b59" FOREIGN KEY ("target_user_id") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_15c35422032e0b22b4ada95f48f" FOREIGN KEY ("inviter_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_6a15b051fe5050aa00a4b9ff0f6" FOREIGN KEY ("channel_id") REFERENCES "channels" ("id") ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT "FK_3f4939aa1461e8af57fea3fb05d" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "invites"(
+ "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ )
+ SELECT "code",
+ "temporary",
+ "uses",
+ "max_uses",
+ "max_age",
+ "created_at",
+ "expires_at",
+ "guild_id",
+ "channel_id",
+ "inviter_id",
+ "target_user_id",
+ "target_user_type",
+ "vanity_url"
+ FROM "temporary_invites"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_invites"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/sqlite/1660538628956-sync_migrations.ts b/src/util/migrations/sqlite/1660538628956-sync_migrations.ts
new file mode 100644
index 00000000..9cdc064f
--- /dev/null
+++ b/src/util/migrations/sqlite/1660538628956-sync_migrations.ts
@@ -0,0 +1,172 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class syncMigrations1660538628956 implements MigrationInterface {
+ name = 'syncMigrations1660538628956'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "temporary_channels" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "created_at" datetime NOT NULL,
+ "name" varchar,
+ "icon" text,
+ "type" integer NOT NULL,
+ "last_message_id" varchar,
+ "guild_id" varchar,
+ "parent_id" varchar,
+ "owner_id" varchar,
+ "last_pin_timestamp" integer,
+ "default_auto_archive_duration" integer,
+ "position" integer,
+ "permission_overwrites" text,
+ "video_quality_mode" integer,
+ "bitrate" integer,
+ "user_limit" integer,
+ "nsfw" boolean,
+ "rate_limit_per_user" integer,
+ "topic" varchar,
+ "retention_policy_id" varchar,
+ "flags" integer,
+ "default_thread_rate_limit_per_user" integer,
+ CONSTRAINT "FK_3873ed438575cce703ecff4fc7b" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_3274522d14af40540b1a883fc80" FOREIGN KEY ("parent_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_c253dafe5f3a03ec00cd8fb4581" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_channels"(
+ "id",
+ "created_at",
+ "name",
+ "icon",
+ "type",
+ "last_message_id",
+ "guild_id",
+ "parent_id",
+ "owner_id",
+ "last_pin_timestamp",
+ "default_auto_archive_duration",
+ "position",
+ "permission_overwrites",
+ "video_quality_mode",
+ "bitrate",
+ "user_limit",
+ "nsfw",
+ "rate_limit_per_user",
+ "topic",
+ "retention_policy_id"
+ )
+ SELECT "id",
+ "created_at",
+ "name",
+ "icon",
+ "type",
+ "last_message_id",
+ "guild_id",
+ "parent_id",
+ "owner_id",
+ "last_pin_timestamp",
+ "default_auto_archive_duration",
+ "position",
+ "permission_overwrites",
+ "video_quality_mode",
+ "bitrate",
+ "user_limit",
+ "nsfw",
+ "rate_limit_per_user",
+ "topic",
+ "retention_policy_id"
+ FROM "channels"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "channels"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_channels"
+ RENAME TO "channels"
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "channels"
+ RENAME TO "temporary_channels"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "channels" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "created_at" datetime NOT NULL,
+ "name" varchar,
+ "icon" text,
+ "type" integer NOT NULL,
+ "last_message_id" varchar,
+ "guild_id" varchar,
+ "parent_id" varchar,
+ "owner_id" varchar,
+ "last_pin_timestamp" integer,
+ "default_auto_archive_duration" integer,
+ "position" integer,
+ "permission_overwrites" text,
+ "video_quality_mode" integer,
+ "bitrate" integer,
+ "user_limit" integer,
+ "nsfw" boolean,
+ "rate_limit_per_user" integer,
+ "topic" varchar,
+ "retention_policy_id" varchar,
+ CONSTRAINT "FK_3873ed438575cce703ecff4fc7b" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_3274522d14af40540b1a883fc80" FOREIGN KEY ("parent_id") REFERENCES "channels" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION,
+ CONSTRAINT "FK_c253dafe5f3a03ec00cd8fb4581" FOREIGN KEY ("guild_id") REFERENCES "guilds" ("id") ON DELETE CASCADE ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "channels"(
+ "id",
+ "created_at",
+ "name",
+ "icon",
+ "type",
+ "last_message_id",
+ "guild_id",
+ "parent_id",
+ "owner_id",
+ "last_pin_timestamp",
+ "default_auto_archive_duration",
+ "position",
+ "permission_overwrites",
+ "video_quality_mode",
+ "bitrate",
+ "user_limit",
+ "nsfw",
+ "rate_limit_per_user",
+ "topic",
+ "retention_policy_id"
+ )
+ SELECT "id",
+ "created_at",
+ "name",
+ "icon",
+ "type",
+ "last_message_id",
+ "guild_id",
+ "parent_id",
+ "owner_id",
+ "last_pin_timestamp",
+ "default_auto_archive_duration",
+ "position",
+ "permission_overwrites",
+ "video_quality_mode",
+ "bitrate",
+ "user_limit",
+ "nsfw",
+ "rate_limit_per_user",
+ "topic",
+ "retention_policy_id"
+ FROM "temporary_channels"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_channels"
+ `);
+ }
+
+}
diff --git a/src/util/migrations/sqlite/1660549233583-fix_nullables.ts b/src/util/migrations/sqlite/1660549233583-fix_nullables.ts
new file mode 100644
index 00000000..68f650c7
--- /dev/null
+++ b/src/util/migrations/sqlite/1660549233583-fix_nullables.ts
@@ -0,0 +1,240 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class fixNullables1660549233583 implements MigrationInterface {
+ name = 'fixNullables1660549233583'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ CREATE TABLE "temporary_users" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "username" varchar NOT NULL,
+ "discriminator" varchar NOT NULL,
+ "avatar" varchar,
+ "accent_color" integer,
+ "banner" varchar,
+ "phone" varchar,
+ "desktop" boolean NOT NULL,
+ "mobile" boolean NOT NULL,
+ "premium" boolean NOT NULL,
+ "premium_type" integer NOT NULL,
+ "bot" boolean NOT NULL,
+ "bio" varchar,
+ "system" boolean NOT NULL,
+ "nsfw_allowed" boolean NOT NULL,
+ "mfa_enabled" boolean,
+ "totp_secret" varchar,
+ "totp_last_ticket" varchar,
+ "created_at" datetime NOT NULL,
+ "premium_since" datetime,
+ "verified" boolean NOT NULL,
+ "disabled" boolean NOT NULL,
+ "deleted" boolean NOT NULL,
+ "email" varchar,
+ "flags" varchar NOT NULL,
+ "public_flags" integer NOT NULL,
+ "rights" bigint NOT NULL,
+ "data" text NOT NULL,
+ "fingerprints" text NOT NULL,
+ "extended_settings" text NOT NULL,
+ "notes" text NOT NULL,
+ "settingsId" varchar,
+ CONSTRAINT "UQ_b1dd13b6ed980004a795ca184a6" UNIQUE ("settingsId"),
+ CONSTRAINT "FK_76ba283779c8441fd5ff819c8cf" FOREIGN KEY ("settingsId") REFERENCES "user_settings" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "temporary_users"(
+ "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes",
+ "settingsId"
+ )
+ SELECT "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes",
+ "settingsId"
+ FROM "users"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "users"
+ `);
+ await queryRunner.query(`
+ ALTER TABLE "temporary_users"
+ RENAME TO "users"
+ `);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`
+ ALTER TABLE "users"
+ RENAME TO "temporary_users"
+ `);
+ await queryRunner.query(`
+ CREATE TABLE "users" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "username" varchar NOT NULL,
+ "discriminator" varchar NOT NULL,
+ "avatar" varchar,
+ "accent_color" integer,
+ "banner" varchar,
+ "phone" varchar,
+ "desktop" boolean NOT NULL,
+ "mobile" boolean NOT NULL,
+ "premium" boolean NOT NULL,
+ "premium_type" integer NOT NULL,
+ "bot" boolean NOT NULL,
+ "bio" varchar NOT NULL,
+ "system" boolean NOT NULL,
+ "nsfw_allowed" boolean NOT NULL,
+ "mfa_enabled" boolean NOT NULL,
+ "totp_secret" varchar,
+ "totp_last_ticket" varchar,
+ "created_at" datetime NOT NULL,
+ "premium_since" datetime,
+ "verified" boolean NOT NULL,
+ "disabled" boolean NOT NULL,
+ "deleted" boolean NOT NULL,
+ "email" varchar,
+ "flags" varchar NOT NULL,
+ "public_flags" integer NOT NULL,
+ "rights" bigint NOT NULL,
+ "data" text NOT NULL,
+ "fingerprints" text NOT NULL,
+ "extended_settings" text NOT NULL,
+ "notes" text NOT NULL,
+ "settingsId" varchar,
+ CONSTRAINT "UQ_b1dd13b6ed980004a795ca184a6" UNIQUE ("settingsId"),
+ CONSTRAINT "FK_76ba283779c8441fd5ff819c8cf" FOREIGN KEY ("settingsId") REFERENCES "user_settings" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
+ )
+ `);
+ await queryRunner.query(`
+ INSERT INTO "users"(
+ "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes",
+ "settingsId"
+ )
+ SELECT "id",
+ "username",
+ "discriminator",
+ "avatar",
+ "accent_color",
+ "banner",
+ "phone",
+ "desktop",
+ "mobile",
+ "premium",
+ "premium_type",
+ "bot",
+ "bio",
+ "system",
+ "nsfw_allowed",
+ "mfa_enabled",
+ "totp_secret",
+ "totp_last_ticket",
+ "created_at",
+ "premium_since",
+ "verified",
+ "disabled",
+ "deleted",
+ "email",
+ "flags",
+ "public_flags",
+ "rights",
+ "data",
+ "fingerprints",
+ "extended_settings",
+ "notes",
+ "settingsId"
+ FROM "temporary_users"
+ `);
+ await queryRunner.query(`
+ DROP TABLE "temporary_users"
+ `);
+ }
+
+}
diff --git a/gateway/src/schema/Activity.ts b/src/util/schemas/ActivitySchema.ts
index e18f66c8..e18f66c8 100644
--- a/gateway/src/schema/Activity.ts
+++ b/src/util/schemas/ActivitySchema.ts
diff --git a/src/util/schemas/BanCreateSchema.ts b/src/util/schemas/BanCreateSchema.ts
new file mode 100644
index 00000000..64b02943
--- /dev/null
+++ b/src/util/schemas/BanCreateSchema.ts
@@ -0,0 +1,5 @@
+
+export interface BanCreateSchema {
+ delete_message_days?: string;
+ reason?: string;
+}
diff --git a/src/util/schemas/BanModeratorSchema.ts b/src/util/schemas/BanModeratorSchema.ts
new file mode 100644
index 00000000..b497d319
--- /dev/null
+++ b/src/util/schemas/BanModeratorSchema.ts
@@ -0,0 +1,8 @@
+
+export interface BanModeratorSchema {
+ id: string;
+ user_id: string;
+ guild_id: string;
+ executor_id: string;
+ reason?: string | undefined;
+}
diff --git a/src/util/schemas/BanRegistrySchema.ts b/src/util/schemas/BanRegistrySchema.ts
new file mode 100644
index 00000000..661f934f
--- /dev/null
+++ b/src/util/schemas/BanRegistrySchema.ts
@@ -0,0 +1,9 @@
+
+export interface BanRegistrySchema {
+ id: string;
+ user_id: string;
+ guild_id: string;
+ executor_id: string;
+ ip?: string;
+ reason?: string | undefined;
+}
diff --git a/src/util/schemas/BulkDeleteSchema.ts b/src/util/schemas/BulkDeleteSchema.ts
new file mode 100644
index 00000000..26f88374
--- /dev/null
+++ b/src/util/schemas/BulkDeleteSchema.ts
@@ -0,0 +1,4 @@
+
+export interface BulkDeleteSchema {
+ messages: string[];
+}
diff --git a/src/util/schemas/ChannelModifySchema.ts b/src/util/schemas/ChannelModifySchema.ts
new file mode 100644
index 00000000..3cfcf7d2
--- /dev/null
+++ b/src/util/schemas/ChannelModifySchema.ts
@@ -0,0 +1,29 @@
+import { ChannelPermissionOverwriteType, ChannelType } from "..";
+
+
+export interface ChannelModifySchema {
+ /**
+ * @maxLength 100
+ */
+ name?: string;
+ type?: ChannelType;
+ topic?: string;
+ icon?: string | null;
+ bitrate?: number;
+ user_limit?: number;
+ rate_limit_per_user?: number;
+ position?: number;
+ permission_overwrites?: {
+ id: string;
+ type: ChannelPermissionOverwriteType;
+ allow: string;
+ deny: string;
+ }[];
+ parent_id?: string;
+ id?: string; // is not used (only for guild create)
+ nsfw?: boolean;
+ rtc_region?: string;
+ default_auto_archive_duration?: number;
+ flags?: number;
+ default_thread_rate_limit_per_user?: number;
+}
\ No newline at end of file
diff --git a/src/util/schemas/ChannelPermissionOverwriteSchema.ts b/src/util/schemas/ChannelPermissionOverwriteSchema.ts
new file mode 100644
index 00000000..fe9ba860
--- /dev/null
+++ b/src/util/schemas/ChannelPermissionOverwriteSchema.ts
@@ -0,0 +1,5 @@
+import { ChannelPermissionOverwrite } from "@fosscord/util";
+
+// TODO: Only permissions your bot has in the guild or channel can be allowed/denied (unless your bot has a MANAGE_ROLES overwrite in the channel)
+
+export interface ChannelPermissionOverwriteSchema extends ChannelPermissionOverwrite { }
diff --git a/src/util/schemas/ChannelReorderSchema.ts b/src/util/schemas/ChannelReorderSchema.ts
new file mode 100644
index 00000000..3715f59e
--- /dev/null
+++ b/src/util/schemas/ChannelReorderSchema.ts
@@ -0,0 +1 @@
+export type ChannelReorderSchema = { id: string; position?: number; lock_permissions?: boolean; parent_id?: string }[];
\ No newline at end of file
diff --git a/src/util/schemas/DmChannelCreateSchema.ts b/src/util/schemas/DmChannelCreateSchema.ts
new file mode 100644
index 00000000..d5afc6d7
--- /dev/null
+++ b/src/util/schemas/DmChannelCreateSchema.ts
@@ -0,0 +1,5 @@
+
+export interface DmChannelCreateSchema {
+ name?: string;
+ recipients: string[];
+}
diff --git a/src/util/schemas/EmojiCreateSchema.ts b/src/util/schemas/EmojiCreateSchema.ts
new file mode 100644
index 00000000..d50c419c
--- /dev/null
+++ b/src/util/schemas/EmojiCreateSchema.ts
@@ -0,0 +1,7 @@
+
+export interface EmojiCreateSchema {
+ name?: string;
+ image: string;
+ require_colons?: boolean | null;
+ roles?: string[];
+}
diff --git a/src/util/schemas/EmojiModifySchema.ts b/src/util/schemas/EmojiModifySchema.ts
new file mode 100644
index 00000000..5529dbd5
--- /dev/null
+++ b/src/util/schemas/EmojiModifySchema.ts
@@ -0,0 +1,5 @@
+
+export interface EmojiModifySchema {
+ name?: string;
+ roles?: string[];
+}
diff --git a/src/util/schemas/GuildCreateSchema.ts b/src/util/schemas/GuildCreateSchema.ts
new file mode 100644
index 00000000..e4855119
--- /dev/null
+++ b/src/util/schemas/GuildCreateSchema.ts
@@ -0,0 +1,14 @@
+import { ChannelModifySchema } from ".";
+
+export interface GuildCreateSchema {
+ /**
+ * @maxLength 100
+ */
+ name: string;
+ region?: string;
+ icon?: string | null;
+ channels?: ChannelModifySchema[];
+ guild_template_code?: string;
+ system_channel_id?: string;
+ rules_channel_id?: string;
+}
diff --git a/src/util/schemas/GuildTemplateCreateSchema.ts b/src/util/schemas/GuildTemplateCreateSchema.ts
new file mode 100644
index 00000000..1579001e
--- /dev/null
+++ b/src/util/schemas/GuildTemplateCreateSchema.ts
@@ -0,0 +1,5 @@
+
+export interface GuildTemplateCreateSchema {
+ name: string;
+ avatar?: string | null;
+}
diff --git a/src/util/schemas/GuildUpdateSchema.ts b/src/util/schemas/GuildUpdateSchema.ts
new file mode 100644
index 00000000..86527cf1
--- /dev/null
+++ b/src/util/schemas/GuildUpdateSchema.ts
@@ -0,0 +1,18 @@
+import { GuildCreateSchema } from ".";
+
+export interface GuildUpdateSchema extends Omit<GuildCreateSchema, "channels" | "name"> {
+ name?: string;
+ banner?: string | null;
+ splash?: string | null;
+ description?: string;
+ features?: string[];
+ verification_level?: number;
+ default_message_notifications?: number;
+ system_channel_flags?: number;
+ explicit_content_filter?: number;
+ public_updates_channel_id?: string;
+ afk_timeout?: number;
+ afk_channel_id?: string;
+ preferred_locale?: string;
+ premium_progress_bar_enabled?: boolean;
+}
diff --git a/src/util/schemas/GuildUpdateWelcomeScreenSchema.ts b/src/util/schemas/GuildUpdateWelcomeScreenSchema.ts
new file mode 100644
index 00000000..b1e36920
--- /dev/null
+++ b/src/util/schemas/GuildUpdateWelcomeScreenSchema.ts
@@ -0,0 +1,11 @@
+
+export interface GuildUpdateWelcomeScreenSchema {
+ welcome_channels?: {
+ channel_id: string;
+ description: string;
+ emoji_id?: string;
+ emoji_name: string;
+ }[];
+ enabled?: boolean;
+ description?: string;
+}
diff --git a/gateway/src/schema/Identify.ts b/src/util/schemas/IdentifySchema.ts
index 21141321..f3d60fb3 100644
--- a/gateway/src/schema/Identify.ts
+++ b/src/util/schemas/IdentifySchema.ts
@@ -1,8 +1,8 @@
-import { ActivitySchema } from "./Activity";
+import { ActivitySchema } from "./ActivitySchema";
export const IdentifySchema = {
token: String,
- $intents: BigInt, // discord uses a Integer for bitfields we use bigints tho. | instanceOf will automatically convert the Number to a BigInt
+ $intents: String, // discord uses a Integer for bitfields we use bigints tho. | instanceOf will automatically convert the Number to a BigInt
$properties: Object,
// {
// // discord uses $ in the property key for bots, so we need to double prefix it, because instanceOf treats $ (prefix) as a optional key
@@ -33,7 +33,7 @@ export const IdentifySchema = {
$presence: ActivitySchema,
$compress: Boolean,
$large_threshold: Number,
- $shard: [BigInt, BigInt],
+ $shard: [Number, Number],
$guild_subscriptions: Boolean,
$capabilities: Number,
$client_state: {
@@ -71,11 +71,11 @@ export interface IdentifySchema {
client_version?: string;
system_locale?: string;
};
- intents?: bigint; // discord uses a Integer for bitfields we use bigints tho. | instanceOf will automatically convert the Number to a BigInt
+ intents?: string; // discord uses a Integer for bitfields we use bigints tho. | instanceOf will automatically convert the Number to a BigInt
presence?: ActivitySchema;
compress?: boolean;
large_threshold?: number;
- shard?: [bigint, bigint];
+ shard?: [number, number];
guild_subscriptions?: boolean;
capabilities?: number;
client_state?: {
diff --git a/src/util/schemas/InviteCreateSchema.ts b/src/util/schemas/InviteCreateSchema.ts
new file mode 100644
index 00000000..7f6af338
--- /dev/null
+++ b/src/util/schemas/InviteCreateSchema.ts
@@ -0,0 +1,12 @@
+
+export interface InviteCreateSchema {
+ target_user_id?: string;
+ target_type?: string;
+ validate?: string; // ? what is this
+ max_age?: number;
+ max_uses?: number;
+ temporary?: boolean;
+ unique?: boolean;
+ target_user?: string;
+ target_user_type?: number;
+}
diff --git a/gateway/src/schema/LazyRequest.ts b/src/util/schemas/LazyRequestSchema.ts
index 1fe658bb..1fe658bb 100644
--- a/gateway/src/schema/LazyRequest.ts
+++ b/src/util/schemas/LazyRequestSchema.ts
diff --git a/src/util/schemas/LoginSchema.ts b/src/util/schemas/LoginSchema.ts
new file mode 100644
index 00000000..358019a8
--- /dev/null
+++ b/src/util/schemas/LoginSchema.ts
@@ -0,0 +1,9 @@
+
+export interface LoginSchema {
+ login: string;
+ password: string;
+ undelete?: boolean;
+ captcha_key?: string;
+ login_source?: string;
+ gift_code_sku_id?: string;
+}
diff --git a/src/util/schemas/MemberChangeSchema.ts b/src/util/schemas/MemberChangeSchema.ts
new file mode 100644
index 00000000..a75c0ea0
--- /dev/null
+++ b/src/util/schemas/MemberChangeSchema.ts
@@ -0,0 +1,4 @@
+
+export interface MemberChangeSchema {
+ roles?: string[];
+}
diff --git a/src/util/schemas/MemberNickChangeSchema.ts b/src/util/schemas/MemberNickChangeSchema.ts
new file mode 100644
index 00000000..e6a6a007
--- /dev/null
+++ b/src/util/schemas/MemberNickChangeSchema.ts
@@ -0,0 +1,4 @@
+
+export interface MemberNickChangeSchema {
+ nick: string;
+}
diff --git a/src/util/schemas/MessageAcknowledgeSchema.ts b/src/util/schemas/MessageAcknowledgeSchema.ts
new file mode 100644
index 00000000..3f4eb2b6
--- /dev/null
+++ b/src/util/schemas/MessageAcknowledgeSchema.ts
@@ -0,0 +1,8 @@
+// TODO: public read receipts & privacy scoping
+// TODO: send read state event to all channel members
+// TODO: advance-only notification cursor
+
+export interface MessageAcknowledgeSchema {
+ manual?: boolean;
+ mention_count?: number;
+}
diff --git a/src/util/schemas/MessageCreateSchema.ts b/src/util/schemas/MessageCreateSchema.ts
new file mode 100644
index 00000000..7b1cc7b9
--- /dev/null
+++ b/src/util/schemas/MessageCreateSchema.ts
@@ -0,0 +1,34 @@
+import { Embed } from "@fosscord/util";
+
+
+export interface MessageCreateSchema {
+ type?: number;
+ content?: string;
+ nonce?: string;
+ channel_id?: string;
+ tts?: boolean;
+ flags?: string;
+ embeds?: Embed[];
+ embed?: Embed;
+ // TODO: ^ embed is deprecated in favor of embeds (https://discord.com/developers/docs/resources/channel#message-object)
+ allowed_mentions?: {
+ parse?: string[];
+ roles?: string[];
+ users?: string[];
+ replied_user?: boolean;
+ };
+ message_reference?: {
+ message_id: string;
+ channel_id: string;
+ guild_id?: string;
+ fail_if_not_exists?: boolean;
+ };
+ payload_json?: string;
+ file?: any;
+ /**
+ TODO: we should create an interface for attachments
+ TODO: OpenWAAO<-->attachment-style metadata conversion
+ **/
+ attachments?: any[];
+ sticker_ids?: string[];
+}
diff --git a/src/util/schemas/MfaCodesSchema.ts b/src/util/schemas/MfaCodesSchema.ts
new file mode 100644
index 00000000..53230841
--- /dev/null
+++ b/src/util/schemas/MfaCodesSchema.ts
@@ -0,0 +1,5 @@
+
+export interface MfaCodesSchema {
+ password: string;
+ regenerate?: boolean;
+}
diff --git a/src/util/schemas/ModifyGuildStickerSchema.ts b/src/util/schemas/ModifyGuildStickerSchema.ts
new file mode 100644
index 00000000..6f24e4ce
--- /dev/null
+++ b/src/util/schemas/ModifyGuildStickerSchema.ts
@@ -0,0 +1,16 @@
+
+export interface ModifyGuildStickerSchema {
+ /**
+ * @minLength 2
+ * @maxLength 30
+ */
+ name: string;
+ /**
+ * @maxLength 100
+ */
+ description?: string;
+ /**
+ * @maxLength 200
+ */
+ tags: string;
+}
diff --git a/src/util/schemas/PruneSchema.ts b/src/util/schemas/PruneSchema.ts
new file mode 100644
index 00000000..eebac763
--- /dev/null
+++ b/src/util/schemas/PruneSchema.ts
@@ -0,0 +1,7 @@
+
+export interface PruneSchema {
+ /**
+ * @min 0
+ */
+ days: number;
+}
diff --git a/src/util/schemas/PurgeSchema.ts b/src/util/schemas/PurgeSchema.ts
new file mode 100644
index 00000000..0eeef6f2
--- /dev/null
+++ b/src/util/schemas/PurgeSchema.ts
@@ -0,0 +1,5 @@
+
+export interface PurgeSchema {
+ before: string;
+ after: string;
+}
diff --git a/src/util/schemas/RegisterSchema.ts b/src/util/schemas/RegisterSchema.ts
new file mode 100644
index 00000000..e53330d2
--- /dev/null
+++ b/src/util/schemas/RegisterSchema.ts
@@ -0,0 +1,27 @@
+
+export interface RegisterSchema {
+ /**
+ * @minLength 2
+ * @maxLength 32
+ */
+ username: string;
+ /**
+ * @minLength 1
+ * @maxLength 72
+ */
+ password?: string;
+ consent: boolean;
+ /**
+ * @TJS-format email
+ */
+ email?: string;
+ fingerprint?: string;
+ invite?: string;
+ /**
+ * @TJS-type string
+ */
+ date_of_birth?: Date; // "2000-04-03"
+ gift_code_sku_id?: string;
+ captcha_key?: string;
+ promotional_email_opt_in?: boolean;
+}
diff --git a/src/util/schemas/RelationshipPostSchema.ts b/src/util/schemas/RelationshipPostSchema.ts
new file mode 100644
index 00000000..40093700
--- /dev/null
+++ b/src/util/schemas/RelationshipPostSchema.ts
@@ -0,0 +1,5 @@
+
+export interface RelationshipPostSchema {
+ discriminator: string;
+ username: string;
+}
diff --git a/src/util/schemas/RelationshipPutSchema.ts b/src/util/schemas/RelationshipPutSchema.ts
new file mode 100644
index 00000000..f46966e0
--- /dev/null
+++ b/src/util/schemas/RelationshipPutSchema.ts
@@ -0,0 +1,6 @@
+import { RelationshipType } from "@fosscord/util";
+
+
+export interface RelationshipPutSchema {
+ type?: RelationshipType;
+}
diff --git a/src/util/schemas/RoleModifySchema.ts b/src/util/schemas/RoleModifySchema.ts
new file mode 100644
index 00000000..d08a5022
--- /dev/null
+++ b/src/util/schemas/RoleModifySchema.ts
@@ -0,0 +1,11 @@
+
+export interface RoleModifySchema {
+ name?: string;
+ permissions?: string;
+ color?: number;
+ hoist?: boolean; // whether the role should be displayed separately in the sidebar
+ mentionable?: boolean; // whether the role should be mentionable
+ position?: number;
+ icon?: string;
+ unicode_emoji?: string;
+}
diff --git a/src/util/schemas/RolePositionUpdateSchema.ts b/src/util/schemas/RolePositionUpdateSchema.ts
new file mode 100644
index 00000000..1019d504
--- /dev/null
+++ b/src/util/schemas/RolePositionUpdateSchema.ts
@@ -0,0 +1,4 @@
+export type RolePositionUpdateSchema = {
+ id: string;
+ position: number;
+}[];
\ No newline at end of file
diff --git a/src/util/schemas/TemplateCreateSchema.ts b/src/util/schemas/TemplateCreateSchema.ts
new file mode 100644
index 00000000..72c19f68
--- /dev/null
+++ b/src/util/schemas/TemplateCreateSchema.ts
@@ -0,0 +1,5 @@
+
+export interface TemplateCreateSchema {
+ name: string;
+ description?: string;
+}
diff --git a/src/util/schemas/TemplateModifySchema.ts b/src/util/schemas/TemplateModifySchema.ts
new file mode 100644
index 00000000..2231a1d2
--- /dev/null
+++ b/src/util/schemas/TemplateModifySchema.ts
@@ -0,0 +1,5 @@
+
+export interface TemplateModifySchema {
+ name: string;
+ description?: string;
+}
diff --git a/src/util/schemas/TotpDisableSchema.ts b/src/util/schemas/TotpDisableSchema.ts
new file mode 100644
index 00000000..b73db64e
--- /dev/null
+++ b/src/util/schemas/TotpDisableSchema.ts
@@ -0,0 +1,4 @@
+
+export interface TotpDisableSchema {
+ code: string;
+}
diff --git a/src/util/schemas/TotpEnableSchema.ts b/src/util/schemas/TotpEnableSchema.ts
new file mode 100644
index 00000000..44d9ebac
--- /dev/null
+++ b/src/util/schemas/TotpEnableSchema.ts
@@ -0,0 +1,6 @@
+
+export interface TotpEnableSchema {
+ password: string;
+ code?: string;
+ secret?: string;
+}
diff --git a/src/util/schemas/TotpSchema.ts b/src/util/schemas/TotpSchema.ts
new file mode 100644
index 00000000..fe54735e
--- /dev/null
+++ b/src/util/schemas/TotpSchema.ts
@@ -0,0 +1,7 @@
+
+export interface TotpSchema {
+ code: string;
+ ticket: string;
+ gift_code_sku_id?: string | null;
+ login_source?: string | null;
+}
diff --git a/src/util/schemas/UserModifySchema.ts b/src/util/schemas/UserModifySchema.ts
new file mode 100644
index 00000000..659f5841
--- /dev/null
+++ b/src/util/schemas/UserModifySchema.ts
@@ -0,0 +1,19 @@
+
+export interface UserModifySchema {
+ /**
+ * @minLength 1
+ * @maxLength 100
+ */
+ username?: string;
+ discriminator?: string;
+ avatar?: string | null;
+ /**
+ * @maxLength 1024
+ */
+ bio?: string;
+ accent_color?: number;
+ banner?: string | null;
+ password?: string;
+ new_password?: string;
+ code?: string;
+}
diff --git a/src/util/schemas/UserSettingsSchema.ts b/src/util/schemas/UserSettingsSchema.ts
new file mode 100644
index 00000000..b497dff2
--- /dev/null
+++ b/src/util/schemas/UserSettingsSchema.ts
@@ -0,0 +1,4 @@
+import { UserSettings } from "@fosscord/util";
+
+
+export interface UserSettingsSchema extends Partial<UserSettings> { }
diff --git a/src/util/schemas/VanityUrlSchema.ts b/src/util/schemas/VanityUrlSchema.ts
new file mode 100644
index 00000000..de32695a
--- /dev/null
+++ b/src/util/schemas/VanityUrlSchema.ts
@@ -0,0 +1,8 @@
+
+export interface VanityUrlSchema {
+ /**
+ * @minLength 1
+ * @maxLength 20
+ */
+ code?: string;
+}
diff --git a/src/util/schemas/VoiceStateUpdateSchema.ts b/src/util/schemas/VoiceStateUpdateSchema.ts
new file mode 100644
index 00000000..02bb141b
--- /dev/null
+++ b/src/util/schemas/VoiceStateUpdateSchema.ts
@@ -0,0 +1,18 @@
+export const VoiceStateUpdateSchema = {
+ $guild_id: String,
+ $channel_id: String,
+ self_mute: Boolean,
+ self_deaf: Boolean,
+ self_video: Boolean,
+};
+
+//TODO need more testing when community guild and voice stage channel are working
+export interface VoiceStateUpdateSchema {
+ channel_id: string;
+ guild_id?: string;
+ suppress?: boolean;
+ request_to_speak_timestamp?: Date;
+ self_mute?: boolean;
+ self_deaf?: boolean;
+ self_video?: boolean;
+}
\ No newline at end of file
diff --git a/src/util/schemas/WebhookCreateSchema.ts b/src/util/schemas/WebhookCreateSchema.ts
new file mode 100644
index 00000000..12ab1869
--- /dev/null
+++ b/src/util/schemas/WebhookCreateSchema.ts
@@ -0,0 +1,8 @@
+// TODO: webhooks
+export interface WebhookCreateSchema {
+ /**
+ * @maxLength 80
+ */
+ name: string;
+ avatar?: string;
+}
diff --git a/src/util/schemas/WidgetModifySchema.ts b/src/util/schemas/WidgetModifySchema.ts
new file mode 100644
index 00000000..390efc30
--- /dev/null
+++ b/src/util/schemas/WidgetModifySchema.ts
@@ -0,0 +1,5 @@
+
+export interface WidgetModifySchema {
+ enabled: boolean; // whether the widget is enabled
+ channel_id: string; // the widget channel id
+}
diff --git a/src/util/schemas/index.ts b/src/util/schemas/index.ts
new file mode 100644
index 00000000..a15ab4b0
--- /dev/null
+++ b/src/util/schemas/index.ts
@@ -0,0 +1,43 @@
+export * from "./ActivitySchema";
+export * from "./BanCreateSchema";
+export * from "./BanModeratorSchema";
+export * from "./BanRegistrySchema";
+export * from "./BulkDeleteSchema";
+export * from "./ChannelModifySchema";
+export * from "./ChannelPermissionOverwriteSchema";
+export * from "./ChannelReorderSchema";
+export * from "./DmChannelCreateSchema";
+export * from "./EmojiCreateSchema";
+export * from "./EmojiModifySchema";
+export * from "./GuildCreateSchema";
+export * from "./GuildTemplateCreateSchema";
+export * from "./GuildUpdateSchema";
+export * from "./GuildUpdateWelcomeScreenSchema";
+export * from "./IdentifySchema";
+export * from "./InviteCreateSchema";
+export * from "./LazyRequestSchema";
+export * from "./LoginSchema";
+export * from "./MemberChangeSchema";
+export * from "./MemberNickChangeSchema";
+export * from "./MessageAcknowledgeSchema";
+export * from "./MessageCreateSchema";
+export * from "./MfaCodesSchema";
+export * from "./ModifyGuildStickerSchema";
+export * from "./PruneSchema";
+export * from "./PurgeSchema";
+export * from "./RegisterSchema";
+export * from "./RelationshipPostSchema";
+export * from "./RelationshipPutSchema";
+export * from "./RoleModifySchema";
+export * from "./RolePositionUpdateSchema";
+export * from "./TemplateCreateSchema";
+export * from "./TemplateModifySchema";
+export * from "./TotpDisableSchema";
+export * from "./TotpEnableSchema";
+export * from "./TotpSchema";
+export * from "./UserModifySchema";
+export * from "./UserSettingsSchema";
+export * from "./VanityUrlSchema";
+export * from "./VoiceStateUpdateSchema";
+export * from "./WebhookCreateSchema";
+export * from "./WidgetModifySchema";
diff --git a/util/src/util/ApiError.ts b/src/util/util/ApiError.ts
index f1a9b4f6..f1a9b4f6 100644
--- a/util/src/util/ApiError.ts
+++ b/src/util/util/ApiError.ts
diff --git a/util/src/util/Array.ts b/src/util/util/Array.ts
index 5a45d1b5..5a45d1b5 100644
--- a/util/src/util/Array.ts
+++ b/src/util/util/Array.ts
diff --git a/util/src/util/AutoUpdate.ts b/src/util/util/AutoUpdate.ts
index 531bd8b7..7d020106 100644
--- a/util/src/util/AutoUpdate.ts
+++ b/src/util/util/AutoUpdate.ts
@@ -1,4 +1,3 @@
-import "missing-native-js-functions";
import fetch from "node-fetch";
import ProxyAgent from 'proxy-agent';
import readline from "readline";
@@ -18,7 +17,7 @@ export function enableAutoUpdate(opts: {
downloadType?: "zip";
}) {
if (!opts.checkInterval) return;
- var interval = 1000 * 60 * 60 * 24;
+ let interval = 1000 * 60 * 60 * 24;
if (typeof opts.checkInterval === "number") opts.checkInterval = 1000 * interval;
const i = setInterval(async () => {
@@ -76,7 +75,7 @@ async function getLatestVersion(url: string) {
try {
const agent = new ProxyAgent();
const response = await fetch(url, { agent });
- const content = await response.json();
+ const content: any = await response.json();
return content.version;
} catch (error) {
throw new Error("[Auto update] check failed for " + url);
diff --git a/util/src/util/BitField.ts b/src/util/util/BitField.ts
index fb887e05..9bdbf6d7 100644
--- a/util/src/util/BitField.ts
+++ b/src/util/util/BitField.ts
@@ -138,6 +138,9 @@ export class BitField {
return bit.map((p) => resolve.call(this, p)).reduce((prev, p) => BigInt(prev) | BigInt(p), BigInt(0));
}
if (typeof bit === "string" && typeof FLAGS[bit] !== "undefined") return FLAGS[bit];
+ if (bit === "0") return BigInt(0); //special case: 0
+ if (typeof bit === "string") return BigInt(bit); //last ditch effort...
+ if(/--debug|--inspect/.test(process.execArgv.join(' '))) debugger; //if you're here, we have an invalid bitfield... if bit is 0, thats fine, I guess...
throw new RangeError("BITFIELD_INVALID: " + bit);
}
}
diff --git a/util/src/util/Categories.ts b/src/util/util/Categories.ts
index a3c69da7..a3c69da7 100644
--- a/util/src/util/Categories.ts
+++ b/src/util/util/Categories.ts
diff --git a/util/src/util/Config.ts b/src/util/util/Config.ts
index 31b8d97c..e0fb2a81 100644
--- a/util/src/util/Config.ts
+++ b/src/util/util/Config.ts
@@ -1,13 +1,13 @@
-import "missing-native-js-functions";
-import { ConfigValue, ConfigEntity, DefaultConfigOptions } from "../entities/Config";
-import path from "path";
+import { ConfigEntity } from "../entities/Config";
import fs from "fs";
+import { ConfigValue } from "../config";
+import { OrmUtils } from ".";
// TODO: yaml instead of json
-// const overridePath = path.join(process.cwd(), "config.json");
+const overridePath = process.env.CONFIG_PATH ?? "";
-var config: ConfigValue;
-var pairs: ConfigEntity[];
+let config: ConfigValue;
+let pairs: ConfigEntity[];
// TODO: use events to inform about config updates
// Config keys are separated with _
@@ -15,20 +15,29 @@ var pairs: ConfigEntity[];
export const Config = {
init: async function init() {
if (config) return config;
+ console.log('[Config] Loading configuration...')
pairs = await ConfigEntity.find();
config = pairsToConfig(pairs);
- config = (config || {}).merge(DefaultConfigOptions);
-
- // try {
- // const overrideConfig = JSON.parse(fs.readFileSync(overridePath, { encoding: "utf8" }));
- // config = overrideConfig.merge(config);
- // } catch (error) {
- // fs.writeFileSync(overridePath, JSON.stringify(config, null, 4));
- // }
+ //config = (config || {}).merge(new ConfigValue());
+ config = OrmUtils.mergeDeep(new ConfigValue(), config)
+
+ if(process.env.CONFIG_PATH)
+ try {
+ const overrideConfig = JSON.parse(fs.readFileSync(overridePath, { encoding: "utf8" }));
+ config = overrideConfig.merge(config);
+ } catch (error) {
+ fs.writeFileSync(overridePath, JSON.stringify(config, null, 4));
+ }
+
return this.set(config);
},
get: function get() {
+ if(!config) {
+ if(/--debug|--inspect/.test(process.execArgv.join(' ')))
+ console.log("Oops.. trying to get config without config existing... Returning defaults... (Is the database still initialising?)");
+ return new ConfigValue();
+ }
return config;
},
set: function set(val: Partial<ConfigValue>) {
@@ -51,13 +60,17 @@ function applyConfig(val: ConfigValue) {
pair.value = obj;
return pair.save();
}
- // fs.writeFileSync(overridePath, JSON.stringify(val, null, 4));
+ if(process.env.CONFIG_PATH) {
+ if(/--debug|--inspect/.test(process.execArgv.join(' ')))
+ console.log(`Writing config: ${process.env.CONFIG_PATH}`)
+ fs.writeFileSync(overridePath, JSON.stringify(val, null, 4));
+ }
return apply(val);
}
function pairsToConfig(pairs: ConfigEntity[]) {
- var value: any = {};
+ let value: any = {};
pairs.forEach((p) => {
const keys = p.key.split("_");
diff --git a/util/src/util/Constants.ts b/src/util/util/Constants.ts
index a5d3fcd2..a5d3fcd2 100644
--- a/util/src/util/Constants.ts
+++ b/src/util/util/Constants.ts
diff --git a/src/util/util/Database.ts b/src/util/util/Database.ts
new file mode 100644
index 00000000..84ce473d
--- /dev/null
+++ b/src/util/util/Database.ts
@@ -0,0 +1,103 @@
+import path from "path";
+import "reflect-metadata";
+import { DataSource, createConnection, DataSourceOptions, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
+import * as Models from "../entities";
+import { Migration } from "../entities/Migration";
+import { yellow, green, red } from "picocolors";
+import fs from "fs";
+import { exit } from "process";
+import { BaseClass, BaseClassWithoutId } from "../entities";
+import { config } from "dotenv";
+
+// UUID extension option is only supported with postgres
+// We want to generate all id's with Snowflakes that's why we have our own BaseEntity class
+
+let promise: Promise<any>;
+let dataSource: DataSource;
+
+export async function getOrInitialiseDatabase(): Promise<DataSource> {
+ //if (dataSource) return dataSource; // prevent initalizing multiple times
+
+ if(dataSource.isInitialized) return dataSource;
+
+ await dataSource.initialize();
+ console.log(`[Database] ${green("Connected!")}`);
+ await dataSource.runMigrations();
+ console.log(`[Database] ${green("Up to date!")}`);
+
+ if("DB_MIGRATE" in process.env) {
+ console.log("DB_MIGRATE specified, exiting!")
+ exit(0);
+ }
+ return dataSource;
+}
+
+export function closeDatabase() {
+ dataSource?.destroy();
+}
+
+function getDataSourceOptions(): DataSourceOptions {
+ config();
+ //get connection string and check for migrations
+ const dbConnectionString = process.env.DATABASE || path.join(process.cwd(), "database.db");
+ const type = dbConnectionString.includes("://") ? dbConnectionString.split(":")[0]?.replace("+srv", "") : "sqlite" as any;
+ const isSqlite = type.includes("sqlite");
+ const migrationsExist = fs.existsSync(path.join(__dirname, "..", "migrations", type));
+ //read env vars
+ const synchronizeInsteadOfMigrations = "DB_UNSAFE" in process.env;
+ const verboseDb = "DB_VERBOSE" in process.env;
+
+ if(isSqlite)
+ console.log(`[Database] ${red(`You are running sqlite! Please keep in mind that we recommend setting up a dedicated database!`)}`);
+ if(verboseDb)
+ console.log(`[Database] ${red(`Verbose database logging is enabled, this might impact performance! Unset DB_VERBOSE to disable.`)}`);
+
+ if(synchronizeInsteadOfMigrations){
+ console.log(`[Database] ${red(`Unsafe database upgrades are enabled! We are not responsible for broken databases! Unset DB_UNSAFE to disable.`)}`);
+ }
+ else if(!migrationsExist) {
+ console.log(`[Database] ${red(`Database engine not supported! Set UNSAFE_DB to bypass.`)}`);
+ console.log(`[Database] ${red(`Please mention this to Fosscord developers, and provide this info:`)}`);
+ console.log(`[Database]\n${red(JSON.stringify({
+ db_type: type,
+ migrations_exist: migrationsExist
+ }, null, 4))}`);
+
+ if(!("DB_MIGRATE" in process.env)) exit(1);
+ }
+ console.log(`[Database] ${yellow(`Configuring data source to use ${type} database...`)}`);
+ return {
+ type,
+ charset: 'utf8mb4',
+ url: isSqlite ? undefined : dbConnectionString,
+ database: isSqlite ? dbConnectionString : undefined,
+ // @ts-ignore
+ //entities: Object.values(Models).filter((x) => x.constructor.name !== "Object" && x.constructor.name !== "Array" && x.constructor.name !== "BigInt" && x).map(x=>x.name),
+ entities: Object.values(Models).filter((x) => x.constructor.name == "Function" && shouldIncludeEntity(x.name)),
+ synchronize: synchronizeInsteadOfMigrations,
+ logging: verboseDb,
+ cache: {
+ duration: 1000 * 3, // cache all find queries for 3 seconds
+ },
+ bigNumberStrings: false,
+ supportBigNumbers: true,
+ name: "default",
+ migrations: synchronizeInsteadOfMigrations ? [] : [path.join(__dirname, "..", "migrations", type, "*.js")],
+ migrationsRun: !synchronizeInsteadOfMigrations,
+ //migrationsRun: false,
+ cli: {
+ migrationsDir: `src/migrations/${type}`
+ },
+ } as DataSourceOptions;
+}
+
+function shouldIncludeEntity(name: string): boolean {
+ return ![
+ BaseClassWithoutId,
+ PrimaryColumn,
+ BaseClass,
+ PrimaryGeneratedColumn
+ ].map(x=>x.name).includes(name);
+}
+
+export default dataSource = new DataSource(getDataSourceOptions());
diff --git a/util/src/util/Email.ts b/src/util/util/Email.ts
index 6885da33..6885da33 100644
--- a/util/src/util/Email.ts
+++ b/src/util/util/Email.ts
diff --git a/util/src/util/Event.ts b/src/util/util/Event.ts
index bb624051..90c24347 100644
--- a/util/src/util/Event.ts
+++ b/src/util/util/Event.ts
@@ -58,8 +58,8 @@ export async function listenEvent(event: string, callback: (event: EventOpts) =>
process.setMaxListeners(process.getMaxListeners() - 1);
};
- const listener = (msg: ProcessEvent) => {
- msg.type === "event" && msg.id === event && callback({ ...msg.event, cancel });
+ const listener = (message: any) => {
+ message.type === "event" && message.id === event && callback({ ...message.event, cancel });
};
process.addListener("message", listener);
diff --git a/util/src/util/FieldError.ts b/src/util/util/FieldError.ts
index 406b33e8..49968e1a 100644
--- a/util/src/util/FieldError.ts
+++ b/src/util/util/FieldError.ts
@@ -1,5 +1,3 @@
-import "missing-native-js-functions";
-
export function FieldErrors(fields: Record<string, { code?: string; message: string }>) {
return new FieldError(
50035,
diff --git a/util/src/util/Intents.ts b/src/util/util/Intents.ts
index 1e840b76..1e840b76 100644
--- a/util/src/util/Intents.ts
+++ b/src/util/util/Intents.ts
diff --git a/util/src/util/InvisibleCharacters.ts b/src/util/util/InvisibleCharacters.ts
index 2b014e14..2b014e14 100644
--- a/util/src/util/InvisibleCharacters.ts
+++ b/src/util/util/InvisibleCharacters.ts
diff --git a/src/util/util/MFA.ts b/src/util/util/MFA.ts
new file mode 100644
index 00000000..2e47b2fc
--- /dev/null
+++ b/src/util/util/MFA.ts
@@ -0,0 +1,17 @@
+import crypto from "crypto";
+import { BackupCode } from "../entities/BackupCodes";
+
+export function generateMfaBackupCodes(user_id: string) {
+ let backup_codes: BackupCode[] = [];
+ for (let i = 0; i < 10; i++) {
+ const code = BackupCode.create({
+ user: { id: user_id },
+ code: crypto.randomBytes(4).toString("hex"), // 8 characters
+ consumed: false,
+ expired: false,
+ });
+ backup_codes.push(code);
+ }
+
+ return backup_codes;
+}
\ No newline at end of file
diff --git a/util/src/util/MessageFlags.ts b/src/util/util/MessageFlags.ts
index b59295c4..b59295c4 100644
--- a/util/src/util/MessageFlags.ts
+++ b/src/util/util/MessageFlags.ts
diff --git a/util/src/util/Permissions.ts b/src/util/util/Permissions.ts
index e5459ab5..c7400303 100644
--- a/util/src/util/Permissions.ts
+++ b/src/util/util/Permissions.ts
@@ -1,17 +1,8 @@
// https://github.com/discordjs/discord.js/blob/master/src/util/Permissions.js
// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
import { Channel, ChannelPermissionOverwrite, Guild, Member, Role } from "../entities";
-import { BitField } from "./BitField";
-import "missing-native-js-functions";
-import { BitFieldResolvable, BitFlag } from "./BitField";
-
-var HTTPError: any;
-
-try {
- HTTPError = require("lambert-server").HTTPError;
-} catch (e) {
- HTTPError = Error;
-}
+import { BitField, BitFieldResolvable, BitFlag } from "./BitField";
+import { HTTPError } from "..";
export type PermissionResolvable = bigint | number | Permissions | PermissionResolvable[] | PermissionString;
@@ -207,9 +198,9 @@ export async function getPermission(
} = {}
) {
if (!user_id) throw new HTTPError("User not found");
- var channel: Channel | undefined;
- var member: Member | undefined;
- var guild: Guild | undefined;
+ let channel: Channel | undefined;
+ let member: Member | undefined;
+ let guild: Guild | undefined;
if (channel_id) {
channel = await Channel.findOneOrFail({
@@ -247,6 +238,7 @@ export async function getPermission(
select: [
"id",
"roles",
+ "index",
// @ts-ignore
...(opts.member_select || []),
],
@@ -257,7 +249,7 @@ export async function getPermission(
if (!recipient_ids?.length) recipient_ids = null;
// TODO: remove guild.roles and convert recipient_ids to recipients
- var permission = Permissions.finalPermission({
+ let permission = Permissions.finalPermission({
user: {
id: user_id,
roles: member?.roles.map((x) => x.id) || [],
diff --git a/util/src/util/RabbitMQ.ts b/src/util/util/RabbitMQ.ts
index 0f5eb6aa..0f5eb6aa 100644
--- a/util/src/util/RabbitMQ.ts
+++ b/src/util/util/RabbitMQ.ts
diff --git a/util/src/util/Regex.ts b/src/util/util/Regex.ts
index 83fc9fe8..83fc9fe8 100644
--- a/util/src/util/Regex.ts
+++ b/src/util/util/Regex.ts
diff --git a/util/src/util/Rights.ts b/src/util/util/Rights.ts
index b28c75b7..1c3906fb 100644
--- a/util/src/util/Rights.ts
+++ b/src/util/util/Rights.ts
@@ -1,15 +1,6 @@
-import { BitField } from "./BitField";
-import "missing-native-js-functions";
-import { BitFieldResolvable, BitFlag } from "./BitField";
+import { BitField, BitFieldResolvable, BitFlag } from "./BitField";
import { User } from "../entities";
-
-var HTTPError: any;
-
-try {
- HTTPError = require("lambert-server").HTTPError;
-} catch (e) {
- HTTPError = Error;
-}
+import { HTTPError } from "..";
export type RightResolvable = bigint | number | Rights | RightResolvable[] | RightString;
diff --git a/util/src/util/Snowflake.ts b/src/util/util/Snowflake.ts
index 134d526e..0ef178fe 100644
--- a/util/src/util/Snowflake.ts
+++ b/src/util/util/Snowflake.ts
@@ -84,10 +84,10 @@ export class Snowflake {
}
static generateWorkerProcess() { // worker process - returns a number
- var time = BigInt(Date.now() - Snowflake.EPOCH) << BigInt(22);
- var worker = Snowflake.workerId << 17n;
- var process = Snowflake.processId << 12n;
- var increment = Snowflake.INCREMENT++;
+ let time = BigInt(Date.now() - Snowflake.EPOCH) << BigInt(22);
+ let worker = Snowflake.workerId << 17n;
+ let process = Snowflake.processId << 12n;
+ let increment = Snowflake.INCREMENT++;
return BigInt(time | worker | process | increment);
}
diff --git a/util/src/util/String.ts b/src/util/util/String.ts
index 55f11e8d..55f11e8d 100644
--- a/util/src/util/String.ts
+++ b/src/util/util/String.ts
diff --git a/util/src/util/Token.ts b/src/util/util/Token.ts
index 500ace45..5a3922d1 100644
--- a/util/src/util/Token.ts
+++ b/src/util/util/Token.ts
@@ -15,10 +15,10 @@ export function checkToken(token: string, jwtSecret: string): Promise<any> {
jwt.verify(token, jwtSecret, JWTOptions, async (err, decoded: any) => {
if (err || !decoded) return rej("Invalid Token");
- const user = await User.findOne(
- { id: decoded.id },
- { select: ["data", "bot", "disabled", "deleted", "rights"] }
- );
+ const user = await User.findOne({
+ where: { id: decoded.id },
+ select: ["data", "bot", "disabled", "deleted", "rights"]
+ });
if (!user) return rej("Invalid Token");
// we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds
if (decoded.iat * 1000 < new Date(user.data.valid_tokens_since).setSeconds(0, 0))
diff --git a/util/src/util/TraverseDirectory.ts b/src/util/util/TraverseDirectory.ts
index 3d0d6279..3d0d6279 100644
--- a/util/src/util/TraverseDirectory.ts
+++ b/src/util/util/TraverseDirectory.ts
diff --git a/util/src/util/cdn.ts b/src/util/util/cdn.ts
index ea950cd1..9cfe4896 100644
--- a/util/src/util/cdn.ts
+++ b/src/util/util/cdn.ts
@@ -1,8 +1,9 @@
import FormData from "form-data";
-import { HTTPError } from "lambert-server";
-import fetch from "node-fetch";
+import { HTTPError } from "..";
import { Config } from "./Config";
import multer from "multer";
+import fetch from "node-fetch"
+import { nodeModuleNameResolver } from "typescript";
export async function uploadFile(path: string, file?: Express.Multer.File) {
if (!file?.buffer) throw new HTTPError("Missing file in body");
diff --git a/src/util/util/imports/Checks.ts b/src/util/util/imports/Checks.ts
new file mode 100644
index 00000000..19a84171
--- /dev/null
+++ b/src/util/util/imports/Checks.ts
@@ -0,0 +1,125 @@
+//source: https://github.com/Flam3rboy/-server/blob/master/src/check.ts
+import { NextFunction, Request, Response } from "express";
+import { HTTPError } from ".";
+
+const OPTIONAL_PREFIX = "$";
+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 check(schema: any) {
+ return (req: Request, res: Response, next: NextFunction) => {
+ try {
+ const result = instanceOf(schema, req.body, { path: "body" });
+ if (result === true) return next();
+ throw result;
+ } catch (error) {
+ next(new HTTPError((error as any).toString(), 400));
+ }
+ };
+}
+export class Tuple {
+ public types: any[];
+ constructor(...types: any[]) {
+ this.types = types;
+ }
+}
+
+export class Email {
+ constructor(public email: string) {}
+ check() {
+ return !!this.email.match(EMAIL_REGEX);
+ }
+}
+export function instanceOf(
+ type: any,
+ value: any,
+ { path = "", optional = false }: { path?: string; optional?: boolean } = {}
+): boolean {
+ if (!type) return true; // no type was specified
+
+ if (value == null) {
+ if (optional) return true;
+ throw `${path} is required`;
+ }
+
+ switch (type) {
+ case String:
+ if (typeof value === "string") return true;
+ throw `${path} must be a string`;
+ case Number:
+ value = Number(value);
+ if (typeof value === "number" && !isNaN(value)) return true;
+ throw `${path} must be a number`;
+ case BigInt:
+ try {
+ value = BigInt(value);
+ if (typeof value === "bigint") return true;
+ } catch (error) {}
+ throw `${path} must be a bigint`;
+ case Boolean:
+ if (value == "true") value = true;
+ if (value == "false") value = false;
+ if (typeof value === "boolean") return true;
+ throw `${path} must be a boolean`;
+ case Object:
+ if (typeof value === "object" && value !== null) return true;
+ throw `${path} must be a object`;
+ }
+
+ if (typeof type === "object") {
+ if (Array.isArray(type)) {
+ if (!Array.isArray(value)) throw `${path} must be an array`;
+ if (!type.length) return true; // type array didn't specify any type
+
+ return value.every((val, i) => instanceOf(type[0], val, { path: `${path}[${i}]`, optional }));
+ }
+ if (type?.constructor?.name != "Object") {
+ if (type instanceof Tuple) {
+ if (
+ (<Tuple>type).types.some((x) => {
+ try {
+ return instanceOf(x, value, { path, optional });
+ } catch (error) {
+ return false;
+ }
+ })
+ ) {
+ return true;
+ }
+ throw `${path} must be one of ${type.types}`;
+ }
+ if (type instanceof Email) {
+ if ((<Email>type).check()) return true;
+ throw `${path} is not a valid E-Mail`;
+ }
+ if (value instanceof type) return true;
+ throw `${path} must be an instance of ${type}`;
+ }
+ if (typeof value !== "object") throw `${path} must be a object`;
+
+ const diff = Object.keys(value).missing(
+ Object.keys(type).map((x) => (x.startsWith(OPTIONAL_PREFIX) ? x.slice(OPTIONAL_PREFIX.length) : x))
+ );
+
+ if (diff.length) throw `Unkown key ${diff}`;
+
+ return Object.keys(type).every((key) => {
+ let newKey = key;
+ const OPTIONAL = key.startsWith(OPTIONAL_PREFIX);
+ if (OPTIONAL) newKey = newKey.slice(OPTIONAL_PREFIX.length);
+
+ return instanceOf(type[key], value[newKey], {
+ path: `${path}.${newKey}`,
+ optional: OPTIONAL,
+ });
+ });
+ } else if (typeof type === "number" || typeof type === "string" || typeof type === "boolean") {
+ if (value === type) return true;
+ throw `${path} must be ${value}`;
+ } else if (typeof type === "bigint") {
+ if (BigInt(value) === type) return true;
+ throw `${path} must be ${value}`;
+ }
+
+ return type == value;
+}
diff --git a/src/util/util/imports/HTTPError.ts b/src/util/util/imports/HTTPError.ts
new file mode 100644
index 00000000..56a7dd55
--- /dev/null
+++ b/src/util/util/imports/HTTPError.ts
@@ -0,0 +1,5 @@
+export class HTTPError extends Error {
+ constructor(message: string, public code: number = 400) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/src/util/util/imports/OrmUtils.ts b/src/util/util/imports/OrmUtils.ts
new file mode 100644
index 00000000..91d88172
--- /dev/null
+++ b/src/util/util/imports/OrmUtils.ts
@@ -0,0 +1,113 @@
+//source: https://github.com/typeorm/typeorm/blob/master/src/util/OrmUtils.ts
+export class OrmUtils {
+ // Checks if it's an object made by Object.create(null), {} or new Object()
+ private static isPlainObject(item: any) {
+ if (item === null || item === undefined) {
+ return false
+ }
+
+ return !item.constructor || item.constructor === Object
+ }
+
+ private static mergeArrayKey(
+ target: any,
+ key: number,
+ value: any,
+ memo: Map<any, any>,
+ ) {
+ // Have we seen this before? Prevent infinite recursion.
+ if (memo.has(value)) {
+ target[key] = memo.get(value)
+ return
+ }
+
+ if (value instanceof Promise) {
+ // Skip promises entirely.
+ // This is a hold-over from the old code & is because we don't want to pull in
+ // the lazy fields. Ideally we'd remove these promises via another function first
+ // but for now we have to do it here.
+ return
+ }
+
+ if (!this.isPlainObject(value) && !Array.isArray(value)) {
+ target[key] = value
+ return
+ }
+
+ if (!target[key]) {
+ target[key] = Array.isArray(value) ? [] : {}
+ }
+
+ memo.set(value, target[key])
+ this.merge(target[key], value, memo)
+ memo.delete(value)
+ }
+
+ private static mergeObjectKey(
+ target: any,
+ key: string,
+ value: any,
+ memo: Map<any, any>,
+ ) {
+ // Have we seen this before? Prevent infinite recursion.
+ if (memo.has(value)) {
+ Object.assign(target, { [key]: memo.get(value) })
+ return
+ }
+
+ if (value instanceof Promise) {
+ // Skip promises entirely.
+ // This is a hold-over from the old code & is because we don't want to pull in
+ // the lazy fields. Ideally we'd remove these promises via another function first
+ // but for now we have to do it here.
+ return
+ }
+
+ if (!this.isPlainObject(value) && !Array.isArray(value)) {
+ Object.assign(target, { [key]: value })
+ return
+ }
+
+ if (!target[key]) {
+ Object.assign(target, { [key]: value })
+ }
+
+ memo.set(value, target[key])
+ this.merge(target[key], value, memo)
+ memo.delete(value)
+ }
+
+ private static merge(
+ target: any,
+ source: any,
+ memo: Map<any, any> = new Map(),
+ ): any {
+ if (Array.isArray(target) && Array.isArray(source)) {
+ for (let key = 0; key < source.length; key++) {
+ this.mergeArrayKey(target, key, source[key], memo)
+ }
+ }
+ else {
+ for (const key of Object.keys(source)) {
+ this.mergeObjectKey(target, key, source[key], memo)
+ }
+ }
+
+
+ }
+
+ /**
+ * Deep Object.assign.
+ */
+ static mergeDeep(target: any, ...sources: any[]): any {
+ if (!sources.length) {
+ return target
+ }
+
+ for (const source of sources) {
+ OrmUtils.merge(target, source)
+ }
+
+ return target
+ }
+}
\ No newline at end of file
diff --git a/src/util/util/imports/index.ts b/src/util/util/imports/index.ts
new file mode 100644
index 00000000..18c47a3b
--- /dev/null
+++ b/src/util/util/imports/index.ts
@@ -0,0 +1,3 @@
+export * from './Checks';
+export * from './HTTPError';
+export * from './OrmUtils';
\ No newline at end of file
diff --git a/util/src/util/index.ts b/src/util/util/index.ts
index f7a273cb..9e6059fa 100644
--- a/util/src/util/index.ts
+++ b/src/util/util/index.ts
@@ -1,6 +1,8 @@
export * from "./ApiError";
export * from "./BitField";
export * from "./Token";
+export * from "./imports/HTTPError";
+export * from "./imports/OrmUtils";
//export * from "./Categories";
export * from "./cdn";
export * from "./Config";
@@ -19,4 +21,6 @@ export * from "./Snowflake";
export * from "./String";
export * from "./Array";
export * from "./TraverseDirectory";
-export * from "./InvisibleCharacters";
\ No newline at end of file
+export * from "./InvisibleCharacters";
+
+export * from "./imports/index";
|