mirror of
https://github.com/spacebarchat/server.git
synced 2024-11-06 02:42:37 +01:00
Merge branch 'feat/multiUploads' into feat/latestWebClient
This commit is contained in:
commit
e28ae77597
@ -2,12 +2,18 @@
|
|||||||
"MessageCreateSchema": {
|
"MessageCreateSchema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"content": {
|
"content": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"nonce": {
|
"nonce": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"channel_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"tts": {
|
"tts": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
@ -46,12 +46,14 @@ export default function rateLimit(opts: {
|
|||||||
}): any {
|
}): any {
|
||||||
return async (req: Request, res: Response, next: NextFunction): Promise<any> => {
|
return async (req: Request, res: Response, next: NextFunction): Promise<any> => {
|
||||||
// exempt user? if so, immediately short circuit
|
// exempt user? if so, immediately short circuit
|
||||||
const rights = await getRights(req.user_id);
|
if (req.user_id) {
|
||||||
if (rights.has("BYPASS_RATE_LIMITS")) return;
|
const rights = await getRights(req.user_id);
|
||||||
|
if (rights.has("BYPASS_RATE_LIMITS")) return;
|
||||||
|
}
|
||||||
|
|
||||||
const bucket_id = opts.bucket || req.originalUrl.replace(API_PREFIX_TRAILING_SLASH, "");
|
const bucket_id = opts.bucket || req.originalUrl.replace(API_PREFIX_TRAILING_SLASH, "");
|
||||||
var executor_id = getIpAdress(req);
|
var executor_id = getIpAdress(req);
|
||||||
if (!opts.onlyIp && req.user_id) executor_id = req.user_id;
|
if (!opts.onlyIp && req.user_id) executor_id = req.user_id;
|
||||||
|
|
||||||
var max_hits = opts.count;
|
var max_hits = opts.count;
|
||||||
if (opts.bot && req.user_bot) max_hits = opts.bot;
|
if (opts.bot && req.user_bot) max_hits = opts.bot;
|
||||||
@ -161,7 +163,7 @@ export async function initRateLimits(app: Router) {
|
|||||||
app.use("/auth/register", rateLimit({ onlyIp: true, success: true, ...routes.auth.register }));
|
app.use("/auth/register", rateLimit({ onlyIp: true, success: true, ...routes.auth.register }));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function hitRoute(opts: { executor_id: string; bucket_id: string; max_hits: number; window: number }) {
|
async function hitRoute(opts: { executor_id: string; bucket_id: string; max_hits: number; window: number; }) {
|
||||||
const id = opts.executor_id + opts.bucket_id;
|
const id = opts.executor_id + opts.bucket_id;
|
||||||
var limit = Cache.get(id);
|
var limit = Cache.get(id);
|
||||||
if (!limit) {
|
if (!limit) {
|
||||||
|
@ -17,7 +17,7 @@ import {
|
|||||||
} from "@fosscord/util";
|
} from "@fosscord/util";
|
||||||
import { HTTPError } from "lambert-server";
|
import { HTTPError } from "lambert-server";
|
||||||
import { handleMessage, postHandleMessage, route } from "@fosscord/api";
|
import { handleMessage, postHandleMessage, route } from "@fosscord/api";
|
||||||
import multer from "multer";
|
import multer, { Multer } from "multer";
|
||||||
import { FindManyOptions, LessThan, MoreThan } from "typeorm";
|
import { FindManyOptions, LessThan, MoreThan } from "typeorm";
|
||||||
import { URL } from "url";
|
import { URL } from "url";
|
||||||
|
|
||||||
@ -50,8 +50,10 @@ export function isTextChannel(type: ChannelType): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageCreateSchema {
|
export interface MessageCreateSchema {
|
||||||
|
type?: number;
|
||||||
content?: string;
|
content?: string;
|
||||||
nonce?: string;
|
nonce?: string;
|
||||||
|
channel_id?: string;
|
||||||
tts?: boolean;
|
tts?: boolean;
|
||||||
flags?: string;
|
flags?: string;
|
||||||
embeds?: Embed[];
|
embeds?: Embed[];
|
||||||
@ -161,7 +163,7 @@ const messageUpload = multer({
|
|||||||
limits: {
|
limits: {
|
||||||
fileSize: 1024 * 1024 * 100,
|
fileSize: 1024 * 1024 * 100,
|
||||||
fields: 10,
|
fields: 10,
|
||||||
files: 1
|
// files: 1
|
||||||
},
|
},
|
||||||
storage: multer.memoryStorage()
|
storage: multer.memoryStorage()
|
||||||
}); // max upload 50 mb
|
}); // max upload 50 mb
|
||||||
@ -176,7 +178,7 @@ const messageUpload = multer({
|
|||||||
// Send message
|
// Send message
|
||||||
router.post(
|
router.post(
|
||||||
"/",
|
"/",
|
||||||
messageUpload.single("file"),
|
messageUpload.any(),
|
||||||
async (req, res, next) => {
|
async (req, res, next) => {
|
||||||
if (req.body.payload_json) {
|
if (req.body.payload_json) {
|
||||||
req.body = JSON.parse(req.body.payload_json);
|
req.body = JSON.parse(req.body.payload_json);
|
||||||
@ -190,19 +192,22 @@ router.post(
|
|||||||
var body = req.body as MessageCreateSchema;
|
var body = req.body as MessageCreateSchema;
|
||||||
const attachments: Attachment[] = [];
|
const attachments: Attachment[] = [];
|
||||||
|
|
||||||
if (req.file) {
|
|
||||||
try {
|
|
||||||
const file = await uploadFile(`/attachments/${req.params.channel_id}`, req.file);
|
|
||||||
attachments.push({ ...file, proxy_url: file.url });
|
|
||||||
} catch (error) {
|
|
||||||
return res.status(400).json(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients", "recipients.user"] });
|
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients", "recipients.user"] });
|
||||||
if (!channel.isWritable()) {
|
if (!channel.isWritable()) {
|
||||||
throw new HTTPError(`Cannot send messages to channel of type ${channel.type}`, 400)
|
throw new HTTPError(`Cannot send messages to channel of type ${channel.type}`, 400)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const files = req.files as Express.Multer.File[] ?? [];
|
||||||
|
for (var currFile of files) {
|
||||||
|
try {
|
||||||
|
const file = await uploadFile(`/attachments/${channel.id}`, currFile);
|
||||||
|
attachments.push({ ...file, proxy_url: file.url });
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
return res.status(400).json(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const embeds = body.embeds || [];
|
const embeds = body.embeds || [];
|
||||||
if (body.embed) embeds.push(body.embed);
|
if (body.embed) embeds.push(body.embed);
|
||||||
let message = await handleMessage({
|
let message = await handleMessage({
|
||||||
|
68
api/src/routes/guilds/#guild_id/roles/#role_id/index.ts
Normal file
68
api/src/routes/guilds/#guild_id/roles/#role_id/index.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import { Router, Request, Response } from "express";
|
||||||
|
import { Role, Member, GuildRoleUpdateEvent, GuildRoleDeleteEvent, emitEvent, handleFile } from "@fosscord/util";
|
||||||
|
import { route } from "@fosscord/api";
|
||||||
|
import { HTTPError } from "lambert-server";
|
||||||
|
import { RoleModifySchema } from "../";
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
|
||||||
|
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||||
|
const { guild_id, role_id } = req.params;
|
||||||
|
await Member.IsInGuildOrFail(req.user_id, guild_id);
|
||||||
|
const role = await Role.findOneOrFail({ guild_id, id: role_id });
|
||||||
|
return res.json(role);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.delete("/", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
|
||||||
|
const { guild_id, role_id } = req.params;
|
||||||
|
if (role_id === guild_id) throw new HTTPError("You can't delete the @everyone role");
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
Role.delete({
|
||||||
|
id: role_id,
|
||||||
|
guild_id: guild_id
|
||||||
|
}),
|
||||||
|
emitEvent({
|
||||||
|
event: "GUILD_ROLE_DELETE",
|
||||||
|
guild_id,
|
||||||
|
data: {
|
||||||
|
guild_id,
|
||||||
|
role_id
|
||||||
|
}
|
||||||
|
} as GuildRoleDeleteEvent)
|
||||||
|
]);
|
||||||
|
|
||||||
|
res.sendStatus(204);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: check role hierarchy
|
||||||
|
|
||||||
|
router.patch("/", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
|
||||||
|
const { role_id, guild_id } = req.params;
|
||||||
|
const body = req.body as RoleModifySchema;
|
||||||
|
|
||||||
|
if (body.icon) body.icon = await handleFile(`/role-icons/${role_id}`, body.icon as string);
|
||||||
|
|
||||||
|
const role = new Role({
|
||||||
|
...body,
|
||||||
|
id: role_id,
|
||||||
|
guild_id,
|
||||||
|
permissions: String(req.permission!.bitfield & BigInt(body.permissions || "0"))
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
role.save(),
|
||||||
|
emitEvent({
|
||||||
|
event: "GUILD_ROLE_UPDATE",
|
||||||
|
guild_id,
|
||||||
|
data: {
|
||||||
|
guild_id,
|
||||||
|
role
|
||||||
|
}
|
||||||
|
} as GuildRoleUpdateEvent)
|
||||||
|
]);
|
||||||
|
|
||||||
|
res.json(role);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
@ -81,59 +81,6 @@ router.post("/", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" })
|
|||||||
res.json(role);
|
res.json(role);
|
||||||
});
|
});
|
||||||
|
|
||||||
router.delete("/:role_id", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
|
|
||||||
const guild_id = req.params.guild_id;
|
|
||||||
const { role_id } = req.params;
|
|
||||||
if (role_id === guild_id) throw new HTTPError("You can't delete the @everyone role");
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
Role.delete({
|
|
||||||
id: role_id,
|
|
||||||
guild_id: guild_id
|
|
||||||
}),
|
|
||||||
emitEvent({
|
|
||||||
event: "GUILD_ROLE_DELETE",
|
|
||||||
guild_id,
|
|
||||||
data: {
|
|
||||||
guild_id,
|
|
||||||
role_id
|
|
||||||
}
|
|
||||||
} as GuildRoleDeleteEvent)
|
|
||||||
]);
|
|
||||||
|
|
||||||
res.sendStatus(204);
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: check role hierarchy
|
|
||||||
|
|
||||||
router.patch("/:role_id", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
|
|
||||||
const { role_id, guild_id } = req.params;
|
|
||||||
const body = req.body as RoleModifySchema;
|
|
||||||
|
|
||||||
if (body.icon) body.icon = await handleFile(`/role-icons/${role_id}`, body.icon as string);
|
|
||||||
|
|
||||||
const role = new Role({
|
|
||||||
...body,
|
|
||||||
id: role_id,
|
|
||||||
guild_id,
|
|
||||||
permissions: String(req.permission!.bitfield & BigInt(body.permissions || "0"))
|
|
||||||
});
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
role.save(),
|
|
||||||
emitEvent({
|
|
||||||
event: "GUILD_ROLE_UPDATE",
|
|
||||||
guild_id,
|
|
||||||
data: {
|
|
||||||
guild_id,
|
|
||||||
role
|
|
||||||
}
|
|
||||||
} as GuildRoleUpdateEvent)
|
|
||||||
]);
|
|
||||||
|
|
||||||
res.json(role);
|
|
||||||
});
|
|
||||||
|
|
||||||
router.patch("/", route({ body: "RolePositionUpdateSchema" }), async (req: Request, res: Response) => {
|
router.patch("/", route({ body: "RolePositionUpdateSchema" }), async (req: Request, res: Response) => {
|
||||||
const { guild_id } = req.params;
|
const { guild_id } = req.params;
|
||||||
const body = req.body as RolePositionUpdateSchema;
|
const body = req.body as RolePositionUpdateSchema;
|
Loading…
Reference in New Issue
Block a user