✨ 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", | ||||
| 			"license": "ISC", | ||||
| 			"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", | ||||
| @ -24,11 +24,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", | ||||
| @ -520,9 +521,9 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/@fosscord/server-util": { | ||||
| 			"version": "1.3.9", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.9.tgz", | ||||
| 			"integrity": "sha512-1oOcMMOBVJO3BodyKQaP3ukg9ok8qfCeIAHSCcloO02lAq45Y+EI7Y7i5a8dotYl7CP8Uv8ke9mGqI3Tojg0Fw==", | ||||
| 			"version": "1.3.10", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.10.tgz", | ||||
| 			"integrity": "sha512-pu+XAoerl/WLFxoNxT1NV7Nj0QT+QigK5ghr1VCXkN5N/pUAJUyC72fJPYk+5Ug0CbJkPb0XNsRVJpuz8k0R2g==", | ||||
| 			"dependencies": { | ||||
| 				"@types/jsonwebtoken": "^8.5.0", | ||||
| 				"@types/mongoose-autopopulate": "^0.10.1", | ||||
| @ -2123,8 +2124,7 @@ | ||||
| 		"node_modules/asynckit": { | ||||
| 			"version": "0.4.0", | ||||
| 			"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", | ||||
| 			"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", | ||||
| 			"dev": true | ||||
| 			"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" | ||||
| 		}, | ||||
| 		"node_modules/atob": { | ||||
| 			"version": "2.1.2", | ||||
| @ -3290,7 +3290,6 @@ | ||||
| 			"version": "1.0.8", | ||||
| 			"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", | ||||
| 			"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"delayed-stream": "~1.0.0" | ||||
| 			}, | ||||
| @ -3848,7 +3847,6 @@ | ||||
| 			"version": "1.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", | ||||
| 			"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", | ||||
| 			"dev": true, | ||||
| 			"engines": { | ||||
| 				"node": ">=0.4.0" | ||||
| 			} | ||||
| @ -4872,7 +4870,6 @@ | ||||
| 			"version": "3.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", | ||||
| 			"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"asynckit": "^0.4.0", | ||||
| 				"combined-stream": "^1.0.8", | ||||
| @ -7928,9 +7925,9 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/lambert-server": { | ||||
| 			"version": "1.2.2", | ||||
| 			"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.2.tgz", | ||||
| 			"integrity": "sha512-rsQlFQZDYl3+feM25WNdV8cUf6yS5SYyelCFV8ohF6pMLqQJfXcbvsEYzGeF1pIIkjnWehxTK2J9kJJpNWeWFg==", | ||||
| 			"version": "1.2.3", | ||||
| 			"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.3.tgz", | ||||
| 			"integrity": "sha512-tBcxVH5Hj6ts/hk11e5ABc1ihxH9aIrXJth/9ivkfeqWjZEEzGrxvEmtnPULwGGy+k6lvUoZw725LDgVxoYGKQ==", | ||||
| 			"dependencies": { | ||||
| 				"body-parser": "^1.19.0", | ||||
| 				"express": "^4.17.1", | ||||
| @ -12860,9 +12857,9 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"@fosscord/server-util": { | ||||
| 			"version": "1.3.9", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.9.tgz", | ||||
| 			"integrity": "sha512-1oOcMMOBVJO3BodyKQaP3ukg9ok8qfCeIAHSCcloO02lAq45Y+EI7Y7i5a8dotYl7CP8Uv8ke9mGqI3Tojg0Fw==", | ||||
| 			"version": "1.3.10", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.10.tgz", | ||||
| 			"integrity": "sha512-pu+XAoerl/WLFxoNxT1NV7Nj0QT+QigK5ghr1VCXkN5N/pUAJUyC72fJPYk+5Ug0CbJkPb0XNsRVJpuz8k0R2g==", | ||||
| 			"requires": { | ||||
| 				"@types/jsonwebtoken": "^8.5.0", | ||||
| 				"@types/mongoose-autopopulate": "^0.10.1", | ||||
| @ -14196,8 +14193,7 @@ | ||||
| 		"asynckit": { | ||||
| 			"version": "0.4.0", | ||||
| 			"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", | ||||
| 			"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", | ||||
| 			"dev": true | ||||
| 			"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" | ||||
| 		}, | ||||
| 		"atob": { | ||||
| 			"version": "2.1.2", | ||||
| @ -15195,7 +15191,6 @@ | ||||
| 			"version": "1.0.8", | ||||
| 			"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", | ||||
| 			"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", | ||||
| 			"dev": true, | ||||
| 			"requires": { | ||||
| 				"delayed-stream": "~1.0.0" | ||||
| 			} | ||||
| @ -15691,8 +15686,7 @@ | ||||
| 		"delayed-stream": { | ||||
| 			"version": "1.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", | ||||
| 			"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", | ||||
| 			"dev": true | ||||
| 			"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" | ||||
| 		}, | ||||
| 		"delegates": { | ||||
| 			"version": "1.0.0", | ||||
| @ -16533,7 +16527,6 @@ | ||||
| 			"version": "3.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", | ||||
| 			"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", | ||||
| 			"dev": true, | ||||
| 			"requires": { | ||||
| 				"asynckit": "^0.4.0", | ||||
| 				"combined-stream": "^1.0.8", | ||||
| @ -18981,9 +18974,9 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"lambert-server": { | ||||
| 			"version": "1.2.2", | ||||
| 			"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.2.tgz", | ||||
| 			"integrity": "sha512-rsQlFQZDYl3+feM25WNdV8cUf6yS5SYyelCFV8ohF6pMLqQJfXcbvsEYzGeF1pIIkjnWehxTK2J9kJJpNWeWFg==", | ||||
| 			"version": "1.2.3", | ||||
| 			"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.3.tgz", | ||||
| 			"integrity": "sha512-tBcxVH5Hj6ts/hk11e5ABc1ihxH9aIrXJth/9ivkfeqWjZEEzGrxvEmtnPULwGGy+k6lvUoZw725LDgVxoYGKQ==", | ||||
| 			"requires": { | ||||
| 				"body-parser": "^1.19.0", | ||||
| 				"express": "^4.17.1", | ||||
|  | ||||
| @ -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", | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
| }); | ||||
|  | ||||
| @ -68,4 +68,5 @@ export interface MessageCreateSchema { | ||||
| 		fail_if_not_exists: boolean; | ||||
| 	}; | ||||
| 	payload_json?: string; | ||||
| 	file?: any; | ||||
| } | ||||
|  | ||||
| @ -50,7 +50,7 @@ export async function handleMessage(opts: Partial<Message>) { | ||||
| 		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 | ||||
|  | ||||
							
								
								
									
										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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Flam3rboy
						Flam3rboy