From d61bbe82936cffe60375436952218775ec1c4506 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 30 May 2021 01:44:09 +0200 Subject: [PATCH] :sparkles: message attachments --- package-lock.json | Bin 780747 -> 780651 bytes package.json | 5 +- .../#channel_id/messages/#message_id/index.ts | 2 + .../channels/#channel_id/messages/index.ts | 49 +++++++++++------- src/schema/Message.ts | 1 + src/util/Message.ts | 2 +- src/util/cdn.ts | 24 +++++++++ 7 files changed, 62 insertions(+), 21 deletions(-) create mode 100644 src/util/cdn.ts diff --git a/package-lock.json b/package-lock.json index 35201da45e0e1640d76a299811f6619d5a45378c..052f63c6c16a324b691de992763e8cb57faae492 100644 GIT binary patch delta 620 zcmX?oS^xDV{Ry9#3=KAZ?q{5Q;F-vDn=5P_lbe|qFd9#C^8Ilj>z^i z_0um1b@U3YbT&6i^9qQ});0}IH*ik!$__{}i0~^83iB!`t+L2A2r^2a9w^2lKY9Lj z_RZOB`xqy`@)Oy7J5cl5^v_$F#I|c`Fm9bWJw}X0WIOXAMpd8bnOcm})8$wg6}Ol0 zF>P-KOSSt?V%qLMiTOy^eMz*10s;Q$> zvSDUMg@ziK&Vf-yL+W}wpmVDXns_= zxsj=lOL|yEex$qibi?^9O6`ATS%8>z`(IhMX)S2s6iSnDn*MP_1^a53?cKT@u7w~0q3J(0S&iCN=5uUUna^1pM311E YsLLfY{kJU3s&@U)oZIz3bIth%0RAxJD*ylh delta 620 zcmaETN&oa^{Ry8KEjNDYXPi8bY2oy)C2U-qJ(*v6Pd6%M(x05jH*7ub_=t}&u}v< z@bxJS^h%3JPAV&QjjVD{bu%pR^vur63s23c2=O-Zvds4KD)0+W4R@P<(T7o?{iZAn z5VLN-Da$sag&u)3U4flTW||;7`{X$+YMa-xH8O7JT*?-)d-~)+cB$>z3G6~0)4N4E zl($cK!M@sMx&j{)+tf}*;q5NE95#j1bEdLzO&4folbEhMi7Bl8#XOGfFXnMZ2GJ+P Y0_{0urUOH4Rr~o*oZHWT;+pdf02Vmdi2wiq diff --git a/package.json b/package.json index 0f651646..b3b2414b 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ }, "homepage": "https://github.com/fosscord/fosscord-api#readme", "dependencies": { - "@fosscord/server-util": "^1.3.9", + "@fosscord/server-util": "^1.3.10", "@types/jest": "^26.0.22", "@types/json-schema": "^7.0.7", "ajv": "^8.4.0", @@ -44,11 +44,12 @@ "env-paths": "^2.2.1", "express": "^4.17.1", "express-validator": "^6.9.2", + "form-data": "^3.0.0", "i18next": "^19.8.5", "i18next-http-middleware": "^3.1.3", "i18next-node-fs-backend": "^2.1.3", "jsonwebtoken": "^8.5.1", - "lambert-server": "^1.2.2", + "lambert-server": "^1.2.3", "missing-native-js-functions": "^1.2.6", "mongodb": "^3.6.5", "mongoose": "^5.12.3", diff --git a/src/routes/channels/#channel_id/messages/#message_id/index.ts b/src/routes/channels/#channel_id/messages/#message_id/index.ts index cfff07d1..aee517fc 100644 --- a/src/routes/channels/#channel_id/messages/#message_id/index.ts +++ b/src/routes/channels/#channel_id/messages/#message_id/index.ts @@ -45,6 +45,8 @@ router.patch("/", check(MessageCreateSchema), async (req, res) => { return res.json(toObject(message)); }); +// TODO: delete attachments in message + router.delete("/", async (req, res) => { const { message_id, channel_id } = req.params; diff --git a/src/routes/channels/#channel_id/messages/index.ts b/src/routes/channels/#channel_id/messages/index.ts index cdc46d14..4bf1516d 100644 --- a/src/routes/channels/#channel_id/messages/index.ts +++ b/src/routes/channels/#channel_id/messages/index.ts @@ -1,24 +1,13 @@ import { Router } from "express"; -import { - ChannelModel, - ChannelType, - getPermission, - Message, - MessageCreateEvent, - MessageDocument, - MessageModel, - Snowflake, - toObject -} from "@fosscord/server-util"; +import { Attachment, ChannelModel, ChannelType, getPermission, MessageDocument, MessageModel, toObject } from "@fosscord/server-util"; import { HTTPError } from "lambert-server"; import { MessageCreateSchema } from "../../../../schema/Message"; import { check, instanceOf, Length } from "../../../../util/instanceOf"; -import { PublicUserProjection } from "../../../../util/User"; import multer from "multer"; -import { emitEvent } from "../../../../util/Event"; import { Query } from "mongoose"; -import { PublicMemberProjection } from "../../../../util/Member"; import { sendMessage } from "../../../../util/Message"; +import { uploadFile } from "../../../../util/cdn"; + const router: Router = Router(); export default router; @@ -93,7 +82,14 @@ router.get("/", async (req, res) => { }); // TODO: config max upload size -const messageUpload = multer({ limits: { fieldSize: 1024 * 1024 * 1024 * 50 } }); // max upload 50 mb +const messageUpload = multer({ + limits: { + fileSize: 1024 * 1024 * 100, + fields: 10, + files: 1 + }, + storage: multer.memoryStorage() +}); // max upload 50 mb // TODO: dynamically change limit of MessageCreateSchema with config // TODO: check: sum of all characters in an embed structure must not exceed 6000 characters @@ -101,14 +97,31 @@ const messageUpload = multer({ limits: { fieldSize: 1024 * 1024 * 1024 * 50 } }) // https://discord.com/developers/docs/resources/channel#create-message // TODO: text channel slowdown // TODO: trim and replace message content and every embed field + // Send message -router.post("/", check(MessageCreateSchema), async (req, res) => { +router.post("/", check(MessageCreateSchema), messageUpload.single("file"), async (req, res) => { const { channel_id } = req.params; - const body = req.body as MessageCreateSchema; + var body = req.body as MessageCreateSchema; + const attachments: Attachment[] = []; + + if (req.file) { + try { + const file = await uploadFile(`/attachments/${channel_id}`, req.file); + attachments.push({ ...file, proxy_url: file.url }); + } catch (error) { + return res.status(400).json(error); + } + } + + if (body.payload_json) { + body = JSON.parse(body.payload_json); + const errors = instanceOf(MessageCreateSchema, body, { req }); + if (errors !== true) throw errors; + } const embeds = []; if (body.embed) embeds.push(body.embed); - const data = await sendMessage({ ...body, type: 0, pinned: false, author_id: req.user_id, embeds, channel_id }); + const data = await sendMessage({ ...body, type: 0, pinned: false, author_id: req.user_id, embeds, channel_id, attachments }); return res.send(data); }); diff --git a/src/schema/Message.ts b/src/schema/Message.ts index e6aa42b3..b2e4b1f7 100644 --- a/src/schema/Message.ts +++ b/src/schema/Message.ts @@ -68,4 +68,5 @@ export interface MessageCreateSchema { fail_if_not_exists: boolean; }; payload_json?: string; + file?: any; } diff --git a/src/util/Message.ts b/src/util/Message.ts index 27796997..9b928031 100644 --- a/src/util/Message.ts +++ b/src/util/Message.ts @@ -50,7 +50,7 @@ export async function handleMessage(opts: Partial) { mention_channels_ids: [], mention_role_ids: [], mention_user_ids: [], - attachments: [], // TODO: message attachments + attachments: opts.attachments || [], // TODO: message attachments embeds: opts.embeds || [], reactions: opts.reactions || [], type: opts.type ?? 0 diff --git a/src/util/cdn.ts b/src/util/cdn.ts new file mode 100644 index 00000000..a66e2215 --- /dev/null +++ b/src/util/cdn.ts @@ -0,0 +1,24 @@ +import { Config } from "@fosscord/server-util"; +import FormData from "form-data"; +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; +}