Merge branch 'master' of https://github.com/fosscord/fosscord-server
This commit is contained in:
		
						commit
						dc01de5f6d
					
				
							
								
								
									
										12591
									
								
								api/assets/openapi.json
									
									
									
									
									
								
							
							
						
						
									
										12591
									
								
								api/assets/openapi.json
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -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, | ||||
|  | ||||
| @ -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", | ||||
|  | ||||
| @ -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 = { | ||||
|  | ||||
| @ -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)
 | ||||
|  | ||||
| @ -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; | ||||
| 		}) | ||||
|  | ||||
| @ -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(), | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
| @ -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); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @ -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}`); | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
|  | ||||
| @ -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: { | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
|  | ||||
| @ -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
 | ||||
| 		}, | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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, | ||||
| 		}, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Flam3rboy
						Flam3rboy