This commit is contained in:
Flam3rboy 2021-09-28 22:27:01 +02:00
commit dc01de5f6d
21 changed files with 6252 additions and 6806 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,33 @@
{
"LoginSchema": {
"type": "object",
"properties": {
"login": {
"type": "string"
},
"password": {
"type": "string"
},
"undelete": {
"type": "boolean"
},
"captcha_key": {
"type": "string"
},
"login_source": {
"type": "string"
},
"gift_code_sku_id": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"login",
"password"
],
"$schema": "http://json-schema.org/draft-07/schema#"
},
"RegisterSchema": {
"type": "object",
"properties": {
@ -42,35 +71,6 @@
],
"$schema": "http://json-schema.org/draft-07/schema#"
},
"LoginSchema": {
"type": "object",
"properties": {
"login": {
"type": "string"
},
"password": {
"type": "string"
},
"undelete": {
"type": "boolean"
},
"captcha_key": {
"type": "string"
},
"login_source": {
"type": "string"
},
"gift_code_sku_id": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"login",
"password"
],
"$schema": "http://json-schema.org/draft-07/schema#"
},
"ChannelModifySchema": {
"type": "object",
"properties": {
@ -127,10 +127,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -353,10 +353,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -727,10 +727,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -1050,10 +1050,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -1352,10 +1352,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -1657,10 +1657,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -1758,10 +1758,10 @@
"type": "object",
"properties": {
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
},
"id": {
"type": "string"
@ -1971,10 +1971,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -2278,10 +2278,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -2580,10 +2580,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -2894,10 +2894,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -3221,10 +3221,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -3587,10 +3587,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -3889,10 +3889,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -4191,10 +4191,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -4505,10 +4505,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -4814,10 +4814,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -5119,10 +5119,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -5424,10 +5424,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -5725,10 +5725,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -6046,10 +6046,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -6374,10 +6374,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -6680,10 +6680,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -6988,10 +6988,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -7302,10 +7302,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -7610,10 +7610,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -7939,10 +7939,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -8244,10 +8244,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -8550,10 +8550,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,
@ -9039,10 +9039,10 @@
"$ref": "#/definitions/ChannelPermissionOverwriteType"
},
"allow": {
"type": "bigint"
"type": "string"
},
"deny": {
"type": "bigint"
"type": "string"
}
},
"additionalProperties": false,

View File

@ -14,8 +14,8 @@
"dev": "tsnd --respawn src/start.ts",
"patch": "ts-patch install -s && npx patch-package",
"postinstall": "npm run patch",
"generate:docs": "node scripts/generate_openapi.ts",
"generate:schema": "node scripts/generate_schema.ts"
"generate:docs": "node scripts/generate_openapi",
"generate:schema": "node scripts/generate_schema"
},
"repository": {
"type": "git",

View File

@ -1,9 +1,9 @@
// https://mermade.github.io/openapi-gui/#
// https://editor.swagger.io/
import path from "path";
import fs from "fs";
import * as TJS from "typescript-json-schema";
import "missing-native-js-functions";
const path = require("path");
const fs = require("fs");
const TJS = require("typescript-json-schema");
require("missing-native-js-functions");
const schemaPath = path.join(__dirname, "..", "assets", "schemas.json");
const settings = {

View File

@ -62,8 +62,8 @@ export interface ChannelModifySchema {
permission_overwrites?: {
id: string;
type: ChannelPermissionOverwriteType;
allow: bigint;
deny: bigint;
allow: string;
deny: string;
}[];
parent_id?: string;
id?: string; // is not used (only for guild create)

View File

@ -3,6 +3,7 @@ import {
Attachment,
Channel,
ChannelType,
Config,
DmChannelDTO,
Embed,
emitEvent,
@ -15,6 +16,7 @@ import { HTTPError } from "lambert-server";
import { handleMessage, postHandleMessage, route } from "@fosscord/api";
import multer from "multer";
import { FindManyOptions, LessThan, MoreThan } from "typeorm";
import { URL } from "url";
const router: Router = Router();
@ -111,6 +113,9 @@ router.get("/", async (req: Request, res: Response) => {
});
// @ts-ignore
if (!x.author) x.author = { discriminator: "0000", username: "Deleted User", public_flags: "0", avatar: null };
x.attachments?.forEach((x) => {
x.proxy_url = `${Config.get().cdn.endpointPublic || "http://localhost:3003"}${new URL(x.proxy_url).pathname}`;
});
return x;
})

View File

@ -1,4 +1,13 @@
import { Channel, ChannelPermissionOverwrite, ChannelUpdateEvent, emitEvent, getPermission, Member, Role } from "@fosscord/util";
import {
Channel,
ChannelPermissionOverwrite,
ChannelPermissionOverwriteType,
ChannelUpdateEvent,
emitEvent,
getPermission,
Member,
Role
} from "@fosscord/util";
import { Router, Response, Request } from "express";
import { HTTPError } from "lambert-server";
@ -14,7 +23,7 @@ router.put(
route({ body: "ChannelPermissionOverwriteSchema", permission: "MANAGE_ROLES" }),
async (req: Request, res: Response) => {
const { channel_id, overwrite_id } = req.params;
const body = req.body as { allow: bigint; deny: bigint; type: number; id: string };
const body = req.body as ChannelPermissionOverwriteSchema;
var channel = await Channel.findOneOrFail({ id: channel_id });
if (!channel.guild_id) throw new HTTPError("Channel not found", 404);
@ -31,14 +40,12 @@ router.put(
// @ts-ignore
overwrite = {
id: overwrite_id,
type: body.type,
allow: body.allow,
deny: body.deny
type: body.type
};
channel.permission_overwrites!.push(overwrite);
}
overwrite.allow = body.allow;
overwrite.deny = body.deny;
overwrite.allow = String(req.permission!.bitfield & (BigInt(body.allow) || 0n));
overwrite.deny = String(req.permission!.bitfield & (BigInt(body.deny) || 0n));
await Promise.all([
channel.save(),

View File

@ -5,14 +5,14 @@ import { route } from "@fosscord/api";
const router = Router();
router.get("/", route({}), (req: Request, res: Response) => {
const { endpoint } = Config.get().gateway;
res.json({ url: endpoint || process.env.GATEWAY || "ws://localhost:3002" });
const { endpointPublic } = Config.get().gateway;
res.json({ url: endpointPublic || process.env.GATEWAY || "ws://localhost:3002" });
});
router.get("/bot", route({}), (req: Request, res: Response) => {
const { endpoint } = Config.get().gateway;
const { endpointPublic } = Config.get().gateway;
res.json({
url: endpoint || process.env.GATEWAY || "ws://localhost:3002",
url: endpointPublic || process.env.GATEWAY || "ws://localhost:3002",
shards: 1,
session_start_limit: {
total: 1000,

View File

@ -87,19 +87,21 @@ router.post("/", route({ body: "GuildCreateSchema" }), async (req: Request, res:
});
await Promise.all(
body.channels?.map((x) => {
var id = ids.get(x.id) || Snowflake.generate();
body.channels
?.sort((a, b) => (a.parent_id ? -1 : 1))
.map((x) => {
var id = ids.get(x.id) || Snowflake.generate();
// TODO: should we abort if parent_id is a category? (to disallow sub category channels)
var parent_id = ids.get(x.parent_id);
// TODO: should we abort if parent_id is a category? (to disallow sub category channels)
var parent_id = ids.get(x.parent_id);
return Channel.createChannel({ ...x, guild_id, id, parent_id }, req.user_id, {
keepId: true,
skipExistsCheck: true,
skipPermissionCheck: true,
skipEventEmit: true
});
})
return Channel.createChannel({ ...x, guild_id, id, parent_id }, req.user_id, {
keepId: true,
skipExistsCheck: true,
skipPermissionCheck: true,
skipEventEmit: true
});
})
);
await Member.addToGuild(req.user_id, guild_id);

View File

@ -1,53 +0,0 @@
import { Config } from "@fosscord/util";
import FormData from "form-data";
import { HTTPError } from "lambert-server";
import fetch from "node-fetch";
export async function uploadFile(path: string, file: Express.Multer.File) {
const form = new FormData();
form.append("file", file.buffer, {
contentType: file.mimetype,
filename: file.originalname
});
const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, {
headers: {
signature: Config.get().security.requestSignature,
...form.getHeaders()
},
method: "POST",
body: form
});
const result = await response.json();
if (response.status !== 200) throw result;
return result;
}
export async function handleFile(path: string, body?: string): Promise<string | undefined> {
if (!body || !body.startsWith("data:")) return body;
try {
const mimetype = body.split(":")[1].split(";")[0];
const buffer = Buffer.from(body.split(",")[1], "base64");
// @ts-ignore
const { id } = await uploadFile(path, { buffer, mimetype, originalname: "banner" });
return id;
} catch (error) {
console.error(error);
throw new HTTPError("Invalid " + path);
}
}
export async function deleteFile(path: string) {
const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, {
headers: {
signature: Config.get().security.requestSignature
},
method: "DELETE"
});
const result = await response.json();
if (response.status !== 200) throw result;
return result;
}

View File

@ -81,10 +81,10 @@ export function route(opts: RouteOptions) {
return async (req: Request, res: Response, next: NextFunction) => {
if (opts.permission) {
const required = new Permissions(opts.permission);
const permission = await getPermission(req.user_id, req.params.guild_id, req.params.channel_id);
req.permission = await getPermission(req.user_id, req.params.guild_id, req.params.channel_id);
// bitfield comparison: check if user lacks certain permission
if (!permission.has(required)) {
if (!req.permission.has(required)) {
throw DiscordApiErrors.MISSING_PERMISSIONS.withParams(opts.permission as string);
}
}

View File

@ -24,16 +24,24 @@ const gateway = new GatewayServer({ server, port, production });
async function main() {
await initDatabase();
await Config.init();
// only set endpointPublic, if not already set
await Config.set({
cdn: {
endpointClient: "${location.host}",
endpoint: `http://localhost:${port}`,
endpointPrivate: `http://localhost:${port}`,
...(!Config.get().cdn.endpointPublic && {
endpointPublic: `http://localhost:${port}`,
}),
},
gateway: {
endpointClient: '${location.protocol === "https:" ? "wss://" : "ws://"}${location.host}',
endpoint: `ws://localhost:${port}`,
endpointClient:
'${location.protocol === "https:" ? "wss://" : "ws://"}${location.host}',
endpointPrivate: `ws://localhost:${port}`,
...(!Config.get().gateway.endpointPublic && {
endpointPublic: `http://localhost:${port}`,
}),
},
});
} as any);
await Promise.all([api.start(), cdn.start(), gateway.start()]);
console.log(`[Server] listening on port ${port}`);

View File

@ -9,16 +9,20 @@ export function initStats() {
console.log(`[Process] running with pid: ${process.pid}`);
setInterval(async () => {
const [cpuUsed, memory, network] = await Promise.all([osu.cpu.usage(), osu.mem.info(), osu.netstat.inOut()]);
const [cpuUsed, memory, network] = await Promise.all([
osu.cpu.usage(),
osu.mem.info(),
osu.netstat.inOut(),
]);
var networkUsage = "";
if (typeof network === "object") {
networkUsage = `| [Network]: in ${network.total.inputMb}mb | out ${network.total.outputMb}mb`;
}
console.log(
`[CPU] ${cpuUsed.toFixed(2)}% | [Memory] ${Math.round(
`[CPU] ${cpuUsed.toPrecision(3)}% | [Memory] ${Math.round(
process.memoryUsage().rss / 1024 / 1024
)}mb/${memory.totalMemMb.toFixed(0)}mb ${networkUsage}`
);
}, 1000 * 30);
}, 1000 * 5);
}

View File

@ -8,6 +8,13 @@ import imageSize from "image-size";
const router = Router();
const SANITIZED_CONTENT_TYPE = [
"text/html",
"text/mhtml",
"multipart/related",
"application/xhtml+xml",
];
router.post(
"/:channel_id",
multer.single("file"),
@ -24,7 +31,8 @@ router.post(
const id = Snowflake.generate();
const path = `attachments/${channel_id}/${id}/${filename}`;
const endpoint = Config.get()?.cdn.endpoint || "http://localhost:3003";
const endpoint =
Config.get()?.cdn.endpointPublic || "http://localhost:3003";
await storage.set(path, buffer);
var width;
@ -61,8 +69,13 @@ router.get(
);
if (!file) throw new HTTPError("File not found");
const type = await FileType.fromBuffer(file);
let content_type = type?.mime || "application/octet-stream";
res.set("Content-Type", type?.mime);
if (SANITIZED_CONTENT_TYPE.includes(content_type)) {
content_type = "application/octet-stream";
}
res.set("Content-Type", content_type);
res.set("Cache-Control", "public, max-age=31536000");
return res.send(file);

View File

@ -44,7 +44,8 @@ router.post(
if (ANIMATED_MIME_TYPES.includes(type.mime)) hash = `a_${hash}`; // animated icons have a_ infront of the hash
const path = `avatars/${user_id}/${hash}`;
const endpoint = Config.get().cdn.endpoint || "http://localhost:3003";
const endpoint =
Config.get().cdn.endpointPublic || "http://localhost:3003";
await storage.set(path, buffer);

View File

@ -320,8 +320,8 @@ export class Channel extends BaseClass {
}
export interface ChannelPermissionOverwrite {
allow: bigint; // for bitfields we use bigints
deny: bigint; // for bitfields we use bigints
allow: string;
deny: string;
id: string;
type: ChannelPermissionOverwriteType;
}

View File

@ -1,12 +1,15 @@
import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
import { BaseClass } from "./BaseClass";
import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm";
import { BaseClass, BaseClassWithoutId } from "./BaseClass";
import crypto from "crypto";
import { Snowflake } from "../util/Snowflake";
@Entity("config")
export class ConfigEntity extends BaseClass {
@Column({ type: "simple-json" })
value: ConfigValue;
export class ConfigEntity extends BaseClassWithoutId {
@PrimaryColumn()
key: string;
@Column({ type: "simple-json", nullable: true })
value: number | boolean | null | string | undefined;
}
export interface RateLimitOptions {
@ -37,14 +40,16 @@ export interface KafkaBroker {
export interface ConfigValue {
gateway: {
endpointClient: string | null;
endpoint: string | null;
endpointPrivate: string | null;
endpointPublic: string | null;
};
cdn: {
endpointClient: string | null;
endpoint: string | null;
endpointPublic: string | null;
endpointPrivate: string | null;
};
general: {
instance_id: string;
instanceId: string;
};
permissions: {
user: {
@ -149,14 +154,16 @@ export interface ConfigValue {
export const DefaultConfigOptions: ConfigValue = {
gateway: {
endpointClient: null,
endpoint: null,
endpointPrivate: null,
endpointPublic: null,
},
cdn: {
endpointClient: null,
endpoint: null,
endpointPrivate: null,
endpointPublic: null,
},
general: {
instance_id: Snowflake.generate(),
instanceId: Snowflake.generate(),
},
permissions: {
user: {

View File

@ -1,22 +1,66 @@
import "missing-native-js-functions";
import { ConfigValue, ConfigEntity, DefaultConfigOptions } from "../entities/Config";
var config: ConfigEntity;
var config: ConfigValue;
var pairs: ConfigEntity[];
// TODO: use events to inform about config updates
// Config keys are separated with _
export const Config = {
init: async function init() {
if (config) return config;
config = (await ConfigEntity.findOne({ id: "0" })) || new ConfigEntity({ id: "0" });
pairs = await ConfigEntity.find();
config = pairsToConfig(pairs);
return this.set((config.value || {}).merge(DefaultConfigOptions));
return this.set((config || {}).merge(DefaultConfigOptions));
},
get: function get() {
return config.value as ConfigValue;
return config;
},
set: function set(val: Partial<ConfigValue>) {
if (!config) return;
config.value = val.merge(config?.value || {});
return config.save();
if (!config || !val) return;
config = val.merge(config);
console.log(config);
return applyConfig(config);
},
};
function applyConfig(val: ConfigValue) {
async function apply(obj: any, key = ""): Promise<any> {
if (typeof obj === "object" && obj !== null)
return Promise.all(Object.keys(obj).map((k) => apply(obj[k], key ? `${key}_${k}` : k)));
let pair = pairs.find((x) => x.key === key);
if (!pair) pair = new ConfigEntity();
pair.key = key;
pair.value = obj;
return pair.save();
}
return apply(val);
}
function pairsToConfig(pairs: ConfigEntity[]) {
var value: any = {};
pairs.forEach((p) => {
const keys = p.key.split("_");
let prev = "";
let obj = value;
let i = 0;
for (const key of keys) {
if (Number(key) && !obj[prev]) obj = obj[prev] = [];
if (i++ === keys.length - 1) obj[key] = p.value;
else if (!obj[key]) obj[key] = {};
prev = key;
obj = obj[key];
}
});
return value as ConfigValue;
}

View File

@ -22,7 +22,7 @@ export function initDatabase() {
//
entities: Object.values(Models).filter((x) => x.constructor.name !== "Object"),
synchronize: true,
logging: true,
logging: false,
cache: {
duration: 1000 * 3, // cache all find queries for 3 seconds
},

View File

@ -3,6 +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
var HTTPError: any;
@ -17,11 +18,19 @@ export type PermissionResolvable = bigint | number | Permissions | PermissionRes
type PermissionString = keyof typeof Permissions.FLAGS;
const CUSTOM_PERMISSION_OFFSET = BigInt(1) << BigInt(48); // 16 free custom permission bits, and 11 for discord to add new ones
// BigInt doesn't have a bit limit (https://stackoverflow.com/questions/53335545/whats-the-biggest-bigint-value-in-js-as-per-spec)
const CUSTOM_PERMISSION_OFFSET = BigInt(1) << BigInt(64); // 27 permission bits left for discord to add new ones
export class Permissions extends BitField {
cache: PermissionCache = {};
constructor(bits: BitFieldResolvable = 0) {
super(bits);
if (this.bitfield & Permissions.FLAGS.ADMINISTRATOR) {
this.bitfield = ALL_PERMISSIONS;
}
}
static FLAGS = {
CREATE_INSTANT_INVITE: BigInt(1) << BigInt(0),
KICK_MEMBERS: BigInt(1) << BigInt(1),
@ -92,7 +101,7 @@ export class Permissions extends BitField {
}
overwriteChannel(overwrites: ChannelPermissionOverwrite[]) {
if (!overwrites) return this
if (!overwrites) return this;
if (!this.cache) throw new Error("permission chache not available");
overwrites = overwrites.filter((x) => {
if (x.type === 0 && this.cache.roles?.some((r) => r.id === x.id)) return true;
@ -175,6 +184,8 @@ export class Permissions extends BitField {
}
}
const ALL_PERMISSIONS = Object.values(Permissions.FLAGS).reduce((total, val) => total | val, BigInt(0));
export type PermissionCache = {
channel?: Channel | undefined;
member?: Member | undefined;

View File

@ -11,7 +11,7 @@ export async function uploadFile(path: string, file: Express.Multer.File) {
filename: file.originalname,
});
const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, {
const response = await fetch(`${Config.get().cdn.endpointPrivate || "http://localhost:3003"}${path}`, {
headers: {
signature: Config.get().security.requestSignature,
...form.getHeaders(),
@ -41,7 +41,7 @@ export async function handleFile(path: string, body?: string): Promise<string |
}
export async function deleteFile(path: string) {
const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, {
const response = await fetch(`${Config.get().cdn.endpointPrivate || "http://localhost:3003"}${path}`, {
headers: {
signature: Config.get().security.requestSignature,
},