mirror of
https://github.com/spacebarchat/server.git
synced 2024-11-25 03:33:33 +01:00
Merge branch 'master' of https://github.com/fosscord/fosscord-server
This commit is contained in:
commit
e52e7ef0e1
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,15 @@ const Excluded = [
|
||||
"supertest.Response"
|
||||
];
|
||||
|
||||
function modify(obj) {
|
||||
delete obj.additionalProperties;
|
||||
for (var k in obj) {
|
||||
if (typeof obj[k] === "object" && obj[k] !== null) {
|
||||
modify(obj[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
const program = TJS.getProgramFromFiles(walk(path.join(__dirname, "..", "src", "routes")), compilerOptions);
|
||||
const generator = TJS.buildGenerator(program, settings);
|
||||
@ -47,6 +56,8 @@ function main() {
|
||||
definitions = { ...definitions, [name]: { ...part } };
|
||||
}
|
||||
|
||||
modify(definitions);
|
||||
|
||||
fs.writeFileSync(schemaPath, JSON.stringify(definitions, null, 4));
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
import { checkToken, Config } from "@fosscord/util";
|
||||
import { checkToken, Config, Rights } from "@fosscord/util";
|
||||
|
||||
export const NO_AUTHORIZATION_ROUTES = [
|
||||
"/auth/login",
|
||||
@ -21,6 +21,7 @@ declare global {
|
||||
user_id: string;
|
||||
user_bot: boolean;
|
||||
token: string;
|
||||
rights: Rights;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -46,6 +47,7 @@ export async function Authentication(req: Request, res: Response, next: NextFunc
|
||||
req.token = decoded;
|
||||
req.user_id = decoded.id;
|
||||
req.user_bot = user.bot;
|
||||
req.rights = new Rights(Number(user.rights));
|
||||
return next();
|
||||
} catch (error: any) {
|
||||
return next(new HTTPError(error?.toString(), 400));
|
||||
|
12
api/src/routes/applications/#id/entitlements.ts
Normal file
12
api/src/routes/applications/#id/entitlements.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
//const { exclude_consumed } = req.query;
|
||||
res.status(200).send([]);
|
||||
});
|
||||
|
||||
export default router;
|
@ -50,6 +50,15 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
|
||||
const { register, security } = Config.get();
|
||||
const ip = getIpAdress(req);
|
||||
|
||||
if (register.disabled) {
|
||||
throw FieldErrors({
|
||||
email: {
|
||||
code: "DISABLED",
|
||||
message: "registration is disabled on this instance"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (register.blockProxies) {
|
||||
if (isProxy(await IPAnalysis(ip))) {
|
||||
console.log(`proxy ${ip} blocked from registration`);
|
||||
@ -202,6 +211,7 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
|
||||
disabled: false,
|
||||
deleted: false,
|
||||
email: email,
|
||||
rights: "0",
|
||||
nsfw_allowed: true, // TODO: depending on age
|
||||
public_flags: "0",
|
||||
flags: "0", // TODO: generate
|
||||
|
@ -1,8 +1,30 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router = Router();
|
||||
|
||||
// TODO:
|
||||
// router.post("/", (req: Request, res: Response) => {});
|
||||
router.post("/", route({ permission: "MANAGE_MESSAGES" }), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
res.json({
|
||||
id: "",
|
||||
type: 0,
|
||||
content: "",
|
||||
channel_id: "",
|
||||
author: {id: "",
|
||||
username: "",
|
||||
avatar: "",
|
||||
discriminator: "", public_flags: 64},
|
||||
attachments: [],
|
||||
embeds: [],
|
||||
mentions: [],
|
||||
mention_roles: [],
|
||||
pinned: false,
|
||||
mention_everyone: false,
|
||||
tts: false,
|
||||
timestamp: "",
|
||||
edited_timestamp: null,
|
||||
flags: 1, components: []}).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
|
@ -124,7 +124,7 @@ router.put("/:emoji/:user_id", route({ permission: "READ_MESSAGE_HISTORY" }), as
|
||||
already_added.count++;
|
||||
} else message.reactions.push({ count: 1, emoji, user_ids: [req.user_id] });
|
||||
|
||||
await Message.update({ id: message_id, channel_id }, message);
|
||||
await message.save();
|
||||
|
||||
const member = channel.guild_id && (await Member.findOneOrFail({ id: req.user_id }));
|
||||
|
||||
@ -165,7 +165,7 @@ router.delete("/:emoji/:user_id", route({}), async (req: Request, res: Response)
|
||||
|
||||
if (already_added.count <= 0) message.reactions.remove(already_added);
|
||||
|
||||
await Message.update({ id: message_id, channel_id }, message);
|
||||
await message.save();
|
||||
|
||||
await emitEvent({
|
||||
event: "MESSAGE_REACTION_REMOVE",
|
||||
|
@ -1,16 +1,18 @@
|
||||
import { Guild } from "@fosscord/util";
|
||||
import { Guild, Config } from "@fosscord/util";
|
||||
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { limit } = req.params;
|
||||
|
||||
var showAllGuilds = Config.get().guild.showAllGuildsInDiscovery;
|
||||
// ! this only works using SQL querys
|
||||
// TODO: implement this with default typeorm query
|
||||
// const guilds = await Guild.find({ where: { features: "DISCOVERABLE" } }); //, take: Math.abs(Number(limit)) });
|
||||
const guilds = await Guild.find({ where: `"features" LIKE 'COMMUNITY'`, take: Math.abs(Number(limit)) });
|
||||
const guilds = showAllGuilds ? await Guild.find({take: Math.abs(Number(limit || 20))}) : await Guild.find({ where: `"features" LIKE '%COMMUNITY%'`, take: Math.abs(Number(limit || 20)) });
|
||||
res.send({ guilds: guilds });
|
||||
});
|
||||
|
||||
|
12
api/src/routes/discovery.ts
Normal file
12
api/src/routes/discovery.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/categories", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
//const { locale, primary_only } = req.query;
|
||||
res.json([]).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
@ -3,9 +3,8 @@ import { route } from "@fosscord/api";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
router.get("/skus/:id", route({}), async (req: Request, res: Response) => {
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
//TODO
|
||||
const { id } = req.params;
|
||||
res.json([]).status(200);
|
||||
});
|
||||
|
79
api/src/routes/store/published-listings/applications.ts
Normal file
79
api/src/routes/store/published-listings/applications.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
router.get("/:id", route({}), async (req: Request, res: Response) => {
|
||||
//TODO
|
||||
const id = req.params.id;
|
||||
res.json({
|
||||
id: "",
|
||||
summary: "",
|
||||
sku: {
|
||||
id: "",
|
||||
type: 1,
|
||||
dependent_sku_id: null,
|
||||
application_id: "",
|
||||
manifets_labels: [],
|
||||
access_type: 2,
|
||||
name: "",
|
||||
features: [],
|
||||
relase_date: "",
|
||||
premium: false,
|
||||
slug: "",
|
||||
flags: 4,
|
||||
genres: [],
|
||||
legal_notice: "",
|
||||
application: {
|
||||
id: "",
|
||||
name: "",
|
||||
icon: "",
|
||||
description: "",
|
||||
summary: "",
|
||||
cover_image: "",
|
||||
primary_sku_id: "",
|
||||
hook: true,
|
||||
slug: "",
|
||||
guild_id: "",
|
||||
bot_public: "",
|
||||
bot_require_code_grant: false,
|
||||
verify_key: "",
|
||||
publishers: [
|
||||
{
|
||||
id: "",
|
||||
name: ""
|
||||
}
|
||||
],
|
||||
developers: [
|
||||
{
|
||||
id: "",
|
||||
name: ""
|
||||
}
|
||||
],
|
||||
system_requirements: {},
|
||||
show_age_gate: false,
|
||||
price: {
|
||||
amount: 0,
|
||||
currency: "EUR"
|
||||
},
|
||||
locales: []
|
||||
},
|
||||
tagline: "",
|
||||
description: "",
|
||||
carousel_items: [
|
||||
{
|
||||
asset_id: ""
|
||||
}
|
||||
],
|
||||
header_logo_dark_theme: {}, //{id: "", size: 4665, mime_type: "image/gif", width 160, height: 160}
|
||||
header_logo_light_theme: {},
|
||||
box_art: {},
|
||||
thumbnail: {},
|
||||
header_background: {},
|
||||
hero_background: {},
|
||||
assets: []
|
||||
}
|
||||
}).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
@ -0,0 +1,24 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
//TODO
|
||||
res.json([
|
||||
{
|
||||
id: "",
|
||||
name: "",
|
||||
interval: 1,
|
||||
interval_count: 1,
|
||||
tax_inclusive: true,
|
||||
sku_id: "",
|
||||
fallback_price: 499,
|
||||
fallback_currency: "eur",
|
||||
currency: "eur",
|
||||
price: 4199,
|
||||
price_tier: null
|
||||
}]).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
79
api/src/routes/store/published-listings/skus.ts
Normal file
79
api/src/routes/store/published-listings/skus.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
router.get("/:id", route({}), async (req: Request, res: Response) => {
|
||||
//TODO
|
||||
const id = req.params.id;
|
||||
res.json({
|
||||
id: "",
|
||||
summary: "",
|
||||
sku: {
|
||||
id: "",
|
||||
type: 1,
|
||||
dependent_sku_id: null,
|
||||
application_id: "",
|
||||
manifets_labels: [],
|
||||
access_type: 2,
|
||||
name: "",
|
||||
features: [],
|
||||
relase_date: "",
|
||||
premium: false,
|
||||
slug: "",
|
||||
flags: 4,
|
||||
genres: [],
|
||||
legal_notice: "",
|
||||
application: {
|
||||
id: "",
|
||||
name: "",
|
||||
icon: "",
|
||||
description: "",
|
||||
summary: "",
|
||||
cover_image: "",
|
||||
primary_sku_id: "",
|
||||
hook: true,
|
||||
slug: "",
|
||||
guild_id: "",
|
||||
bot_public: "",
|
||||
bot_require_code_grant: false,
|
||||
verify_key: "",
|
||||
publishers: [
|
||||
{
|
||||
id: "",
|
||||
name: ""
|
||||
}
|
||||
],
|
||||
developers: [
|
||||
{
|
||||
id: "",
|
||||
name: ""
|
||||
}
|
||||
],
|
||||
system_requirements: {},
|
||||
show_age_gate: false,
|
||||
price: {
|
||||
amount: 0,
|
||||
currency: "EUR"
|
||||
},
|
||||
locales: []
|
||||
},
|
||||
tagline: "",
|
||||
description: "",
|
||||
carousel_items: [
|
||||
{
|
||||
asset_id: ""
|
||||
}
|
||||
],
|
||||
header_logo_dark_theme: {}, //{id: "", size: 4665, mime_type: "image/gif", width 160, height: 160}
|
||||
header_logo_light_theme: {},
|
||||
box_art: {},
|
||||
thumbnail: {},
|
||||
header_background: {},
|
||||
hero_background: {},
|
||||
assets: []
|
||||
}
|
||||
}).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
@ -0,0 +1,25 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
const skus = new Map([
|
||||
["521842865731534868", [{"id": "511651856145973248", "name": "Premium Monthly (Legacy)", "interval": 1, "interval_count": 1, "tax_inclusive": true, "sku_id": "521842865731534868", "currency": "usd", "price": 0, "price_tier": null}, {"id": "511651860671627264", "name": "Premium Yearly (Legacy)", "interval": 2, "interval_count": 1, "tax_inclusive": true, "sku_id": "521842865731534868", "currency": "usd", "price": 0, "price_tier": null}]],
|
||||
["521846918637420545", [{"id": "511651871736201216", "name": "Premium Classic Monthly", "interval": 1, "interval_count": 1, "tax_inclusive": true, "sku_id": "521846918637420545", "currency": "usd", "price": 0, "price_tier": null}, {"id": "511651876987469824", "name": "Premium Classic Yearly", "interval": 2, "interval_count": 1, "tax_inclusive": true, "sku_id": "521846918637420545", "currency": "usd", "price": 0, "price_tier": null}]],
|
||||
["521847234246082599", [{"id": "642251038925127690", "name": "Premium Quarterly", "interval": 1, "interval_count": 3, "tax_inclusive": true, "sku_id": "521847234246082599", "currency": "usd", "price": 0, "price_tier": null}, {"id": "511651880837840896", "name": "Premium Monthly", "interval": 1, "interval_count": 1, "tax_inclusive": true, "sku_id": "521847234246082599", "currency": "usd", "price": 0, "price_tier": null}, {"id": "511651885459963904", "name": "Premium Yearly", "interval": 2, "interval_count": 1, "tax_inclusive": true, "sku_id": "521847234246082599", "currency": "usd", "price": 0, "price_tier": null}]],
|
||||
["590663762298667008", [{"id": "590665532894740483", "name": "Server Boost Monthly", "interval": 1, "interval_count": 1, "tax_inclusive": true, "sku_id": "590663762298667008", "discount_price": 0, "currency": "usd", "price": 0, "price_tier": null}, {"id": "590665538238152709", "name": "Server Boost Yearly", "interval": 2, "interval_count": 1, "tax_inclusive": true, "sku_id": "590663762298667008", "discount_price": 0, "currency": "usd", "price": 0, "price_tier": null}]],
|
||||
]);
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
// TODO: add the ability to add custom
|
||||
const { sku_id } = req.params;
|
||||
|
||||
if(!skus.has(sku_id)) {
|
||||
console.log(`Request for invalid SKU ${sku_id}! Please report this!`);
|
||||
res.sendStatus(404);
|
||||
} else {
|
||||
res.json(skus.get(sku_id)).status(200);
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
@ -0,0 +1,11 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
res.json([]).status(200)
|
||||
});
|
||||
|
||||
export default router;
|
11
api/src/routes/users/@me/billing/payment-sources.ts
Normal file
11
api/src/routes/users/@me/billing/payment-sources.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
res.json([]).status(200)
|
||||
});
|
||||
|
||||
export default router;
|
19
api/src/routes/users/@me/email-settings.ts
Normal file
19
api/src/routes/users/@me/email-settings.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
res.json({
|
||||
categories: {
|
||||
social: true,
|
||||
communication: true,
|
||||
tips: false,
|
||||
updates_and_announcements: false,
|
||||
recommendations_and_events: false },
|
||||
initialized: false
|
||||
}).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
11
api/src/routes/users/@me/entitlements.ts
Normal file
11
api/src/routes/users/@me/entitlements.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/gifts", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
res.json([]).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
@ -0,0 +1,11 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
res.json([]).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
@ -3,10 +3,12 @@ import { route } from "@fosscord/api";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
router.get("/applications/:id", route({}), async (req: Request, res: Response) => {
|
||||
router.put("/:id", route({}), async (req: Request, res: Response) => {
|
||||
//TODO
|
||||
const { id } = req.params;
|
||||
res.json([]).status(200);
|
||||
res.json({
|
||||
message: "400: Bad Request",
|
||||
code: 0
|
||||
}).status(400);
|
||||
});
|
||||
|
||||
export default router;
|
@ -1,4 +1,15 @@
|
||||
import { DiscordApiErrors, EVENT, Event, EventData, getPermission, PermissionResolvable, Permissions } from "@fosscord/util";
|
||||
import {
|
||||
DiscordApiErrors,
|
||||
EVENT,
|
||||
Event,
|
||||
EventData,
|
||||
FosscordApiErrors,
|
||||
getPermission,
|
||||
PermissionResolvable,
|
||||
Permissions,
|
||||
RightResolvable,
|
||||
Rights
|
||||
} from "@fosscord/util";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
@ -33,6 +44,7 @@ export type RouteResponse = { status?: number; body?: `${string}Response`; heade
|
||||
|
||||
export interface RouteOptions {
|
||||
permission?: PermissionResolvable;
|
||||
right?: RightResolvable;
|
||||
body?: `${string}Schema`; // typescript interface name
|
||||
test?: {
|
||||
response?: RouteResponse;
|
||||
@ -89,6 +101,13 @@ export function route(opts: RouteOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.right) {
|
||||
const required = new Rights(opts.right);
|
||||
if (!req.rights || !req.rights.has(required)) {
|
||||
throw FosscordApiErrors.MISSING_RIGHTS.withParams(opts.right as string);
|
||||
}
|
||||
}
|
||||
|
||||
if (validate) {
|
||||
const valid = validate(normalizeBody(req.body));
|
||||
if (!valid) {
|
||||
|
@ -38,9 +38,23 @@ async function main() {
|
||||
'${location.protocol === "https:" ? "wss://" : "ws://"}${location.host}',
|
||||
endpointPrivate: `ws://localhost:${port}`,
|
||||
...(!Config.get().gateway.endpointPublic && {
|
||||
endpointPublic: `http://localhost:${port}`,
|
||||
endpointPublic: `ws://localhost:${port}`,
|
||||
}),
|
||||
},
|
||||
// regions: {
|
||||
// default: "fosscord",
|
||||
// useDefaultAsOptimal: true,
|
||||
// available: [
|
||||
// {
|
||||
// id: "fosscord",
|
||||
// name: "Fosscord",
|
||||
// endpoint: "127.0.0.1:3001",
|
||||
// vip: false,
|
||||
// custom: false,
|
||||
// deprecated: false,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
} as any);
|
||||
|
||||
await Promise.all([api.start(), cdn.start(), gateway.start()]);
|
||||
|
@ -4,7 +4,7 @@
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"postinstall": "ts-patch install -s",
|
||||
"postinstall": "npx ts-patch install -s",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "npm run build && node dist/start.js",
|
||||
"build": "npx tsc -b .",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import "missing-native-js-functions";
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
import { closeDatabase, Config, initDatabase, initEvent, RabbitMQ } from "@fosscord/util";
|
||||
import { closeDatabase, Config, initDatabase, initEvent } from "@fosscord/util";
|
||||
import { Server as WebSocketServer } from "ws";
|
||||
import { Connection } from "./events/Connection";
|
||||
import http from "http";
|
||||
@ -12,15 +12,24 @@ export class Server {
|
||||
public server: http.Server;
|
||||
public production: boolean;
|
||||
|
||||
constructor({ port, server, production }: { port: number; server?: http.Server; production?: boolean }) {
|
||||
constructor({
|
||||
port,
|
||||
server,
|
||||
production,
|
||||
}: {
|
||||
port: number;
|
||||
server?: http.Server;
|
||||
production?: boolean;
|
||||
}) {
|
||||
this.port = port;
|
||||
this.production = production || false;
|
||||
|
||||
if (server) this.server = server;
|
||||
else
|
||||
else {
|
||||
this.server = http.createServer(function (req, res) {
|
||||
res.writeHead(200).end("Online");
|
||||
});
|
||||
}
|
||||
|
||||
this.server.on("upgrade", (request, socket, head) => {
|
||||
console.log("socket requests upgrade", request.url);
|
||||
|
@ -35,8 +35,11 @@ export async function Connection(
|
||||
// @ts-ignore
|
||||
socket.encoding = searchParams.get("encoding") || "json";
|
||||
if (!["json", "etf"].includes(socket.encoding)) {
|
||||
if (socket.encoding === "etf" && erlpack)
|
||||
throw new Error("Erlpack is not installed: 'npm i -D erlpack'");
|
||||
if (socket.encoding === "etf" && erlpack) {
|
||||
throw new Error(
|
||||
"Erlpack is not installed: 'npm i @yukikaze-bot/erlpack'"
|
||||
);
|
||||
}
|
||||
return socket.close(CLOSECODES.Decode_error);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Intents, Permissions } from "@fosscord/util";
|
||||
import WS from "ws";
|
||||
import { Deflate } from "zlib";
|
||||
import { Channel } from "amqplib";
|
||||
|
||||
export interface WebSocket extends WS {
|
||||
version: number;
|
||||
|
@ -1,5 +1,5 @@
|
||||
export * from "./Constants";
|
||||
export * from "./Send";
|
||||
export * from "./SessionUtils";
|
||||
export * from "./setHeartbeat";
|
||||
export * from "./Heartbeat";
|
||||
export * from "./WebSocket";
|
||||
|
@ -71,8 +71,7 @@
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@fosscord/gateway": ["src/index"],
|
||||
"@fosscord/gateway/*": ["src/*"],
|
||||
"@fosscord/util/*": ["../util/src/*"]
|
||||
"@fosscord/gateway/*": ["src/*"]
|
||||
},
|
||||
"plugins": [{ "transform": "@zerollup/ts-transform-paths" }]
|
||||
}
|
||||
|
@ -125,6 +125,7 @@ export interface ConfigValue {
|
||||
required: boolean;
|
||||
minimum: number; // in years
|
||||
};
|
||||
disabled: boolean;
|
||||
requireCaptcha: boolean;
|
||||
requireInvite: boolean;
|
||||
allowNewRegistration: boolean;
|
||||
@ -143,6 +144,10 @@ export interface ConfigValue {
|
||||
useDefaultAsOptimal: boolean;
|
||||
available: Region[];
|
||||
};
|
||||
|
||||
guild: {
|
||||
showAllGuildsInDiscovery: boolean;
|
||||
};
|
||||
rabbitmq: {
|
||||
host: string | null;
|
||||
};
|
||||
@ -266,6 +271,7 @@ export const DefaultConfigOptions: ConfigValue = {
|
||||
required: false,
|
||||
minimum: 13,
|
||||
},
|
||||
disabled: false,
|
||||
requireInvite: false,
|
||||
requireCaptcha: true,
|
||||
allowNewRegistration: true,
|
||||
@ -293,6 +299,10 @@ export const DefaultConfigOptions: ConfigValue = {
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
guild: {
|
||||
showAllGuildsInDiscovery: false,
|
||||
},
|
||||
rabbitmq: {
|
||||
host: null,
|
||||
},
|
||||
|
@ -74,9 +74,7 @@ export class Message extends BaseClass {
|
||||
author_id: string;
|
||||
|
||||
@JoinColumn({ name: "author_id", referencedColumnName: "id" })
|
||||
@ManyToOne(() => User, {
|
||||
onDelete: "CASCADE",
|
||||
})
|
||||
@ManyToOne(() => User)
|
||||
author?: User;
|
||||
|
||||
@Column({ nullable: true })
|
||||
@ -120,7 +118,7 @@ export class Message extends BaseClass {
|
||||
mention_everyone?: boolean;
|
||||
|
||||
@JoinTable({ name: "message_user_mentions" })
|
||||
@ManyToMany(() => User, { orphanedRowAction: "delete", onDelete: "CASCADE", cascade: true })
|
||||
@ManyToMany(() => User)
|
||||
mentions: User[];
|
||||
|
||||
@JoinTable({ name: "message_role_mentions" })
|
||||
|
@ -3,7 +3,6 @@ import { BaseClass } from "./BaseClass";
|
||||
import { BitField } from "../util/BitField";
|
||||
import { Relationship } from "./Relationship";
|
||||
import { ConnectedAccount } from "./ConnectedAccount";
|
||||
import { HTTPError } from "lambert-server";
|
||||
|
||||
export enum PublicUserEnum {
|
||||
username,
|
||||
@ -126,6 +125,9 @@ export class User extends BaseClass {
|
||||
@Column()
|
||||
public_flags: number;
|
||||
|
||||
@Column()
|
||||
rights: string; // Rights
|
||||
|
||||
@JoinColumn({ name: "relationship_ids" })
|
||||
@OneToMany(() => Relationship, (relationship: Relationship) => relationship.from, {
|
||||
cascade: true,
|
||||
@ -278,5 +280,7 @@ export class UserFlags extends BitField {
|
||||
UNDERAGE_DELETED: BigInt(1) << BigInt(15),
|
||||
VERIFIED_BOT: BigInt(1) << BigInt(16),
|
||||
EARLY_VERIFIED_BOT_DEVELOPER: BigInt(1) << BigInt(17),
|
||||
CERTIFIED_MODERATOR: BigInt(1) << BigInt(18),
|
||||
BOT_HTTP_INTERACTIONS: BigInt(1) << BigInt(19),
|
||||
};
|
||||
}
|
||||
|
@ -141,3 +141,7 @@ export class BitField {
|
||||
throw new RangeError("BITFIELD_INVALID: " + bit);
|
||||
}
|
||||
}
|
||||
|
||||
export function BitFlag(x: bigint | number) {
|
||||
return BigInt(1) << BigInt(x);
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ export const Config = {
|
||||
set: function set(val: Partial<ConfigValue>) {
|
||||
if (!config || !val) return;
|
||||
config = val.merge(config);
|
||||
console.log(config);
|
||||
|
||||
return applyConfig(config);
|
||||
},
|
||||
|
@ -726,7 +726,9 @@ export const DiscordApiErrors = {
|
||||
/**
|
||||
* An error encountered while performing an API request (Fosscord only). Here are the potential errors:
|
||||
*/
|
||||
export const FosscordApiErrors = {};
|
||||
export const FosscordApiErrors = {
|
||||
MISSING_RIGHTS: new ApiError("You lack rights to perform that action ({})", 50013, undefined, [""]),
|
||||
};
|
||||
|
||||
/**
|
||||
* The value set for a guild's default message notifications, e.g. `ALL`. Here are the available types:
|
||||
|
@ -3,8 +3,7 @@
|
||||
import { Channel, ChannelPermissionOverwrite, Guild, Member, Role } from "../entities";
|
||||
import { BitField } from "./BitField";
|
||||
import "missing-native-js-functions";
|
||||
import { BitFieldResolvable } from ".";
|
||||
// TODO: check role hierarchy permission
|
||||
import { BitFieldResolvable, BitFlag } from "./BitField";
|
||||
|
||||
var HTTPError: any;
|
||||
|
||||
@ -32,44 +31,44 @@ export class Permissions extends BitField {
|
||||
}
|
||||
|
||||
static FLAGS = {
|
||||
CREATE_INSTANT_INVITE: BigInt(1) << BigInt(0),
|
||||
KICK_MEMBERS: BigInt(1) << BigInt(1),
|
||||
BAN_MEMBERS: BigInt(1) << BigInt(2),
|
||||
ADMINISTRATOR: BigInt(1) << BigInt(3),
|
||||
MANAGE_CHANNELS: BigInt(1) << BigInt(4),
|
||||
MANAGE_GUILD: BigInt(1) << BigInt(5),
|
||||
ADD_REACTIONS: BigInt(1) << BigInt(6),
|
||||
VIEW_AUDIT_LOG: BigInt(1) << BigInt(7),
|
||||
PRIORITY_SPEAKER: BigInt(1) << BigInt(8),
|
||||
STREAM: BigInt(1) << BigInt(9),
|
||||
VIEW_CHANNEL: BigInt(1) << BigInt(10),
|
||||
SEND_MESSAGES: BigInt(1) << BigInt(11),
|
||||
SEND_TTS_MESSAGES: BigInt(1) << BigInt(12),
|
||||
MANAGE_MESSAGES: BigInt(1) << BigInt(13),
|
||||
EMBED_LINKS: BigInt(1) << BigInt(14),
|
||||
ATTACH_FILES: BigInt(1) << BigInt(15),
|
||||
READ_MESSAGE_HISTORY: BigInt(1) << BigInt(16),
|
||||
MENTION_EVERYONE: BigInt(1) << BigInt(17),
|
||||
USE_EXTERNAL_EMOJIS: BigInt(1) << BigInt(18),
|
||||
VIEW_GUILD_INSIGHTS: BigInt(1) << BigInt(19),
|
||||
CONNECT: BigInt(1) << BigInt(20),
|
||||
SPEAK: BigInt(1) << BigInt(21),
|
||||
MUTE_MEMBERS: BigInt(1) << BigInt(22),
|
||||
DEAFEN_MEMBERS: BigInt(1) << BigInt(23),
|
||||
MOVE_MEMBERS: BigInt(1) << BigInt(24),
|
||||
USE_VAD: BigInt(1) << BigInt(25),
|
||||
CHANGE_NICKNAME: BigInt(1) << BigInt(26),
|
||||
MANAGE_NICKNAMES: BigInt(1) << BigInt(27),
|
||||
MANAGE_ROLES: BigInt(1) << BigInt(28),
|
||||
MANAGE_WEBHOOKS: BigInt(1) << BigInt(29),
|
||||
MANAGE_EMOJIS_AND_STICKERS: BigInt(1) << BigInt(30),
|
||||
USE_APPLICATION_COMMANDS: BigInt(1) << BigInt(31),
|
||||
REQUEST_TO_SPEAK: BigInt(1) << BigInt(32),
|
||||
CREATE_INSTANT_INVITE: BitFlag(0),
|
||||
KICK_MEMBERS: BitFlag(1),
|
||||
BAN_MEMBERS: BitFlag(2),
|
||||
ADMINISTRATOR: BitFlag(3),
|
||||
MANAGE_CHANNELS: BitFlag(4),
|
||||
MANAGE_GUILD: BitFlag(5),
|
||||
ADD_REACTIONS: BitFlag(6),
|
||||
VIEW_AUDIT_LOG: BitFlag(7),
|
||||
PRIORITY_SPEAKER: BitFlag(8),
|
||||
STREAM: BitFlag(9),
|
||||
VIEW_CHANNEL: BitFlag(10),
|
||||
SEND_MESSAGES: BitFlag(11),
|
||||
SEND_TTS_MESSAGES: BitFlag(12),
|
||||
MANAGE_MESSAGES: BitFlag(13),
|
||||
EMBED_LINKS: BitFlag(14),
|
||||
ATTACH_FILES: BitFlag(15),
|
||||
READ_MESSAGE_HISTORY: BitFlag(16),
|
||||
MENTION_EVERYONE: BitFlag(17),
|
||||
USE_EXTERNAL_EMOJIS: BitFlag(18),
|
||||
VIEW_GUILD_INSIGHTS: BitFlag(19),
|
||||
CONNECT: BitFlag(20),
|
||||
SPEAK: BitFlag(21),
|
||||
MUTE_MEMBERS: BitFlag(22),
|
||||
DEAFEN_MEMBERS: BitFlag(23),
|
||||
MOVE_MEMBERS: BitFlag(24),
|
||||
USE_VAD: BitFlag(25),
|
||||
CHANGE_NICKNAME: BitFlag(26),
|
||||
MANAGE_NICKNAMES: BitFlag(27),
|
||||
MANAGE_ROLES: BitFlag(28),
|
||||
MANAGE_WEBHOOKS: BitFlag(29),
|
||||
MANAGE_EMOJIS_AND_STICKERS: BitFlag(30),
|
||||
USE_APPLICATION_COMMANDS: BitFlag(31),
|
||||
REQUEST_TO_SPEAK: BitFlag(32),
|
||||
// TODO: what is permission 33?
|
||||
MANAGE_THREADS: BigInt(1) << BigInt(34),
|
||||
USE_PUBLIC_THREADS: BigInt(1) << BigInt(35),
|
||||
USE_PRIVATE_THREADS: BigInt(1) << BigInt(36),
|
||||
USE_EXTERNAL_STICKERS: BigInt(1) << BigInt(37),
|
||||
MANAGE_THREADS: BitFlag(34),
|
||||
USE_PUBLIC_THREADS: BitFlag(35),
|
||||
USE_PRIVATE_THREADS: BitFlag(36),
|
||||
USE_EXTERNAL_STICKERS: BitFlag(37),
|
||||
|
||||
/**
|
||||
* CUSTOM PERMISSIONS ideas:
|
||||
|
73
util/src/util/Rights.ts
Normal file
73
util/src/util/Rights.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import { BitField } from "./BitField";
|
||||
import "missing-native-js-functions";
|
||||
import { BitFieldResolvable, BitFlag } from "./BitField";
|
||||
|
||||
var HTTPError: any;
|
||||
|
||||
try {
|
||||
HTTPError = require("lambert-server").HTTPError;
|
||||
} catch (e) {
|
||||
HTTPError = Error;
|
||||
}
|
||||
|
||||
export type RightResolvable = bigint | number | Rights | RightResolvable[] | RightString;
|
||||
|
||||
type RightString = keyof typeof Rights.FLAGS;
|
||||
// TODO: just like roles for members, users should have privilidges which combine multiple rights into one and make it easy to assign
|
||||
|
||||
export class Rights extends BitField {
|
||||
constructor(bits: BitFieldResolvable = 0) {
|
||||
super(bits);
|
||||
if (this.bitfield & Rights.FLAGS.OPERATOR) {
|
||||
this.bitfield = ALL_RIGHTS;
|
||||
}
|
||||
}
|
||||
|
||||
static FLAGS = {
|
||||
OPERATOR: BitFlag(0), // has all rights
|
||||
MANAGE_APPLICATIONS: BitFlag(1),
|
||||
MANAGE_GUILDS: BitFlag(2),
|
||||
MANAGE_MESSAGES: BitFlag(3), // Can't see other messages but delete/edit them in channels that they can see
|
||||
MANAGE_RATE_LIMITS: BitFlag(4),
|
||||
MANAGE_ROUTING: BitFlag(5), // can create custom message routes to any channel/guild
|
||||
MANAGE_TICKETS: BitFlag(6),
|
||||
MANAGE_USERS: BitFlag(7),
|
||||
ADD_MEMBERS: BitFlag(8), // can manually add any members in their guilds
|
||||
BYPASS_RATE_LIMITS: BitFlag(9),
|
||||
CREATE_APPLICATIONS: BitFlag(10),
|
||||
CREATE_CHANNELS: BitFlag(11),
|
||||
CREATE_DMS: BitFlag(12),
|
||||
CREATE_DM_GROUPS: BitFlag(13),
|
||||
CREATE_GUILDS: BitFlag(14),
|
||||
CREATE_INVITES: BitFlag(15),
|
||||
CREATE_ROLES: BitFlag(16),
|
||||
CREATE_TEMPLATES: BitFlag(17),
|
||||
CREATE_WEBHOOKS: BitFlag(18),
|
||||
JOIN_GUILDS: BitFlag(19),
|
||||
PIN_MESSAGES: BitFlag(20),
|
||||
SELF_ADD_REACTIONS: BitFlag(21),
|
||||
SELF_DELETE_MESSAGES: BitFlag(22),
|
||||
SELF_EDIT_MESSAGES: BitFlag(23),
|
||||
SELF_EDIT_NAME: BitFlag(24),
|
||||
SEND_MESSAGES: BitFlag(25),
|
||||
USE_SCREEN: BitFlag(26),
|
||||
USE_VIDEO: BitFlag(27),
|
||||
USE_VOICE: BitFlag(28),
|
||||
};
|
||||
|
||||
any(permission: RightResolvable, checkOperator = true) {
|
||||
return (checkOperator && super.any(Rights.FLAGS.OPERATOR)) || super.any(permission);
|
||||
}
|
||||
|
||||
has(permission: RightResolvable, checkOperator = true) {
|
||||
return (checkOperator && super.has(Rights.FLAGS.OPERATOR)) || super.has(permission);
|
||||
}
|
||||
|
||||
hasThrow(permission: RightResolvable) {
|
||||
if (this.has(permission)) return true;
|
||||
// @ts-ignore
|
||||
throw new HTTPError(`You are missing the following rights ${permission}`, 403);
|
||||
}
|
||||
}
|
||||
|
||||
const ALL_RIGHTS = Object.values(Rights.FLAGS).reduce((total, val) => total | val, BigInt(0));
|
@ -10,7 +10,10 @@ export function checkToken(token: string, jwtSecret: string): Promise<any> {
|
||||
jwt.verify(token, jwtSecret, JWTOptions, async (err, decoded: any) => {
|
||||
if (err || !decoded) return rej("Invalid Token");
|
||||
|
||||
const user = await User.findOne({ id: decoded.id }, { select: ["data", "bot", "disabled", "deleted"] });
|
||||
const user = await User.findOne(
|
||||
{ id: decoded.id },
|
||||
{ select: ["data", "bot", "disabled", "deleted", "rights"] }
|
||||
);
|
||||
if (!user) return rej("Invalid Token");
|
||||
// we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds
|
||||
if (decoded.iat * 1000 < new Date(user.data.valid_tokens_since).setSeconds(0, 0))
|
||||
|
@ -12,6 +12,7 @@ export * from "./MessageFlags";
|
||||
export * from "./Permissions";
|
||||
export * from "./RabbitMQ";
|
||||
export * from "./Regex";
|
||||
export * from "./Rights";
|
||||
export * from "./Snowflake";
|
||||
export * from "./String";
|
||||
export * from "./Array";
|
||||
|
Loading…
Reference in New Issue
Block a user