mirror of
https://github.com/spacebarchat/server.git
synced 2024-11-10 20:52:42 +01:00
✨ message attachments
This commit is contained in:
parent
b59d32f9bb
commit
d61bbe8293
43
package-lock.json
generated
43
package-lock.json
generated
@ -9,7 +9,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fosscord/server-util": "^1.3.9",
|
"@fosscord/server-util": "^1.3.10",
|
||||||
"@types/jest": "^26.0.22",
|
"@types/jest": "^26.0.22",
|
||||||
"@types/json-schema": "^7.0.7",
|
"@types/json-schema": "^7.0.7",
|
||||||
"ajv": "^8.4.0",
|
"ajv": "^8.4.0",
|
||||||
@ -24,11 +24,12 @@
|
|||||||
"env-paths": "^2.2.1",
|
"env-paths": "^2.2.1",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-validator": "^6.9.2",
|
"express-validator": "^6.9.2",
|
||||||
|
"form-data": "^3.0.0",
|
||||||
"i18next": "^19.8.5",
|
"i18next": "^19.8.5",
|
||||||
"i18next-http-middleware": "^3.1.3",
|
"i18next-http-middleware": "^3.1.3",
|
||||||
"i18next-node-fs-backend": "^2.1.3",
|
"i18next-node-fs-backend": "^2.1.3",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"lambert-server": "^1.2.2",
|
"lambert-server": "^1.2.3",
|
||||||
"missing-native-js-functions": "^1.2.6",
|
"missing-native-js-functions": "^1.2.6",
|
||||||
"mongodb": "^3.6.5",
|
"mongodb": "^3.6.5",
|
||||||
"mongoose": "^5.12.3",
|
"mongoose": "^5.12.3",
|
||||||
@ -520,9 +521,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@fosscord/server-util": {
|
"node_modules/@fosscord/server-util": {
|
||||||
"version": "1.3.9",
|
"version": "1.3.10",
|
||||||
"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.9.tgz",
|
"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.10.tgz",
|
||||||
"integrity": "sha512-1oOcMMOBVJO3BodyKQaP3ukg9ok8qfCeIAHSCcloO02lAq45Y+EI7Y7i5a8dotYl7CP8Uv8ke9mGqI3Tojg0Fw==",
|
"integrity": "sha512-pu+XAoerl/WLFxoNxT1NV7Nj0QT+QigK5ghr1VCXkN5N/pUAJUyC72fJPYk+5Ug0CbJkPb0XNsRVJpuz8k0R2g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/jsonwebtoken": "^8.5.0",
|
"@types/jsonwebtoken": "^8.5.0",
|
||||||
"@types/mongoose-autopopulate": "^0.10.1",
|
"@types/mongoose-autopopulate": "^0.10.1",
|
||||||
@ -2123,8 +2124,7 @@
|
|||||||
"node_modules/asynckit": {
|
"node_modules/asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/atob": {
|
"node_modules/atob": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@ -3290,7 +3290,6 @@
|
|||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"delayed-stream": "~1.0.0"
|
"delayed-stream": "~1.0.0"
|
||||||
},
|
},
|
||||||
@ -3848,7 +3847,6 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
@ -4872,7 +4870,6 @@
|
|||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
||||||
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
@ -7928,9 +7925,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lambert-server": {
|
"node_modules/lambert-server": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.3.tgz",
|
||||||
"integrity": "sha512-rsQlFQZDYl3+feM25WNdV8cUf6yS5SYyelCFV8ohF6pMLqQJfXcbvsEYzGeF1pIIkjnWehxTK2J9kJJpNWeWFg==",
|
"integrity": "sha512-tBcxVH5Hj6ts/hk11e5ABc1ihxH9aIrXJth/9ivkfeqWjZEEzGrxvEmtnPULwGGy+k6lvUoZw725LDgVxoYGKQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
@ -12860,9 +12857,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@fosscord/server-util": {
|
"@fosscord/server-util": {
|
||||||
"version": "1.3.9",
|
"version": "1.3.10",
|
||||||
"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.9.tgz",
|
"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.10.tgz",
|
||||||
"integrity": "sha512-1oOcMMOBVJO3BodyKQaP3ukg9ok8qfCeIAHSCcloO02lAq45Y+EI7Y7i5a8dotYl7CP8Uv8ke9mGqI3Tojg0Fw==",
|
"integrity": "sha512-pu+XAoerl/WLFxoNxT1NV7Nj0QT+QigK5ghr1VCXkN5N/pUAJUyC72fJPYk+5Ug0CbJkPb0XNsRVJpuz8k0R2g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/jsonwebtoken": "^8.5.0",
|
"@types/jsonwebtoken": "^8.5.0",
|
||||||
"@types/mongoose-autopopulate": "^0.10.1",
|
"@types/mongoose-autopopulate": "^0.10.1",
|
||||||
@ -14196,8 +14193,7 @@
|
|||||||
"asynckit": {
|
"asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"atob": {
|
"atob": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@ -15195,7 +15191,6 @@
|
|||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"delayed-stream": "~1.0.0"
|
"delayed-stream": "~1.0.0"
|
||||||
}
|
}
|
||||||
@ -15691,8 +15686,7 @@
|
|||||||
"delayed-stream": {
|
"delayed-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"delegates": {
|
"delegates": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@ -16533,7 +16527,6 @@
|
|||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
||||||
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
@ -18981,9 +18974,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lambert-server": {
|
"lambert-server": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.3.tgz",
|
||||||
"integrity": "sha512-rsQlFQZDYl3+feM25WNdV8cUf6yS5SYyelCFV8ohF6pMLqQJfXcbvsEYzGeF1pIIkjnWehxTK2J9kJJpNWeWFg==",
|
"integrity": "sha512-tBcxVH5Hj6ts/hk11e5ABc1ihxH9aIrXJth/9ivkfeqWjZEEzGrxvEmtnPULwGGy+k6lvUoZw725LDgVxoYGKQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/fosscord/fosscord-api#readme",
|
"homepage": "https://github.com/fosscord/fosscord-api#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fosscord/server-util": "^1.3.9",
|
"@fosscord/server-util": "^1.3.10",
|
||||||
"@types/jest": "^26.0.22",
|
"@types/jest": "^26.0.22",
|
||||||
"@types/json-schema": "^7.0.7",
|
"@types/json-schema": "^7.0.7",
|
||||||
"ajv": "^8.4.0",
|
"ajv": "^8.4.0",
|
||||||
@ -44,11 +44,12 @@
|
|||||||
"env-paths": "^2.2.1",
|
"env-paths": "^2.2.1",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-validator": "^6.9.2",
|
"express-validator": "^6.9.2",
|
||||||
|
"form-data": "^3.0.0",
|
||||||
"i18next": "^19.8.5",
|
"i18next": "^19.8.5",
|
||||||
"i18next-http-middleware": "^3.1.3",
|
"i18next-http-middleware": "^3.1.3",
|
||||||
"i18next-node-fs-backend": "^2.1.3",
|
"i18next-node-fs-backend": "^2.1.3",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"lambert-server": "^1.2.2",
|
"lambert-server": "^1.2.3",
|
||||||
"missing-native-js-functions": "^1.2.6",
|
"missing-native-js-functions": "^1.2.6",
|
||||||
"mongodb": "^3.6.5",
|
"mongodb": "^3.6.5",
|
||||||
"mongoose": "^5.12.3",
|
"mongoose": "^5.12.3",
|
||||||
|
@ -45,6 +45,8 @@ router.patch("/", check(MessageCreateSchema), async (req, res) => {
|
|||||||
return res.json(toObject(message));
|
return res.json(toObject(message));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: delete attachments in message
|
||||||
|
|
||||||
router.delete("/", async (req, res) => {
|
router.delete("/", async (req, res) => {
|
||||||
const { message_id, channel_id } = req.params;
|
const { message_id, channel_id } = req.params;
|
||||||
|
|
||||||
|
@ -1,24 +1,13 @@
|
|||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import {
|
import { Attachment, ChannelModel, ChannelType, getPermission, MessageDocument, MessageModel, toObject } from "@fosscord/server-util";
|
||||||
ChannelModel,
|
|
||||||
ChannelType,
|
|
||||||
getPermission,
|
|
||||||
Message,
|
|
||||||
MessageCreateEvent,
|
|
||||||
MessageDocument,
|
|
||||||
MessageModel,
|
|
||||||
Snowflake,
|
|
||||||
toObject
|
|
||||||
} from "@fosscord/server-util";
|
|
||||||
import { HTTPError } from "lambert-server";
|
import { HTTPError } from "lambert-server";
|
||||||
import { MessageCreateSchema } from "../../../../schema/Message";
|
import { MessageCreateSchema } from "../../../../schema/Message";
|
||||||
import { check, instanceOf, Length } from "../../../../util/instanceOf";
|
import { check, instanceOf, Length } from "../../../../util/instanceOf";
|
||||||
import { PublicUserProjection } from "../../../../util/User";
|
|
||||||
import multer from "multer";
|
import multer from "multer";
|
||||||
import { emitEvent } from "../../../../util/Event";
|
|
||||||
import { Query } from "mongoose";
|
import { Query } from "mongoose";
|
||||||
import { PublicMemberProjection } from "../../../../util/Member";
|
|
||||||
import { sendMessage } from "../../../../util/Message";
|
import { sendMessage } from "../../../../util/Message";
|
||||||
|
import { uploadFile } from "../../../../util/cdn";
|
||||||
|
|
||||||
const router: Router = Router();
|
const router: Router = Router();
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
@ -93,7 +82,14 @@ router.get("/", async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// TODO: config max upload size
|
// 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: dynamically change limit of MessageCreateSchema with config
|
||||||
// TODO: check: sum of all characters in an embed structure must not exceed 6000 characters
|
// 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
|
// https://discord.com/developers/docs/resources/channel#create-message
|
||||||
// TODO: text channel slowdown
|
// TODO: text channel slowdown
|
||||||
// TODO: trim and replace message content and every embed field
|
// TODO: trim and replace message content and every embed field
|
||||||
|
|
||||||
// Send message
|
// 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 { 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 = [];
|
const embeds = [];
|
||||||
if (body.embed) embeds.push(body.embed);
|
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);
|
return res.send(data);
|
||||||
});
|
});
|
||||||
|
@ -68,4 +68,5 @@ export interface MessageCreateSchema {
|
|||||||
fail_if_not_exists: boolean;
|
fail_if_not_exists: boolean;
|
||||||
};
|
};
|
||||||
payload_json?: string;
|
payload_json?: string;
|
||||||
|
file?: any;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ export async function handleMessage(opts: Partial<Message>) {
|
|||||||
mention_channels_ids: [],
|
mention_channels_ids: [],
|
||||||
mention_role_ids: [],
|
mention_role_ids: [],
|
||||||
mention_user_ids: [],
|
mention_user_ids: [],
|
||||||
attachments: [], // TODO: message attachments
|
attachments: opts.attachments || [], // TODO: message attachments
|
||||||
embeds: opts.embeds || [],
|
embeds: opts.embeds || [],
|
||||||
reactions: opts.reactions || [],
|
reactions: opts.reactions || [],
|
||||||
type: opts.type ?? 0
|
type: opts.type ?? 0
|
||||||
|
24
src/util/cdn.ts
Normal file
24
src/util/cdn.ts
Normal file
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user