mirror of
https://github.com/spacebarchat/server.git
synced 2024-11-09 20:22:47 +01:00
prettier
This commit is contained in:
parent
363d9887cf
commit
04dea8d788
18
.github/ISSUE_TEMPLATE/config.yml
vendored
18
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,11 +1,11 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Fosscord Documentation
|
||||
url: https://docs.fosscord.com/
|
||||
about: Need documentation and examples for the Fosscord? Head over to Fosscord's official documentation.
|
||||
- name: Discord's Developer Documentation
|
||||
url: https://discord.com/developers/docs/intro
|
||||
about: Need help with the Discord resources? Head here instead of asking on Fosscord!
|
||||
- name: Fosscord' Official Discord server
|
||||
url: https://discord.com/invite/Ms5Ev7S6bF
|
||||
about: Need help with the server? Talk with us in our official server.
|
||||
- name: Fosscord Documentation
|
||||
url: https://docs.fosscord.com/
|
||||
about: Need documentation and examples for the Fosscord? Head over to Fosscord's official documentation.
|
||||
- name: Discord's Developer Documentation
|
||||
url: https://discord.com/developers/docs/intro
|
||||
about: Need help with the Discord resources? Head here instead of asking on Fosscord!
|
||||
- name: Fosscord' Official Discord server
|
||||
url: https://discord.com/invite/Ms5Ev7S6bF
|
||||
about: Need help with the server? Talk with us in our official server.
|
||||
|
12
.github/relase_body_template.md
vendored
12
.github/relase_body_template.md
vendored
@ -1,13 +1,17 @@
|
||||
## Notes
|
||||
|
||||
## Additions
|
||||
-
|
||||
|
||||
-
|
||||
|
||||
## Fixes
|
||||
|
||||
-
|
||||
|
||||
## Download
|
||||
- [Windows]()
|
||||
- [MacOS]()
|
||||
- [Linux]()
|
||||
|
||||
- [Windows]()
|
||||
- [MacOS]()
|
||||
- [Linux]()
|
||||
|
||||
After (extracting) and starting the server executable you can access your own Fosscord server on http://localhost:3001/
|
||||
|
28
.vscode/launch.json
vendored
28
.vscode/launch.json
vendored
@ -1,17 +1,13 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "${file}",
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/**/*.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"program": "${file}",
|
||||
"outFiles": ["${workspaceFolder}/**/*.js"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,2 +1 @@
|
||||
|
||||
The Docker image is coming with the dashboard. The planned release date is 2022-12-24.
|
||||
The Docker image is coming with the dashboard. The planned release date is 2022-12-24.
|
||||
|
@ -87,6 +87,7 @@
|
||||
"node-fetch": "^2.6.7",
|
||||
"patch-package": "^6.4.7",
|
||||
"picocolors": "^1.0.0",
|
||||
"prettier": "^2.7.1",
|
||||
"proxy-agent": "^5.0.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"typeorm": "^0.3.7",
|
||||
|
@ -8,9 +8,9 @@ const rl = readline.createInterface({ input: process.stdin, output: process.stdo
|
||||
const data = { env: [], config: { register: {} }, extra_pkgs: [] };
|
||||
let rights = [];
|
||||
|
||||
process.on('SIGINT', function() {
|
||||
console.log("Caught interrupt signal");
|
||||
process.exit();
|
||||
process.on("SIGINT", function () {
|
||||
console.log("Caught interrupt signal");
|
||||
process.exit();
|
||||
});
|
||||
|
||||
console.log("Welcome to Fosscord!");
|
||||
@ -18,8 +18,8 @@ console.log("Please remember this is pre-release software!");
|
||||
console.log("We will guide you through some important setup steps.");
|
||||
console.log();
|
||||
|
||||
if(fs.existsSync("package-lock.json")) fs.rmSync("package-lock.json");
|
||||
if(fs.existsSync("yarn.lock")) fs.rmSync("yarn.lock");
|
||||
if (fs.existsSync("package-lock.json")) fs.rmSync("package-lock.json");
|
||||
if (fs.existsSync("yarn.lock")) fs.rmSync("yarn.lock");
|
||||
|
||||
async function main() {
|
||||
printTitle("Step 1: Database setup");
|
||||
@ -82,7 +82,7 @@ async function main() {
|
||||
if (data.db != "sqlite")
|
||||
data.env.push(`DATABASE=${data.db}://${data.db_user}:${data.db_pass}@${data.db_host}:${data.db_port}/${data.db_name}`);
|
||||
data.env.push(`PORT=${data.port}`);
|
||||
data.env.push('THREADS=1')
|
||||
data.env.push("THREADS=1");
|
||||
|
||||
printTitle("Step 4: Default rights");
|
||||
console.log("Please enter the default rights for new users.");
|
||||
@ -126,8 +126,9 @@ async function main() {
|
||||
};
|
||||
printTitle("Step 5: extra options");
|
||||
|
||||
if(/y?/i.test(await ask("Use fast BCrypt implementation (requires a compiler) (Y/n): "))) data.extra_pkgs.push("bcrypt");
|
||||
if(/y?/.test(await ask("Enable support for widgets (requires compiler, known to fail on some ARM devices.) (Y/n): "))) data.extra_pkgs.push("canvas");
|
||||
if (/y?/i.test(await ask("Use fast BCrypt implementation (requires a compiler) (Y/n): "))) data.extra_pkgs.push("bcrypt");
|
||||
if (/y?/.test(await ask("Enable support for widgets (requires compiler, known to fail on some ARM devices.) (Y/n): ")))
|
||||
data.extra_pkgs.push("canvas");
|
||||
|
||||
printTitle("Step 6: finalizing...");
|
||||
//save
|
||||
@ -140,13 +141,13 @@ async function main() {
|
||||
console.log(" ==> Ensuring yarn is up to date (v3, not v1)...");
|
||||
execIn("npx yarn set version stable", process.cwd());
|
||||
console.log(" ==> Installing base packages");
|
||||
execIn("npx --yes yarn install", process.cwd(), {stdio: "inherit"});
|
||||
execIn("npx --yes yarn install", process.cwd(), { stdio: "inherit" });
|
||||
|
||||
console.log(` ==> Installing extra packages: ${data.extra_pkgs.join(', ')}...`);
|
||||
execIn(`npx --yes yarn add -O ${data.extra_pkgs.join(' ')}`, process.cwd(), {stdio: "inherit"});
|
||||
console.log(` ==> Installing extra packages: ${data.extra_pkgs.join(", ")}...`);
|
||||
execIn(`npx --yes yarn add -O ${data.extra_pkgs.join(" ")}`, process.cwd(), { stdio: "inherit" });
|
||||
|
||||
console.log('==> Building...')
|
||||
execIn('npx --yes yarn run build', process.cwd(), {stdio: "inherit"});
|
||||
console.log("==> Building...");
|
||||
execIn("npx --yes yarn run build", process.cwd(), { stdio: "inherit" });
|
||||
printTitle("Step 6: run your instance!");
|
||||
console.log("Installation is complete!");
|
||||
console.log("You can now start your instance by running 'npm run start:bundle'!");
|
||||
|
@ -1,15 +1,15 @@
|
||||
process.on("unhandledRejection", console.error);
|
||||
process.on("uncaughtException", console.error);
|
||||
|
||||
import http from "http";
|
||||
import * as Api from "@fosscord/api";
|
||||
import * as Gateway from "@fosscord/gateway";
|
||||
import { CDNServer } from "@fosscord/cdn";
|
||||
import express from "express";
|
||||
import { green, bold, yellow } from "picocolors";
|
||||
import * as Gateway from "@fosscord/gateway";
|
||||
import { Config, getOrInitialiseDatabase } from "@fosscord/util";
|
||||
import * as Sentry from "@sentry/node";
|
||||
import * as Tracing from "@sentry/tracing";
|
||||
import express from "express";
|
||||
import http from "http";
|
||||
import { bold, green, yellow } from "picocolors";
|
||||
// import { PluginLoader } from "@fosscord/util";
|
||||
|
||||
const app = express();
|
||||
@ -26,12 +26,12 @@ const cdn = new CDNServer({ server, port, production, app });
|
||||
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)
|
||||
process.on("SIGTERM", () => {
|
||||
setTimeout(() => process.exit(0), 3000);
|
||||
server.close(() => {
|
||||
console.log("Stop API has been successfully POSTed, SIGTERM sent")
|
||||
})
|
||||
})
|
||||
console.log("Stop API has been successfully POSTed, SIGTERM sent");
|
||||
});
|
||||
});
|
||||
//this is what has been added for the /stop API route
|
||||
|
||||
async function main() {
|
||||
@ -42,16 +42,15 @@ async function main() {
|
||||
await Config.set({
|
||||
cdn: {
|
||||
endpointClient: "${location.host}",
|
||||
endpointPrivate: `http://localhost:${port}`,
|
||||
endpointPrivate: `http://localhost:${port}`
|
||||
},
|
||||
gateway: {
|
||||
endpointClient:
|
||||
'${location.protocol === "https:" ? "wss://" : "ws://"}${location.host}',
|
||||
endpointClient: '${location.protocol === "https:" ? "wss://" : "ws://"}${location.host}',
|
||||
endpointPrivate: `ws://localhost:${port}`,
|
||||
...(!Config.get().gateway.endpointPublic && {
|
||||
endpointPublic: `ws://localhost:${port}`,
|
||||
}),
|
||||
},
|
||||
endpointPublic: `ws://localhost:${port}`
|
||||
})
|
||||
}
|
||||
// regions: {
|
||||
// default: "fosscord",
|
||||
// useDefaultAsOptimal: true,
|
||||
@ -70,15 +69,10 @@ async function main() {
|
||||
|
||||
//Sentry
|
||||
if (Config.get().sentry.enabled) {
|
||||
console.log(
|
||||
`[Bundle] ${yellow("You are using Sentry! This may slightly impact performance on large loads!")}`
|
||||
);
|
||||
console.log(`[Bundle] ${yellow("You are using Sentry! This may slightly impact performance on large loads!")}`);
|
||||
Sentry.init({
|
||||
dsn: Config.get().sentry.endpoint,
|
||||
integrations: [
|
||||
new Sentry.Integrations.Http({ tracing: true }),
|
||||
new Tracing.Integrations.Express({ app }),
|
||||
],
|
||||
integrations: [new Sentry.Integrations.Http({ tracing: true }), new Tracing.Integrations.Express({ app })],
|
||||
tracesSampleRate: Config.get().sentry.traceSampleRate,
|
||||
environment: Config.get().sentry.environment
|
||||
});
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { Server, ServerOptions } from "lambert-server";
|
||||
import { Authentication, CORS } from "./middlewares/";
|
||||
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";
|
||||
import { NextFunction, Request, Response, Router } from "express";
|
||||
import { Server, ServerOptions } from "lambert-server";
|
||||
import morgan from "morgan";
|
||||
import path from "path";
|
||||
import { red } from "picocolors";
|
||||
import { Authentication, CORS } from "./middlewares/";
|
||||
import { BodyParser } from "./middlewares/BodyParser";
|
||||
import { ErrorHandler } from "./middlewares/ErrorHandler";
|
||||
import { initRateLimits } from "./middlewares/RateLimit";
|
||||
import TestClient from "./middlewares/TestClient";
|
||||
import { initTranslation } from "./middlewares/Translation";
|
||||
import morgan from "morgan";
|
||||
import { initInstance } from "./util/handlers/Instance";
|
||||
import { red } from "picocolors"
|
||||
|
||||
export interface FosscordServerOptions extends ServerOptions {}
|
||||
|
||||
@ -85,8 +85,13 @@ export class FosscordServer extends Server {
|
||||
this.app.use(ErrorHandler);
|
||||
TestClient(this.app);
|
||||
|
||||
if (logRequests) console.log(red(`Warning: Request logging is enabled! This will spam your console!\nTo disable this, unset the 'LOG_REQUESTS' environment variable!`));
|
||||
|
||||
if (logRequests)
|
||||
console.log(
|
||||
red(
|
||||
`Warning: Request logging is enabled! This will spam your console!\nTo disable this, unset the 'LOG_REQUESTS' environment variable!`
|
||||
)
|
||||
);
|
||||
|
||||
return super.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
export * from "./Server";
|
||||
export * from "./middlewares/";
|
||||
export * from "./Server";
|
||||
export * from "./util/";
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { checkToken, Config, HTTPError, Rights } from "@fosscord/util";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { checkToken, Config, Rights } from "@fosscord/util";
|
||||
|
||||
export const NO_AUTHORIZATION_ROUTES = [
|
||||
// Authentication routes
|
||||
@ -10,7 +9,7 @@ export const NO_AUTHORIZATION_ROUTES = [
|
||||
"/auth/mfa/totp",
|
||||
// Routes with a seperate auth system
|
||||
"/webhooks/",
|
||||
// Public information endpoints
|
||||
// Public information endpoints
|
||||
"/ping",
|
||||
"/gateway",
|
||||
"/experiments",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import bodyParser, { OptionsJson } from "body-parser";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
|
||||
export function BodyParser(opts?: OptionsJson) {
|
||||
const jsonParser = bodyParser.json(opts);
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { ApiError, FieldError, HTTPError } from "@fosscord/util";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { ApiError, FieldError } from "@fosscord/util";
|
||||
const EntityNotFoundErrorRegex = /"(\w+)"/;
|
||||
|
||||
export function ErrorHandler(error: Error, req: Request, res: Response, next: NextFunction) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Config, getRights, listenEvent, Rights } from "@fosscord/util";
|
||||
import { NextFunction, Request, Response, Router } from "express";
|
||||
import { getIpAdress } from "@fosscord/api";
|
||||
import { Config, getRights, listenEvent } from "@fosscord/util";
|
||||
import { NextFunction, Request, Response, Router } from "express";
|
||||
import { API_PREFIX_TRAILING_SLASH } from "./Authentication";
|
||||
|
||||
// Docs: https://discord.com/developers/docs/topics/rate-limits
|
||||
@ -163,7 +163,7 @@ export async function initRateLimits(app: Router) {
|
||||
app.use("/auth/register", rateLimit({ onlyIp: true, success: true, ...routes.auth.register }));
|
||||
}
|
||||
|
||||
async function hitRoute(opts: { executor_id: string; bucket_id: string; max_hits: number; window: number; }) {
|
||||
async function hitRoute(opts: { executor_id: string; bucket_id: string; max_hits: number; window: number }) {
|
||||
const id = opts.executor_id + opts.bucket_id;
|
||||
let limit = Cache.get(id);
|
||||
if (!limit) {
|
||||
|
@ -1,17 +1,17 @@
|
||||
import express, { Request, Response, Application } from "express";
|
||||
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 express, { Application, Request, Response } from "express";
|
||||
import fs from "fs";
|
||||
import fetch, { Headers, Response as FetchResponse } from "node-fetch";
|
||||
import path from "path";
|
||||
import { green } from "picocolors";
|
||||
import ProxyAgent from "proxy-agent";
|
||||
import { AssetCacheItem } from "../util/entities/AssetCacheItem";
|
||||
|
||||
const AssetsPath = path.join(__dirname, "..", "..", "..", "assets")
|
||||
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(AssetsPath, "index.html"), { encoding: "utf8" });
|
||||
html = applyEnv(html);
|
||||
@ -22,31 +22,29 @@ export default function TestClient(app: Application) {
|
||||
//load asset cache
|
||||
let newAssetCache: Map<string, AssetCacheItem> = new Map<string, AssetCacheItem>();
|
||||
let assetCacheDir = path.join(AssetsPath, "cache");
|
||||
if(process.env.ASSET_CACHE_DIR)
|
||||
assetCacheDir = process.env.ASSET_CACHE_DIR
|
||||
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)) {
|
||||
console.log(`[TestClient] ${green(`Using asset cache path: ${assetCacheDir}`)}`);
|
||||
if (!fs.existsSync(assetCacheDir)) {
|
||||
fs.mkdirSync(assetCacheDir);
|
||||
}
|
||||
if(fs.existsSync(path.join(assetCacheDir, "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(AssetsPath)));
|
||||
app.use("/assets", express.static(path.join(AssetsPath)));
|
||||
app.get("/assets/:file", async (req: Request, res: Response) => {
|
||||
delete req.headers.host;
|
||||
let response: FetchResponse;
|
||||
let buffer: Buffer;
|
||||
let assetCacheItem: AssetCacheItem = new AssetCacheItem(req.params.file);
|
||||
if(newAssetCache.has(req.params.file)){
|
||||
if (newAssetCache.has(req.params.file)) {
|
||||
assetCacheItem = newAssetCache.get(req.params.file)!;
|
||||
assetCacheItem.Headers.forEach((value: any, name: any) => {
|
||||
res.set(name, value);
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
console.log(`[TestClient] Downloading file not yet cached! Asset file: ${req.params.file}`);
|
||||
response = await fetch(`https://discord.com/assets/${req.params.file}`, {
|
||||
agent,
|
||||
@ -55,7 +53,7 @@ export default function TestClient(app: Application) {
|
||||
...req.headers
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//set cache info
|
||||
assetCacheItem.Headers = Object.fromEntries(stripHeaders(response.headers));
|
||||
assetCacheItem.FilePath = path.join(assetCacheDir, req.params.file);
|
||||
@ -66,7 +64,7 @@ export default function TestClient(app: Application) {
|
||||
//download file
|
||||
fs.writeFileSync(assetCacheItem.FilePath, await response.buffer());
|
||||
}
|
||||
|
||||
|
||||
assetCacheItem.Headers.forEach((value: string, name: string) => {
|
||||
res.set(name, value);
|
||||
});
|
||||
@ -77,8 +75,8 @@ export default function TestClient(app: Application) {
|
||||
res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24);
|
||||
res.set("content-type", "text/html");
|
||||
|
||||
if(!useTestClient) return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance.")
|
||||
|
||||
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, "..", "..", "..", "assets", "developers.html"), { encoding: "utf8" }));
|
||||
});
|
||||
app.get("*", (req: Request, res: Response) => {
|
||||
@ -86,15 +84,13 @@ export default function TestClient(app: Application) {
|
||||
res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24);
|
||||
res.set("content-type", "text/html");
|
||||
|
||||
if(req.url.startsWith("/api") || req.url.startsWith("/__development")) return;
|
||||
if (req.url.startsWith("/api") || req.url.startsWith("/__development")) return;
|
||||
|
||||
if(!useTestClient) return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance.")
|
||||
if (!useTestClient) return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance.");
|
||||
if (req.url.startsWith("/invite")) return res.send(html.replace("9b2b7f0632acd0c5e781", "9f24f709a3de09b67c49"));
|
||||
|
||||
|
||||
res.send(html);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
function applyEnv(html: string): string {
|
||||
@ -117,23 +113,29 @@ function applyPlugins(html: string): string {
|
||||
// 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`; });
|
||||
files.forEach((x) => {
|
||||
if (x.endsWith(".js")) plugins += `<script src='/assets/plugins/${x}'></script>\n`;
|
||||
});
|
||||
return html.replaceAll("<!-- plugin marker -->", plugins);
|
||||
}
|
||||
|
||||
function applyInlinePlugins(html: string): string{
|
||||
function applyInlinePlugins(html: string): string {
|
||||
// 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`; });
|
||||
files.forEach((x) => {
|
||||
if (x.endsWith(".js")) plugins += `<script src='/assets/inline-plugins/${x}'></script>\n\n`;
|
||||
});
|
||||
return html.replaceAll("<!-- inline plugin marker -->", plugins);
|
||||
}
|
||||
|
||||
function applyPreloadPlugins(html: string): string{
|
||||
function applyPreloadPlugins(html: string): string {
|
||||
//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(AssetsPath, "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);
|
||||
}
|
||||
|
||||
@ -147,7 +149,7 @@ function stripHeaders(headers: Headers): Headers {
|
||||
"expect-ct",
|
||||
"access-control-allow-origin",
|
||||
"content-encoding"
|
||||
].forEach(headerName => {
|
||||
].forEach((headerName) => {
|
||||
headers.delete(headerName);
|
||||
});
|
||||
return headers;
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Router } from "express";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import i18next from "i18next";
|
||||
import i18nextMiddleware from "i18next-http-middleware";
|
||||
import i18nextBackend from "i18next-node-fs-backend";
|
||||
import { Router } from "express";
|
||||
import path from "path";
|
||||
|
||||
export async function initTranslation(router: Router) {
|
||||
const languages = fs.readdirSync(path.join(__dirname, "..", "..", "..", "assets", "locales"));
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { getConnection } from "typeorm";
|
||||
|
||||
const router = Router();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { getConnection } from "typeorm";
|
||||
|
||||
const router = Router();
|
||||
|
@ -1,14 +1,14 @@
|
||||
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 { Application, Config, FieldErrors, generateToken, handleFile, OrmUtils, trimSpecial, User } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
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 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) {
|
||||
@ -16,8 +16,8 @@ router.post("/", route({}), async (req: Request, res: Response) => {
|
||||
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")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -47,37 +47,37 @@ router.post("/", route({}), async (req: Request, res: Response) => {
|
||||
flags: "0",
|
||||
data: {
|
||||
hash: null,
|
||||
valid_tokens_since: new Date(),
|
||||
valid_tokens_since: new Date()
|
||||
},
|
||||
settings: {},
|
||||
extended_settings: {},
|
||||
fingerprints: [],
|
||||
notes: {},
|
||||
notes: {}
|
||||
});
|
||||
await user.save();
|
||||
app.bot = user;
|
||||
await app.save();
|
||||
res.send().status(204)
|
||||
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))) {
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
export default router;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,22 +1,22 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Application, OrmUtils, Team, trimSpecial, User } from "@fosscord/util";
|
||||
import { Application, OrmUtils } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
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"] });
|
||||
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
|
||||
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;
|
||||
if (req.body.tags) app.tags = req.body.tags;
|
||||
await app.save();
|
||||
res.json(app).status(200);
|
||||
});
|
||||
@ -26,5 +26,4 @@ router.post("/delete", route({}), async (req: Request, res: Response) => {
|
||||
res.send().status(200);
|
||||
});
|
||||
|
||||
|
||||
export default router;
|
||||
export default router;
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Application, OrmUtils, Team, trimSpecial, User } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@ -8,4 +7,4 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
res.json([]).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
||||
export default router;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Application, OrmUtils, Team, trimSpecial, User } from "@fosscord/util";
|
||||
import { Application, OrmUtils, trimSpecial, User } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@ -11,14 +11,14 @@ export interface ApplicationCreateSchema {
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
//TODO
|
||||
let results = await Application.find({where: {owner: {id: req.user_id}}, relations: ["owner", "bot"] });
|
||||
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);
|
||||
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: "",
|
||||
@ -31,4 +31,4 @@ router.post("/", route({}), async (req: Request, res: Response) => {
|
||||
res.json(app).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
||||
export default router;
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { getIpAdress, IPAnalysis } from "@fosscord/api";
|
||||
import { getIpAdress, IPAnalysis, route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
router.get("/",route({}), async (req: Request, res: Response) => {
|
||||
//TODO
|
||||
//Note: It's most likely related to legal. At the moment Discord hasn't finished this too
|
||||
const country_code = (await IPAnalysis(getIpAdress(req))).country_code;
|
||||
res.json({ consent_required: false, country_code: country_code, promotional_email_opt_in: { required: true, pre_checked: false}});
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
//TODO
|
||||
//Note: It's most likely related to legal. At the moment Discord hasn't finished this too
|
||||
const country_code = (await IPAnalysis(getIpAdress(req))).country_code;
|
||||
res.json({ consent_required: false, country_code: country_code, promotional_email_opt_in: { required: true, pre_checked: false } });
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { adjustEmail, Config, FieldErrors, generateToken, LoginSchema, User } from "@fosscord/util";
|
||||
import crypto from "crypto";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
let bcrypt: any;
|
||||
try {
|
||||
@ -64,9 +64,9 @@ router.post("/", route({ body: "LoginSchema" }), async (req: Request, res: Respo
|
||||
return res.json({
|
||||
ticket: ticket,
|
||||
mfa: true,
|
||||
sms: false, // TODO
|
||||
token: null,
|
||||
})
|
||||
sms: false, // TODO
|
||||
token: null
|
||||
});
|
||||
}
|
||||
|
||||
const token = await generateToken(user.id);
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { BackupCode, FieldErrors, generateToken, TotpSchema, User } from "@fosscord/util";
|
||||
import { verifyToken } from "node-2fa";
|
||||
import { BackupCode, generateToken, TotpSchema, User } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
import { verifyToken } from "node-2fa";
|
||||
const router = Router();
|
||||
|
||||
router.post("/", route({ body: "TotpSchema" }), async (req: Request, res: Response) => {
|
||||
@ -10,23 +10,17 @@ router.post("/", route({ body: "TotpSchema" }), async (req: Request, res: Respon
|
||||
|
||||
const user = await User.findOneOrFail({
|
||||
where: {
|
||||
totp_last_ticket: ticket,
|
||||
totp_last_ticket: ticket
|
||||
},
|
||||
select: [
|
||||
"id",
|
||||
"totp_secret",
|
||||
"settings",
|
||||
],
|
||||
select: ["id", "totp_secret", "settings"]
|
||||
});
|
||||
|
||||
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);
|
||||
if (!ret || ret.delta != 0)
|
||||
throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
|
||||
}
|
||||
else {
|
||||
if (!ret || ret.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
|
||||
} else {
|
||||
backup.consumed = true;
|
||||
await backup.save();
|
||||
}
|
||||
@ -35,7 +29,7 @@ router.post("/", route({ body: "TotpSchema" }), async (req: Request, res: Respon
|
||||
|
||||
return res.json({
|
||||
token: await generateToken(user.id),
|
||||
user_settings: user.settings,
|
||||
user_settings: user.settings
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
// TODO:
|
||||
|
||||
|
@ -1,17 +1,16 @@
|
||||
import { route } from "@fosscord/api";
|
||||
import {
|
||||
Channel,
|
||||
ChannelDeleteEvent,
|
||||
ChannelPermissionOverwriteType,
|
||||
ChannelModifySchema,
|
||||
ChannelType,
|
||||
ChannelUpdateEvent,
|
||||
emitEvent,
|
||||
Recipient,
|
||||
handleFile,
|
||||
ChannelModifySchema
|
||||
OrmUtils,
|
||||
Recipient
|
||||
} 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
|
||||
|
@ -1,45 +1,45 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
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 { Channel, emitEvent, Guild, HTTPError, Invite, InviteCreateEvent, OrmUtils, PublicInviteRelation, User } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { isTextChannel } from "./messages";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE", right: "CREATE_INVITES" }),
|
||||
async (req: Request, res: Response) => {
|
||||
const { user_id } = req;
|
||||
const { channel_id } = req.params;
|
||||
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, select: ["id", "name", "type", "guild_id"] });
|
||||
isTextChannel(channel.type);
|
||||
router.post(
|
||||
"/",
|
||||
route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE", right: "CREATE_INVITES" }),
|
||||
async (req: Request, res: Response) => {
|
||||
const { user_id } = req;
|
||||
const { channel_id } = req.params;
|
||||
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, select: ["id", "name", "type", "guild_id"] });
|
||||
isTextChannel(channel.type);
|
||||
|
||||
if (!channel.guild_id) {
|
||||
throw new HTTPError("This channel doesn't exist", 404);
|
||||
if (!channel.guild_id) {
|
||||
throw new HTTPError("This channel doesn't exist", 404);
|
||||
}
|
||||
const { guild_id } = channel;
|
||||
|
||||
const expires_at = new Date(req.body.max_age * 1000 + Date.now());
|
||||
|
||||
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,
|
||||
guild_id,
|
||||
channel_id,
|
||||
inviter_id: user_id
|
||||
}).save();
|
||||
//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({ where: { id: guild_id } });
|
||||
data.channel = channel;
|
||||
|
||||
await emitEvent({ event: "INVITE_CREATE", data, guild_id } as InviteCreateEvent);
|
||||
res.status(201).send(data);
|
||||
}
|
||||
const { guild_id } = channel;
|
||||
|
||||
const expires_at = new Date(req.body.max_age * 1000 + Date.now());
|
||||
|
||||
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,
|
||||
guild_id,
|
||||
channel_id,
|
||||
inviter_id: user_id
|
||||
}).save();
|
||||
//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({ where: { id: guild_id } });
|
||||
data.channel = channel;
|
||||
|
||||
await emitEvent({ event: "INVITE_CREATE", data, guild_id } as InviteCreateEvent);
|
||||
res.status(201).send(data);
|
||||
});
|
||||
);
|
||||
|
||||
router.get("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => {
|
||||
const { channel_id } = req.params;
|
||||
|
@ -1,7 +1,6 @@
|
||||
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";
|
||||
import { emitEvent, getPermission, MessageAckEvent, OrmUtils, ReadState } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,25 +1,22 @@
|
||||
import { handleMessage, postHandleMessage, route } from "@fosscord/api";
|
||||
import {
|
||||
Attachment,
|
||||
Channel,
|
||||
Embed,
|
||||
DiscordApiErrors,
|
||||
emitEvent,
|
||||
FosscordApiErrors,
|
||||
getPermission,
|
||||
getRights,
|
||||
Message,
|
||||
HTTPError,
|
||||
Message,
|
||||
MessageCreateEvent,
|
||||
MessageCreateSchema,
|
||||
MessageDeleteEvent,
|
||||
MessageUpdateEvent,
|
||||
Snowflake,
|
||||
uploadFile,
|
||||
MessageCreateSchema
|
||||
uploadFile
|
||||
} from "@fosscord/util";
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Request, Response, Router } from "express";
|
||||
import multer from "multer";
|
||||
import { route } from "@fosscord/api";
|
||||
import { handleMessage, postHandleMessage } from "@fosscord/api";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
// TODO: message content/embed string length limit
|
||||
@ -33,50 +30,53 @@ const messageUpload = multer({
|
||||
storage: multer.memoryStorage()
|
||||
}); // max upload 50 mb
|
||||
|
||||
router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_MESSAGES" }), async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id } = req.params;
|
||||
let body = req.body as MessageCreateSchema;
|
||||
router.patch(
|
||||
"/",
|
||||
route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_MESSAGES" }),
|
||||
async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id } = req.params;
|
||||
let body = req.body as MessageCreateSchema;
|
||||
|
||||
const message = await Message.findOneOrFail({ where: { id: message_id, channel_id }, relations: ["attachments"] });
|
||||
const message = await Message.findOneOrFail({ where: { id: message_id, channel_id }, relations: ["attachments"] });
|
||||
|
||||
const permissions = await getPermission(req.user_id, undefined, channel_id);
|
||||
|
||||
const rights = await getRights(req.user_id);
|
||||
const permissions = await getPermission(req.user_id, undefined, channel_id);
|
||||
|
||||
if ((req.user_id !== message.author_id)) {
|
||||
if (!rights.has("MANAGE_MESSAGES")) {
|
||||
permissions.hasThrow("MANAGE_MESSAGES");
|
||||
body = { flags: body.flags };
|
||||
// guild admins can only suppress embeds of other messages, no such restriction imposed to instance-wide admins
|
||||
}
|
||||
} else rights.hasThrow("SELF_EDIT_MESSAGES");
|
||||
const rights = await getRights(req.user_id);
|
||||
|
||||
const new_message = await handleMessage({
|
||||
...message,
|
||||
// TODO: should message_reference be overridable?
|
||||
// @ts-ignore
|
||||
message_reference: message.message_reference,
|
||||
...body,
|
||||
author_id: message.author_id,
|
||||
channel_id,
|
||||
id: message_id,
|
||||
edited_timestamp: new Date()
|
||||
});
|
||||
if (req.user_id !== message.author_id) {
|
||||
if (!rights.has("MANAGE_MESSAGES")) {
|
||||
permissions.hasThrow("MANAGE_MESSAGES");
|
||||
body = { flags: body.flags };
|
||||
// guild admins can only suppress embeds of other messages, no such restriction imposed to instance-wide admins
|
||||
}
|
||||
} else rights.hasThrow("SELF_EDIT_MESSAGES");
|
||||
|
||||
await Promise.all([
|
||||
new_message!.save(),
|
||||
await emitEvent({
|
||||
event: "MESSAGE_UPDATE",
|
||||
const new_message = await handleMessage({
|
||||
...message,
|
||||
// TODO: should message_reference be overridable?
|
||||
// @ts-ignore
|
||||
message_reference: message.message_reference,
|
||||
...body,
|
||||
author_id: message.author_id,
|
||||
channel_id,
|
||||
data: { ...new_message, nonce: undefined }
|
||||
} as MessageUpdateEvent)
|
||||
]);
|
||||
id: message_id,
|
||||
edited_timestamp: new Date()
|
||||
});
|
||||
|
||||
postHandleMessage(message);
|
||||
await Promise.all([
|
||||
new_message!.save(),
|
||||
await emitEvent({
|
||||
event: "MESSAGE_UPDATE",
|
||||
channel_id,
|
||||
data: { ...new_message, nonce: undefined }
|
||||
} as MessageUpdateEvent)
|
||||
]);
|
||||
|
||||
return res.json(message);
|
||||
});
|
||||
postHandleMessage(message);
|
||||
|
||||
return res.json(message);
|
||||
}
|
||||
);
|
||||
|
||||
// Backfill message with specific timestamp
|
||||
router.put(
|
||||
@ -94,7 +94,7 @@ router.put(
|
||||
const { channel_id, message_id } = req.params;
|
||||
let body = req.body as MessageCreateSchema;
|
||||
const attachments: Attachment[] = [];
|
||||
|
||||
|
||||
const rights = await getRights(req.user_id);
|
||||
rights.hasThrow("SEND_MESSAGES");
|
||||
|
||||
@ -103,13 +103,13 @@ router.put(
|
||||
throw new HTTPError("Message IDs must be positive integers", 400);
|
||||
}
|
||||
|
||||
const snowflake = Snowflake.deconstruct(message_id)
|
||||
const snowflake = Snowflake.deconstruct(message_id);
|
||||
if (Date.now() < snowflake.timestamp) {
|
||||
// message is in the future
|
||||
throw FosscordApiErrors.CANNOT_BACKFILL_TO_THE_FUTURE;
|
||||
}
|
||||
|
||||
const exists = await Message.findOne({ where: { id: message_id, channel_id: channel_id }});
|
||||
const exists = await Message.findOne({ where: { id: message_id, channel_id: channel_id } });
|
||||
if (exists) {
|
||||
throw FosscordApiErrors.CANNOT_REPLACE_BY_BACKFILL;
|
||||
}
|
||||
@ -136,19 +136,19 @@ router.put(
|
||||
channel_id,
|
||||
attachments,
|
||||
edited_timestamp: undefined,
|
||||
timestamp: new Date(snowflake.timestamp),
|
||||
timestamp: new Date(snowflake.timestamp)
|
||||
});
|
||||
|
||||
//Fix for the client bug
|
||||
delete message.member
|
||||
|
||||
delete message.member;
|
||||
|
||||
await Promise.all([
|
||||
message.save(),
|
||||
emitEvent({ event: "MESSAGE_CREATE", channel_id: channel_id, data: message } as MessageCreateEvent),
|
||||
channel.save()
|
||||
]);
|
||||
|
||||
postHandleMessage(message).catch((e) => { }); // no await as it shouldnt block the message send function and silently catch error
|
||||
postHandleMessage(message).catch((e) => {}); // no await as it shouldnt block the message send function and silently catch error
|
||||
|
||||
return res.json(message);
|
||||
}
|
||||
@ -160,7 +160,7 @@ router.get("/", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res:
|
||||
const message = await Message.findOneOrFail({ where: { id: message_id, channel_id }, relations: ["attachments"] });
|
||||
|
||||
const permissions = await getPermission(req.user_id, undefined, channel_id);
|
||||
|
||||
|
||||
if (message.author_id !== req.user_id) permissions.hasThrow("READ_MESSAGE_HISTORY");
|
||||
|
||||
return res.json(message);
|
||||
@ -171,10 +171,10 @@ router.delete("/", route({}), async (req: Request, res: Response) => {
|
||||
|
||||
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);
|
||||
|
||||
if ((message.author_id !== req.user_id)) {
|
||||
if (message.author_id !== req.user_id) {
|
||||
if (!rights.has("MANAGE_MESSAGES")) {
|
||||
const permission = await getPermission(req.user_id, channel.guild_id, channel_id);
|
||||
permission.hasThrow("MANAGE_MESSAGES");
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { route } from "@fosscord/api";
|
||||
import {
|
||||
Channel,
|
||||
emitEvent,
|
||||
Emoji,
|
||||
getPermission,
|
||||
HTTPError,
|
||||
Member,
|
||||
Message,
|
||||
MessageReactionAddEvent,
|
||||
@ -13,9 +15,7 @@ import {
|
||||
PublicUserProjection,
|
||||
User
|
||||
} from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Router, Response, Request } from "express";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { In } from "typeorm";
|
||||
|
||||
const router = Router();
|
||||
@ -101,48 +101,52 @@ router.get("/:emoji", route({ permission: "VIEW_CHANNEL" }), async (req: Request
|
||||
res.json(users);
|
||||
});
|
||||
|
||||
router.put("/:emoji/:user_id", route({ permission: "READ_MESSAGE_HISTORY", right: "SELF_ADD_REACTIONS" }), async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id, user_id } = req.params;
|
||||
if (user_id !== "@me") throw new HTTPError("Invalid user");
|
||||
const emoji = getEmoji(req.params.emoji);
|
||||
router.put(
|
||||
"/:emoji/:user_id",
|
||||
route({ permission: "READ_MESSAGE_HISTORY", right: "SELF_ADD_REACTIONS" }),
|
||||
async (req: Request, res: Response) => {
|
||||
const { message_id, channel_id, user_id } = req.params;
|
||||
if (user_id !== "@me") throw new HTTPError("Invalid user");
|
||||
const emoji = getEmoji(req.params.emoji);
|
||||
|
||||
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);
|
||||
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 (!already_added) req.permission!.hasThrow("ADD_REACTIONS");
|
||||
|
||||
if (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;
|
||||
}
|
||||
|
||||
if (already_added) {
|
||||
if (already_added.user_ids.includes(req.user_id)) return res.sendStatus(204); // Do not throw an error ¯\_(ツ)_/¯ as discord also doesn't throw any error
|
||||
already_added.count++;
|
||||
} else message.reactions.push({ count: 1, emoji, user_ids: [req.user_id] });
|
||||
|
||||
await message.save();
|
||||
|
||||
const member = channel.guild_id && (await Member.findOneOrFail({ where: { id: req.user_id } }));
|
||||
|
||||
await emitEvent({
|
||||
event: "MESSAGE_REACTION_ADD",
|
||||
channel_id,
|
||||
data: {
|
||||
user_id: req.user_id,
|
||||
channel_id,
|
||||
message_id,
|
||||
guild_id: channel.guild_id,
|
||||
emoji,
|
||||
member
|
||||
if (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;
|
||||
}
|
||||
} as MessageReactionAddEvent);
|
||||
|
||||
res.sendStatus(204);
|
||||
});
|
||||
if (already_added) {
|
||||
if (already_added.user_ids.includes(req.user_id)) return res.sendStatus(204); // Do not throw an error ¯\_(ツ)_/¯ as discord also doesn't throw any error
|
||||
already_added.count++;
|
||||
} else message.reactions.push({ count: 1, emoji, user_ids: [req.user_id] });
|
||||
|
||||
await message.save();
|
||||
|
||||
const member = channel.guild_id && (await Member.findOneOrFail({ where: { id: req.user_id } }));
|
||||
|
||||
await emitEvent({
|
||||
event: "MESSAGE_REACTION_ADD",
|
||||
channel_id,
|
||||
data: {
|
||||
user_id: req.user_id,
|
||||
channel_id,
|
||||
message_id,
|
||||
guild_id: channel.guild_id,
|
||||
emoji,
|
||||
member
|
||||
}
|
||||
} as MessageReactionAddEvent);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
);
|
||||
|
||||
router.delete("/:emoji/:user_id", route({}), async (req: Request, res: Response) => {
|
||||
let { message_id, channel_id, user_id } = req.params;
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Channel, Config, emitEvent, getPermission, getRights, MessageDeleteBulkEvent, Message } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Channel, Config, emitEvent, getPermission, getRights, HTTPError, Message, MessageDeleteBulkEvent } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { In } from "typeorm";
|
||||
|
||||
const router: Router = Router();
|
||||
@ -13,7 +12,7 @@ export default router;
|
||||
// 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({where:{ 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);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { handleMessage, postHandleMessage, route } from "@fosscord/api";
|
||||
import {
|
||||
Attachment,
|
||||
Channel,
|
||||
@ -7,16 +7,15 @@ import {
|
||||
DmChannelDTO,
|
||||
emitEvent,
|
||||
getPermission,
|
||||
getRights,
|
||||
HTTPError,
|
||||
Member,
|
||||
Message,
|
||||
MessageCreateEvent,
|
||||
MessageCreateSchema,
|
||||
Snowflake,
|
||||
uploadFile,
|
||||
Member,
|
||||
MessageCreateSchema
|
||||
uploadFile
|
||||
} from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { handleMessage, postHandleMessage, route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
import multer from "multer";
|
||||
import { FindManyOptions, LessThan, MoreThan } from "typeorm";
|
||||
import { URL } from "url";
|
||||
@ -69,23 +68,20 @@ router.get("/", async (req: Request, res: Response) => {
|
||||
permissions.hasThrow("VIEW_CHANNEL");
|
||||
if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]);
|
||||
|
||||
let query: FindManyOptions<Message> & { where: { id?: any; }; } = {
|
||||
let query: FindManyOptions<Message> & { where: { id?: any } } = {
|
||||
order: { id: "DESC" },
|
||||
take: limit,
|
||||
where: { channel_id },
|
||||
relations: ["author", "webhook", "application", "mentions", "mention_roles", "mention_channels", "sticker_items", "attachments"]
|
||||
};
|
||||
|
||||
|
||||
if (after) {
|
||||
if (after > new Snowflake()) return res.status(422);
|
||||
query.where.id = MoreThan(after);
|
||||
}
|
||||
else if (before) {
|
||||
} else if (before) {
|
||||
if (before < req.params.channel_id) return res.status(422);
|
||||
query.where.id = LessThan(before);
|
||||
}
|
||||
else if (around) {
|
||||
} else if (around) {
|
||||
query.where.id = [
|
||||
MoreThan((BigInt(around) - BigInt(halfLimit)).toString()),
|
||||
LessThan((BigInt(around) + BigInt(halfLimit)).toString())
|
||||
@ -110,15 +106,14 @@ router.get("/", async (req: Request, res: Response) => {
|
||||
const uri = y.proxy_url.startsWith("http") ? y.proxy_url : `https://example.org${y.proxy_url}`;
|
||||
y.proxy_url = `${endpoint == null ? "" : endpoint}${new URL(uri).pathname}`;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
Some clients ( discord.js ) only check if a property exists within the response,
|
||||
which causes erorrs when, say, the `application` property is `null`.
|
||||
**/
|
||||
|
||||
|
||||
for (let curr in x) {
|
||||
if (x[curr] === null)
|
||||
delete x[curr];
|
||||
if (x[curr] === null) delete x[curr];
|
||||
}
|
||||
|
||||
return x;
|
||||
@ -130,7 +125,7 @@ router.get("/", async (req: Request, res: Response) => {
|
||||
const messageUpload = multer({
|
||||
limits: {
|
||||
fileSize: 1024 * 1024 * 100,
|
||||
fields: 10,
|
||||
fields: 10
|
||||
// files: 1
|
||||
},
|
||||
storage: multer.memoryStorage()
|
||||
@ -162,16 +157,15 @@ router.post(
|
||||
|
||||
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients", "recipients.user"] });
|
||||
if (!channel.isWritable()) {
|
||||
throw new HTTPError(`Cannot send messages to channel of type ${channel.type}`, 400)
|
||||
throw new HTTPError(`Cannot send messages to channel of type ${channel.type}`, 400);
|
||||
}
|
||||
|
||||
const files = req.files as Express.Multer.File[] ?? [];
|
||||
const files = (req.files as Express.Multer.File[]) ?? [];
|
||||
for (let currFile of files) {
|
||||
try {
|
||||
const file: any = await uploadFile(`/attachments/${channel.id}`, currFile);
|
||||
attachments.push({ ...file, proxy_url: file.url });
|
||||
}
|
||||
catch (error) {
|
||||
} catch (error) {
|
||||
return res.status(400).json(error);
|
||||
}
|
||||
}
|
||||
@ -212,11 +206,11 @@ router.post(
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
//Defining member fields
|
||||
|
||||
//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) => {
|
||||
// member.roles = member.roles.filter((role) => {
|
||||
// return role.id !== role.guild_id;
|
||||
// }).map((role) => {
|
||||
// return role.id;
|
||||
@ -225,7 +219,7 @@ router.post(
|
||||
// TODO: Figure this out
|
||||
// delete message.member.last_message_id;
|
||||
// delete message.member.index;
|
||||
|
||||
|
||||
await Promise.all([
|
||||
message.save(),
|
||||
emitEvent({ event: "MESSAGE_CREATE", channel_id: channel_id, data: message } as MessageCreateEvent),
|
||||
@ -233,9 +227,8 @@ router.post(
|
||||
channel.save()
|
||||
]);
|
||||
|
||||
postHandleMessage(message).catch((e) => { }); // no await as it shouldnt block the message send function and silently catch error
|
||||
postHandleMessage(message).catch((e) => {}); // no await as it shouldnt block the message send function and silently catch error
|
||||
|
||||
return res.json(message);
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,17 +1,15 @@
|
||||
import { route } from "@fosscord/api";
|
||||
import {
|
||||
Channel,
|
||||
ChannelPermissionOverwrite,
|
||||
ChannelPermissionOverwriteSchema,
|
||||
ChannelPermissionOverwriteType,
|
||||
ChannelUpdateEvent,
|
||||
emitEvent,
|
||||
getPermission,
|
||||
HTTPError,
|
||||
Member,
|
||||
Role
|
||||
} from "@fosscord/util";
|
||||
import { Router, Response, Request } from "express";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@ -22,7 +20,7 @@ router.put(
|
||||
const { channel_id, overwrite_id } = req.params;
|
||||
const body = req.body as ChannelPermissionOverwriteSchema;
|
||||
|
||||
let channel = await Channel.findOneOrFail({ where: {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) {
|
||||
|
@ -1,16 +1,6 @@
|
||||
import {
|
||||
Channel,
|
||||
ChannelPinsUpdateEvent,
|
||||
Config,
|
||||
emitEvent,
|
||||
getPermission,
|
||||
Message,
|
||||
MessageUpdateEvent,
|
||||
DiscordApiErrors
|
||||
} from "@fosscord/util";
|
||||
import { Router, Request, Response } from "express";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Channel, ChannelPinsUpdateEvent, Config, DiscordApiErrors, emitEvent, Message, MessageUpdateEvent } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,10 +1,18 @@
|
||||
import { HTTPError, PurgeSchema } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import {
|
||||
Channel,
|
||||
Config,
|
||||
emitEvent,
|
||||
getPermission,
|
||||
getRights,
|
||||
HTTPError,
|
||||
Message,
|
||||
MessageDeleteBulkEvent,
|
||||
PurgeSchema
|
||||
} from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Between, FindManyOptions, In, Not } from "typeorm";
|
||||
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();
|
||||
|
||||
@ -13,7 +21,12 @@ 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) => {
|
||||
router.post(
|
||||
"/",
|
||||
route({
|
||||
/*body: "PurgeSchema",*/
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id } = req.params;
|
||||
const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import {
|
||||
Channel,
|
||||
ChannelRecipientAddEvent,
|
||||
@ -6,12 +6,12 @@ import {
|
||||
DiscordApiErrors,
|
||||
DmChannelDTO,
|
||||
emitEvent,
|
||||
OrmUtils,
|
||||
PublicUserProjection,
|
||||
Recipient,
|
||||
User
|
||||
} from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Channel, emitEvent, Member, TypingStartEvent } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Router, Request, Response } from "express";
|
||||
import { Channel, emitEvent, Member, TypingStartEvent } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Channel, Config, getPermission, trimSpecial, Webhook } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { Channel, Config, DiscordApiErrors, HTTPError, trimSpecial, Webhook } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { isTextChannel } from "./messages/index";
|
||||
import { DiscordApiErrors } from "@fosscord/util";
|
||||
|
||||
const router: Router = Router();
|
||||
//TODO: implement webhooks
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Guild, Config } from "@fosscord/util";
|
||||
import { Config, Guild } from "@fosscord/util";
|
||||
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "..";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Like } from "typeorm";
|
||||
import { route } from "..";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Categories } from "@fosscord/util";
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Request, Response, Router } from "express";
|
||||
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);
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Config, Release } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "..";
|
||||
import { Release, Config } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@ -10,7 +10,7 @@ router.get("/:branch", route({}), async (req: Request, res: Response) => {
|
||||
const { platform } = req.query;
|
||||
//TODO
|
||||
|
||||
if(!platform || !["linux", "osx", "win"].includes(platform.toString())) return res.status(404)
|
||||
if (!platform || !["linux", "osx", "win"].includes(platform.toString())) return res.status(404);
|
||||
|
||||
const release = await Release.findOneOrFail({ where: { name: client.releases.upstreamVersion } });
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "..";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
res.send({ fingerprint: "", assignments: [], guild_experiments:[] });
|
||||
res.send({ fingerprint: "", assignments: [], guild_experiments: [] });
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Config } from "@fosscord/util";
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route, RouteOptions } from "@fosscord/api";
|
||||
import { Config } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Config } from "@fosscord/util";
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route, RouteOptions } from "@fosscord/api";
|
||||
import { Config } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import fetch from "node-fetch";
|
||||
import ProxyAgent from 'proxy-agent';
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
import fetch from "node-fetch";
|
||||
import ProxyAgent from "proxy-agent";
|
||||
import { getGifApiKey, parseGifResult } from "./trending";
|
||||
|
||||
const router = Router();
|
||||
@ -11,7 +11,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { q, media_format, locale } = req.query;
|
||||
|
||||
const apiKey = getGifApiKey();
|
||||
|
||||
|
||||
const agent = new ProxyAgent();
|
||||
|
||||
const response = await fetch(`https://g.tenor.com/v1/search?q=${q}&media_format=${media_format}&locale=${locale}&key=${apiKey}`, {
|
||||
@ -20,7 +20,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
headers: { "Content-Type": "application/json" }
|
||||
});
|
||||
|
||||
const { results } = await response.json() as any;
|
||||
const { results } = (await response.json()) as any;
|
||||
|
||||
res.json(results.map(parseGifResult)).status(200);
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import fetch from "node-fetch";
|
||||
import ProxyAgent from 'proxy-agent';
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
import fetch from "node-fetch";
|
||||
import ProxyAgent from "proxy-agent";
|
||||
import { getGifApiKey, parseGifResult } from "./trending";
|
||||
|
||||
const router = Router();
|
||||
@ -11,7 +11,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { media_format, locale } = req.query;
|
||||
|
||||
const apiKey = getGifApiKey();
|
||||
|
||||
|
||||
const agent = new ProxyAgent();
|
||||
|
||||
const response = await fetch(`https://g.tenor.com/v1/trending?media_format=${media_format}&locale=${locale}&key=${apiKey}`, {
|
||||
@ -20,7 +20,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
headers: { "Content-Type": "application/json" }
|
||||
});
|
||||
|
||||
const { results } = await response.json() as any;
|
||||
const { results } = (await response.json()) as any;
|
||||
|
||||
res.json(results.map(parseGifResult)).status(200);
|
||||
});
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import fetch from "node-fetch";
|
||||
import ProxyAgent from 'proxy-agent';
|
||||
import { route } from "@fosscord/api";
|
||||
import { Config } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { Config, HTTPError } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import fetch from "node-fetch";
|
||||
import ProxyAgent from "proxy-agent";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@ -34,7 +33,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { media_format, locale } = req.query;
|
||||
|
||||
const apiKey = getGifApiKey();
|
||||
|
||||
|
||||
const agent = new ProxyAgent();
|
||||
|
||||
const [responseSource, trendGifSource] = await Promise.all([
|
||||
@ -50,8 +49,8 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
})
|
||||
]);
|
||||
|
||||
const { tags } = await responseSource.json() as any;
|
||||
const { results } = await trendGifSource.json() as any;
|
||||
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 })),
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Guild, Config } from "@fosscord/util";
|
||||
import { Config, Guild } from "@fosscord/util";
|
||||
|
||||
import { Router, Request, Response } from "express";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Like } from "typeorm";
|
||||
import { route } from "..";
|
||||
import {Like} from "typeorm"
|
||||
|
||||
const router = Router();
|
||||
|
||||
@ -13,12 +13,12 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
// TODO: implement this with default typeorm query
|
||||
// const guilds = await Guild.find({ where: { features: "DISCOVERABLE" } }); //, take: Math.abs(Number(limit)) });
|
||||
|
||||
const genLoadId = (size: Number) => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('');
|
||||
const genLoadId = (size: Number) => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join("");
|
||||
|
||||
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)) });
|
||||
res.send({ recommended_guilds: guilds, load_id: `server_recs/${genLoadId(32)}`}).status(200);
|
||||
: 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);
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
//TODO: implement audit logs
|
||||
|
@ -1,8 +1,18 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
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";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
import {
|
||||
Ban,
|
||||
BanModeratorSchema,
|
||||
BanRegistrySchema,
|
||||
DiscordApiErrors,
|
||||
emitEvent,
|
||||
GuildBanAddEvent,
|
||||
GuildBanRemoveEvent,
|
||||
HTTPError,
|
||||
Member,
|
||||
OrmUtils,
|
||||
User
|
||||
} from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@ -44,16 +54,16 @@ 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({ where: { guild_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
|
||||
|
||||
|
||||
/* Filter secret from registry. */
|
||||
|
||||
|
||||
ban = ban as BanModeratorSchema;
|
||||
|
||||
delete ban.ip
|
||||
delete ban.ip;
|
||||
|
||||
return res.json(ban);
|
||||
});
|
||||
@ -62,14 +72,14 @@ router.put("/:user_id", route({ body: "BanCreateSchema", permission: "BAN_MEMBER
|
||||
const { guild_id } = req.params;
|
||||
const banned_user_id = req.params.user_id;
|
||||
|
||||
if ( (req.user_id === banned_user_id) && (banned_user_id === req.permission!.cache.guild?.owner_id))
|
||||
if (req.user_id === banned_user_id && banned_user_id === req.permission!.cache.guild?.owner_id)
|
||||
throw new HTTPError("You are the guild owner, hence can't ban yourself", 403);
|
||||
|
||||
|
||||
if (req.permission!.cache.guild?.owner_id === banned_user_id) throw new HTTPError("You can't ban the owner", 400);
|
||||
|
||||
|
||||
const banned_user = await User.getPublicUser(banned_user_id);
|
||||
|
||||
const ban = OrmUtils.mergeDeep(new Ban(),{
|
||||
const ban = OrmUtils.mergeDeep(new Ban(), {
|
||||
user_id: banned_user_id,
|
||||
guild_id: guild_id,
|
||||
ip: getIpAdress(req),
|
||||
@ -93,14 +103,14 @@ router.put("/:user_id", route({ body: "BanCreateSchema", permission: "BAN_MEMBER
|
||||
return res.json(ban);
|
||||
});
|
||||
|
||||
router.put("/@me", route({ body: "BanCreateSchema"}), async (req: Request, res: Response) => {
|
||||
router.put("/@me", route({ body: "BanCreateSchema" }), async (req: Request, res: Response) => {
|
||||
const { guild_id } = req.params;
|
||||
|
||||
const banned_user = await User.getPublicUser(req.params.user_id);
|
||||
|
||||
if (req.permission!.cache.guild?.owner_id === req.params.user_id)
|
||||
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 = OrmUtils.mergeDeep(new Ban(), {
|
||||
user_id: req.params.user_id,
|
||||
guild_id: guild_id,
|
||||
@ -129,12 +139,12 @@ router.delete("/:user_id", route({ permission: "BAN_MEMBERS" }), async (req: Req
|
||||
const { guild_id, user_id } = req.params;
|
||||
|
||||
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
|
||||
|
||||
|
||||
const banned_user = await User.getPublicUser(user_id);
|
||||
|
||||
|
||||
await Promise.all([
|
||||
Ban.delete({
|
||||
user_id: user_id,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Channel, ChannelUpdateEvent, getPermission, emitEvent, ChannelModifySchema, ChannelReorderSchema } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Channel, ChannelModifySchema, ChannelReorderSchema, ChannelUpdateEvent, emitEvent, HTTPError } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Channel, emitEvent, GuildDeleteEvent, Guild, Member, Message, Role, Invite, Emoji } from "@fosscord/util";
|
||||
import { Router, Request, Response } from "express";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { emitEvent, Guild, GuildDeleteEvent, HTTPError } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,38 +1,36 @@
|
||||
import { Guild, Config } from "@fosscord/util";
|
||||
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { guild_id } = req.params;
|
||||
// TODO:
|
||||
// Load from database
|
||||
// Admin control, but for now it allows anyone to be discoverable
|
||||
const { guild_id } = req.params;
|
||||
// TODO:
|
||||
// Load from database
|
||||
// Admin control, but for now it allows anyone to be discoverable
|
||||
|
||||
res.send({
|
||||
guild_id: guild_id,
|
||||
safe_environment: true,
|
||||
healthy: true,
|
||||
health_score_pending: false,
|
||||
size: true,
|
||||
nsfw_properties: {},
|
||||
protected: true,
|
||||
sufficient: true,
|
||||
sufficient_without_grace_period: true,
|
||||
valid_rules_channel: true,
|
||||
retention_healthy: true,
|
||||
engagement_healthy: true,
|
||||
age: true,
|
||||
minimum_age: 0,
|
||||
health_score: {
|
||||
avg_nonnew_participators: 0,
|
||||
avg_nonnew_communicators: 0,
|
||||
num_intentful_joiners: 0,
|
||||
perc_ret_w1_intentful: 0
|
||||
},
|
||||
minimum_size: 0
|
||||
healthy: true,
|
||||
health_score_pending: false,
|
||||
size: true,
|
||||
nsfw_properties: {},
|
||||
protected: true,
|
||||
sufficient: true,
|
||||
sufficient_without_grace_period: true,
|
||||
valid_rules_channel: true,
|
||||
retention_healthy: true,
|
||||
engagement_healthy: true,
|
||||
age: true,
|
||||
minimum_age: 0,
|
||||
health_score: {
|
||||
avg_nonnew_participators: 0,
|
||||
avg_nonnew_communicators: 0,
|
||||
num_intentful_joiners: 0,
|
||||
perc_ret_w1_intentful: 0
|
||||
},
|
||||
minimum_size: 0
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,7 +1,19 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
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";
|
||||
import {
|
||||
Config,
|
||||
DiscordApiErrors,
|
||||
emitEvent,
|
||||
Emoji,
|
||||
EmojiCreateSchema,
|
||||
EmojiModifySchema,
|
||||
GuildEmojisUpdateEvent,
|
||||
handleFile,
|
||||
Member,
|
||||
OrmUtils,
|
||||
Snowflake,
|
||||
User
|
||||
} from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,8 +1,18 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { DiscordApiErrors, emitEvent, getPermission, getRights, Guild, GuildUpdateEvent, GuildUpdateSchema, handleFile, Member } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
import {
|
||||
DiscordApiErrors,
|
||||
emitEvent,
|
||||
getPermission,
|
||||
getRights,
|
||||
Guild,
|
||||
GuildUpdateEvent,
|
||||
GuildUpdateSchema,
|
||||
handleFile,
|
||||
HTTPError,
|
||||
Member,
|
||||
OrmUtils
|
||||
} from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@ -21,17 +31,16 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
return res.send(guild);
|
||||
});
|
||||
|
||||
router.patch("/", route({ body: "GuildUpdateSchema"}), async (req: Request, res: Response) => {
|
||||
router.patch("/", route({ body: "GuildUpdateSchema" }), async (req: Request, res: Response) => {
|
||||
const body = req.body as GuildUpdateSchema;
|
||||
const { guild_id } = req.params;
|
||||
|
||||
|
||||
|
||||
const rights = await getRights(req.user_id);
|
||||
const permission = await getPermission(req.user_id, guild_id);
|
||||
|
||||
if (!rights.has("MANAGE_GUILDS")||!permission.has("MANAGE_GUILD"))
|
||||
|
||||
if (!rights.has("MANAGE_GUILDS") || !permission.has("MANAGE_GUILD"))
|
||||
throw DiscordApiErrors.MISSING_PERMISSIONS.withParams("MANAGE_GUILD");
|
||||
|
||||
|
||||
// TODO: guild update check image
|
||||
|
||||
if (body.icon) body.icon = await handleFile(`/icons/${guild_id}`, body.icon);
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
//TODO: implement integrations list
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { getPermission, Invite, PublicInviteRelation } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Invite, PublicInviteRelation } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
@ -1,8 +1,18 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
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";
|
||||
import {
|
||||
emitEvent,
|
||||
Emoji,
|
||||
getPermission,
|
||||
getRights,
|
||||
Guild,
|
||||
GuildMemberUpdateEvent,
|
||||
Member,
|
||||
MemberChangeSchema,
|
||||
OrmUtils,
|
||||
Role,
|
||||
Sticker
|
||||
} from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@ -46,7 +56,6 @@ router.patch("/", route({ body: "MemberChangeSchema" }), async (req: Request, re
|
||||
});
|
||||
|
||||
router.put("/", route({}), async (req: Request, res: Response) => {
|
||||
|
||||
// TODO: Lurker mode
|
||||
|
||||
const rights = await getRights(req.user_id);
|
||||
@ -56,7 +65,7 @@ router.put("/", route({}), async (req: Request, res: Response) => {
|
||||
member_id = req.user_id;
|
||||
rights.hasThrow("JOIN_GUILDS");
|
||||
} else {
|
||||
// TODO: join others by controller
|
||||
// TODO: join others by controller
|
||||
}
|
||||
|
||||
let guild = await Guild.findOneOrFail({
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { getPermission, Member, PermissionResolvable } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { getPermission, Member, PermissionResolvable } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { getPermission, Member } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Member } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Guild, Member, PublicMemberProjection } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { HTTPError, Member, PublicMemberProjection } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { MoreThan } from "typeorm";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
router.get("/subscriptions", route({}), async (req: Request, res: Response) => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { Guild, Member, Snowflake } from "@fosscord/util";
|
||||
import { LessThan, IsNull } from "typeorm";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Guild, Member, Snowflake } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { IsNull, LessThan } from "typeorm";
|
||||
const router = Router();
|
||||
|
||||
//Returns all inactive members, respecting role hierarchy
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Config, Guild, Member } from "@fosscord/util";
|
||||
import { getIpAdress, getVoiceRegions, route } from "@fosscord/api";
|
||||
import { Guild } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { getVoiceRegions, route } from "@fosscord/api";
|
||||
import { getIpAdress } from "@fosscord/api";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,8 +1,16 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { Role, Member, GuildRoleUpdateEvent, GuildRoleDeleteEvent, emitEvent, handleFile, RoleModifySchema } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
import {
|
||||
emitEvent,
|
||||
GuildRoleDeleteEvent,
|
||||
GuildRoleUpdateEvent,
|
||||
handleFile,
|
||||
HTTPError,
|
||||
Member,
|
||||
OrmUtils,
|
||||
Role,
|
||||
RoleModifySchema
|
||||
} from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,21 +1,18 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import {
|
||||
Role,
|
||||
getPermission,
|
||||
Member,
|
||||
GuildRoleCreateEvent,
|
||||
GuildRoleUpdateEvent,
|
||||
GuildRoleDeleteEvent,
|
||||
emitEvent,
|
||||
Config,
|
||||
DiscordApiErrors,
|
||||
handleFile,
|
||||
emitEvent,
|
||||
getPermission,
|
||||
GuildRoleCreateEvent,
|
||||
GuildRoleUpdateEvent,
|
||||
Member,
|
||||
OrmUtils,
|
||||
Role,
|
||||
RoleModifySchema,
|
||||
RolePositionUpdateSchema
|
||||
} from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@ -38,7 +35,7 @@ router.post("/", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" })
|
||||
|
||||
if (role_count > maxRoles) throw DiscordApiErrors.MAXIMUM_ROLES.withParams(maxRoles);
|
||||
|
||||
let role: Role = OrmUtils.mergeDeep(new Role(),{
|
||||
let role: Role = OrmUtils.mergeDeep(new Role(), {
|
||||
// values before ...body are default and can be overriden
|
||||
position: 0,
|
||||
hoist: false,
|
||||
|
@ -1,20 +1,19 @@
|
||||
import { route } from "@fosscord/api";
|
||||
import {
|
||||
emitEvent,
|
||||
GuildStickersUpdateEvent,
|
||||
handleFile,
|
||||
HTTPError,
|
||||
Member,
|
||||
ModifyGuildStickerSchema,
|
||||
OrmUtils,
|
||||
Snowflake,
|
||||
Sticker,
|
||||
StickerFormatType,
|
||||
StickerType,
|
||||
uploadFile
|
||||
} from "@fosscord/util";
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
import multer from "multer";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
|
@ -1,9 +1,6 @@
|
||||
import { generateCode, route } from "@fosscord/api";
|
||||
import { Guild, HTTPError, OrmUtils, Template } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Guild, Template } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { generateCode } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@ -75,7 +72,12 @@ router.patch("/:code", route({ body: "TemplateModifySchema", permission: "MANAGE
|
||||
const { code, guild_id } = req.params;
|
||||
const { name, description } = req.body;
|
||||
|
||||
const template = await OrmUtils.mergeDeep(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);
|
||||
});
|
||||
|
@ -1,8 +1,6 @@
|
||||
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 "@fosscord/util";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
import { Channel, ChannelType, Guild, HTTPError, Invite, OrmUtils, VanityUrlSchema } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,7 +1,16 @@
|
||||
import { Channel, ChannelType, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent, VoiceStateUpdateSchema } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import {
|
||||
Channel,
|
||||
ChannelType,
|
||||
DiscordApiErrors,
|
||||
emitEvent,
|
||||
getPermission,
|
||||
OrmUtils,
|
||||
VoiceState,
|
||||
VoiceStateUpdateEvent,
|
||||
VoiceStateUpdateSchema
|
||||
} from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
router.patch("/", route({ body: "VoiceStateUpdateSchema" }), async (req: Request, res: Response) => {
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
//TODO: implement webhooks
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Guild, getPermission, Snowflake, Member, GuildUpdateWelcomeScreenSchema } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Guild, GuildUpdateWelcomeScreenSchema, HTTPError, Member } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Config, Permissions, Guild, Invite, Channel, Member } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { random, route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
import { Channel, Guild, HTTPError, Invite, Member, OrmUtils, Permissions } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Guild } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Guild, HTTPError } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Guild, WidgetModifySchema } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Guild, WidgetModifySchema } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { Role, Guild, Snowflake, Config, getRights, Member, Channel, DiscordApiErrors, handleFile, GuildCreateSchema } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Config, DiscordApiErrors, getRights, Guild, GuildCreateSchema, Member } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@ -12,7 +12,7 @@ router.post("/", route({ body: "GuildCreateSchema", right: "CREATE_GUILDS" }), a
|
||||
const { maxGuilds } = Config.get().limits.user;
|
||||
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")) {
|
||||
if (guild_count >= maxGuilds && !rights.has("MANAGE_GUILDS")) {
|
||||
throw DiscordApiErrors.MAXIMUM_GUILDS.withParams(maxGuilds);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Template, Guild, Role, Snowflake, Config, User, Member, DiscordApiErrors, OrmUtils, GuildTemplateCreateSchema } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Config, DiscordApiErrors, Guild, GuildTemplateCreateSchema, Member, OrmUtils, Role, Snowflake, Template } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import fetch from "node-fetch";
|
||||
const router: Router = Router();
|
||||
|
||||
@ -9,9 +9,10 @@ router.get("/:code", route({}), async (req: Request, res: Response) => {
|
||||
if (!enabled) res.json({ code: 403, message: "Template creation & usage is disabled on this instance." }).sendStatus(403);
|
||||
|
||||
const { code } = req.params;
|
||||
|
||||
|
||||
if (code.startsWith("discord:")) {
|
||||
if (!allowDiscordTemplates) return res.json({ code: 403, message: "Discord templates cannot be used on this instance." }).sendStatus(403);
|
||||
if (!allowDiscordTemplates)
|
||||
return res.json({ code: 403, message: "Discord templates cannot be used on this instance." }).sendStatus(403);
|
||||
const discordTemplateID = code.split("discord:", 2)[1];
|
||||
|
||||
const discordTemplateData = await fetch(`https://discord.com/api/v9/guilds/templates/${discordTemplateID}`, {
|
||||
@ -22,7 +23,7 @@ router.get("/:code", route({}), async (req: Request, res: Response) => {
|
||||
}
|
||||
|
||||
if (code.startsWith("external:")) {
|
||||
if (!allowRaws) return res.json({ code: 403, message: "Importing raws is disabled on this instance." }).sendStatus(403);
|
||||
if (!allowRaws) return res.json({ code: 403, message: "Importing raws is disabled on this instance." }).sendStatus(403);
|
||||
|
||||
return res.json(code.split("external:", 2)[1]);
|
||||
}
|
||||
@ -57,18 +58,20 @@ router.post("/:code", route({ body: "GuildTemplateCreateSchema" }), async (req:
|
||||
id: guild_id,
|
||||
owner_id: req.user_id
|
||||
}).save(),
|
||||
(OrmUtils.mergeDeep(new Role(), {
|
||||
id: guild_id,
|
||||
guild_id: guild_id,
|
||||
color: 0,
|
||||
hoist: false,
|
||||
managed: true,
|
||||
mentionable: true,
|
||||
name: "@everyone",
|
||||
permissions: BigInt("2251804225"),
|
||||
position: 0,
|
||||
tags: null
|
||||
}) as Role).save()
|
||||
(
|
||||
OrmUtils.mergeDeep(new Role(), {
|
||||
id: guild_id,
|
||||
guild_id: guild_id,
|
||||
color: 0,
|
||||
hoist: false,
|
||||
managed: true,
|
||||
mentionable: true,
|
||||
name: "@everyone",
|
||||
permissions: BigInt("2251804225"),
|
||||
position: 0,
|
||||
tags: null
|
||||
}) as Role
|
||||
).save()
|
||||
]);
|
||||
|
||||
await Member.addToGuild(req.user_id, guild_id);
|
||||
|
@ -1,7 +1,6 @@
|
||||
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 "@fosscord/util";
|
||||
import { emitEvent, getPermission, Guild, HTTPError, Invite, InviteDeleteEvent, PublicInviteRelation, User } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@ -13,15 +12,16 @@ router.get("/:code", route({}), async (req: Request, res: Response) => {
|
||||
res.status(200).send(invite);
|
||||
});
|
||||
|
||||
router.post("/:code", route({right: "USE_MASS_INVITES"}), 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({ where: { code } })
|
||||
const { features } = await Guild.findOneOrFail({ where: { id: guild_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);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
const invite = await Invite.joinGuild(req.user_id, code);
|
||||
|
||||
res.json(invite);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,39 +1,36 @@
|
||||
|
||||
import { Guild, Config } from "@fosscord/util";
|
||||
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { guild_id } = req.params;
|
||||
// TODO:
|
||||
// Load from database
|
||||
// Admin control, but for now it allows anyone to be discoverable
|
||||
const { guild_id } = req.params;
|
||||
// TODO:
|
||||
// Load from database
|
||||
// Admin control, but for now it allows anyone to be discoverable
|
||||
|
||||
res.send({
|
||||
guild_id: guild_id,
|
||||
safe_environment: true,
|
||||
healthy: true,
|
||||
health_score_pending: false,
|
||||
size: true,
|
||||
nsfw_properties: {},
|
||||
protected: true,
|
||||
sufficient: true,
|
||||
sufficient_without_grace_period: true,
|
||||
valid_rules_channel: true,
|
||||
retention_healthy: true,
|
||||
engagement_healthy: true,
|
||||
age: true,
|
||||
minimum_age: 0,
|
||||
health_score: {
|
||||
avg_nonnew_participators: 0,
|
||||
avg_nonnew_communicators: 0,
|
||||
num_intentful_joiners: 0,
|
||||
perc_ret_w1_intentful: 0
|
||||
},
|
||||
minimum_size: 0
|
||||
healthy: true,
|
||||
health_score_pending: false,
|
||||
size: true,
|
||||
nsfw_properties: {},
|
||||
protected: true,
|
||||
sufficient: true,
|
||||
sufficient_without_grace_period: true,
|
||||
valid_rules_channel: true,
|
||||
retention_healthy: true,
|
||||
engagement_healthy: true,
|
||||
age: true,
|
||||
minimum_age: 0,
|
||||
health_score: {
|
||||
avg_nonnew_participators: 0,
|
||||
avg_nonnew_communicators: 0,
|
||||
num_intentful_joiners: 0,
|
||||
perc_ret_w1_intentful: 0
|
||||
},
|
||||
minimum_size: 0
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Config } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@ -18,8 +18,8 @@ router.get("/", route({}), (req: Request, res: Response) => {
|
||||
correspondenceUserID: general.correspondenceUserID,
|
||||
|
||||
frontPage: general.frontPage,
|
||||
tosPage: general.tosPage,
|
||||
},
|
||||
tosPage: general.tosPage
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,16 +1,15 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Config } from "@fosscord/util";
|
||||
import { config } from "dotenv"
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
router.get("/",route({}), async (req: Request, res: Response) => {
|
||||
const { cdn, gateway } = Config.get();
|
||||
|
||||
const IdentityForm = {
|
||||
cdn: cdn.endpointPublic || process.env.CDN || "http://localhost:3001",
|
||||
gateway: gateway.endpointPublic || process.env.GATEWAY || "ws://localhost:3002"
|
||||
};
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { cdn, gateway } = Config.get();
|
||||
|
||||
const IdentityForm = {
|
||||
cdn: cdn.endpointPublic || process.env.CDN || "http://localhost:3001",
|
||||
gateway: gateway.endpointPublic || process.env.GATEWAY || "ws://localhost:3002"
|
||||
};
|
||||
|
||||
res.json(IdentityForm);
|
||||
});
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Config } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
|
||||
router.get("/",route({}), async (req: Request, res: Response) => {
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { general } = Config.get();
|
||||
res.json(general);
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Config } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
router.get("/",route({}), async (req: Request, res: Response) => {
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { limits } = Config.get();
|
||||
res.json(limits);
|
||||
});
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
router.get("/scheduled-maintenances/upcoming.json",route({}), async (req: Request, res: Response) => {
|
||||
router.get("/scheduled-maintenances/upcoming.json", route({}), async (req: Request, res: Response) => {
|
||||
res.json({
|
||||
"page": {},
|
||||
"scheduled_maintenances": {}
|
||||
});
|
||||
page: {},
|
||||
scheduled_maintenances: {}
|
||||
});
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { StickerPack } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Sticker } from "@fosscord/util";
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Sticker } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
|
@ -1,22 +1,21 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { User } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
router.post("/", route({}), async (req: Request, res: Response) => {
|
||||
//EXPERIMENTAL: have an "OPERATOR" platform permission implemented for this API route
|
||||
const user = await User.findOneOrFail({ where: { id: req.user_id }, select: ["rights"] });
|
||||
if((Number(user.rights) << Number(0))%Number(2)==Number(1)) {
|
||||
if ((Number(user.rights) << Number(0)) % Number(2) == Number(1)) {
|
||||
console.log("user that POSTed to the API was ALLOWED");
|
||||
console.log(user.rights);
|
||||
res.sendStatus(200)
|
||||
process.kill(process.pid, 'SIGTERM')
|
||||
}
|
||||
else {
|
||||
res.sendStatus(200);
|
||||
process.kill(process.pid, "SIGTERM");
|
||||
} else {
|
||||
console.log("operation failed");
|
||||
console.log(user.rights);
|
||||
res.sendStatus(403)
|
||||
res.sendStatus(403);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user