summary refs log tree commit diff
path: root/api/src
diff options
context:
space:
mode:
Diffstat (limited to 'api/src')
-rw-r--r--api/src/routes/channels/#channel_id/invites.ts2
-rw-r--r--api/src/routes/channels/#channel_id/messages/#message_id/index.ts7
-rw-r--r--api/src/routes/channels/#channel_id/messages/index.ts1
-rw-r--r--api/src/routes/guilds/#guild_id/index.ts10
-rw-r--r--api/src/routes/guilds/index.ts2
-rw-r--r--api/src/routes/invites/index.ts17
-rw-r--r--api/src/routes/store/applications.ts11
-rw-r--r--api/src/routes/store/skus.ts11
-rw-r--r--api/src/routes/users/@me/index.ts14
-rw-r--r--api/src/util/Attachments.ts12
-rw-r--r--api/src/util/cdn.ts13
11 files changed, 85 insertions, 15 deletions
diff --git a/api/src/routes/channels/#channel_id/invites.ts b/api/src/routes/channels/#channel_id/invites.ts
index 2edb4fc2..71612e31 100644
--- a/api/src/routes/channels/#channel_id/invites.ts
+++ b/api/src/routes/channels/#channel_id/invites.ts
@@ -8,7 +8,7 @@ import { isTextChannel } from "./messages";
 const router: Router = Router();
 
 export interface InviteCreateSchema {
-	target_user_id?: string;
+	target_user_id?: string | null;
 	target_type?: string | null;
 	validate?: string | null; // ? what is this
 	max_age?: number;
diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts
index d0f780db..b5220fab 100644
--- a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts
+++ b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts
@@ -3,6 +3,7 @@ import { Router, Response, Request } from "express";
 import { route } from "@fosscord/api";
 import { handleMessage, postHandleMessage } from "@fosscord/api";
 import { MessageCreateSchema } from "../index";
+import { deleteMessageAttachments } from "@fosscord/api/util/Attachments";
 
 const router = Router();
 // TODO: message content/embed string length limit
@@ -11,7 +12,7 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE
 	const { message_id, channel_id } = req.params;
 	var body = req.body as MessageCreateSchema;
 
-	const message = await Message.findOneOrFail({ id: message_id, channel_id });
+	const message = await Message.findOneOrFail({ where: { id: message_id, channel_id }, relations: ["attachments"] });
 
 	const permissions = await getPermission(req.user_id, undefined, channel_id);
 
@@ -33,6 +34,7 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE
 	});
 
 	await Promise.all([
+		await deleteMessageAttachments(message_id, new_message.attachments), //This delete all the attachments not in the array
 		new_message!.save(),
 		await emitEvent({
 			event: "MESSAGE_UPDATE",
@@ -46,8 +48,6 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE
 	return res.json(message);
 });
 
-// TODO: delete attachments in message
-
 // permission check only if deletes messagr from other user
 router.delete("/", route({}), async (req: Request, res: Response) => {
 	const { message_id, channel_id } = req.params;
@@ -60,6 +60,7 @@ router.delete("/", route({}), async (req: Request, res: Response) => {
 		permission.hasThrow("MANAGE_MESSAGES");
 	}
 
+	await deleteMessageAttachments(message_id);
 	await Message.delete({ id: message_id });
 
 	await emitEvent({
diff --git a/api/src/routes/channels/#channel_id/messages/index.ts b/api/src/routes/channels/#channel_id/messages/index.ts
index be9a41b1..ec93649e 100644
--- a/api/src/routes/channels/#channel_id/messages/index.ts
+++ b/api/src/routes/channels/#channel_id/messages/index.ts
@@ -51,6 +51,7 @@ export interface MessageCreateSchema {
 	};
 	payload_json?: string;
 	file?: any;
+	attachments?: any[]; //TODO we should create an interface for attachments
 }
 
 // https://discord.com/developers/docs/resources/channel#create-message
diff --git a/api/src/routes/guilds/#guild_id/index.ts b/api/src/routes/guilds/#guild_id/index.ts
index a75d1138..7e4bf28a 100644
--- a/api/src/routes/guilds/#guild_id/index.ts
+++ b/api/src/routes/guilds/#guild_id/index.ts
@@ -9,17 +9,17 @@ import { GuildCreateSchema } from "../index";
 const router = Router();
 
 export interface GuildUpdateSchema extends Omit<GuildCreateSchema, "channels"> {
-	banner?: string;
-	splash?: string;
-	description?: string;
+	banner?: string | null;
+	splash?: string | null;
+	description?: string | null;
 	features?: string[];
 	verification_level?: number;
 	default_message_notifications?: number;
 	system_channel_flags?: number;
 	explicit_content_filter?: number;
-	public_updates_channel_id?: string;
+	public_updates_channel_id?: string | null;
 	afk_timeout?: number;
-	afk_channel_id?: string;
+	afk_channel_id?: string | null;
 	preferred_locale?: string;
 }
 
diff --git a/api/src/routes/guilds/index.ts b/api/src/routes/guilds/index.ts
index 082f8539..2334bb9c 100644
--- a/api/src/routes/guilds/index.ts
+++ b/api/src/routes/guilds/index.ts
@@ -15,7 +15,7 @@ export interface GuildCreateSchema {
 	icon?: string;
 	channels?: ChannelModifySchema[];
 	guild_template_code?: string;
-	system_channel_id?: string;
+	system_channel_id?: string | null;
 	rules_channel_id?: string;
 }
 
diff --git a/api/src/routes/invites/index.ts b/api/src/routes/invites/index.ts
index 6e77a853..ae8a5944 100644
--- a/api/src/routes/invites/index.ts
+++ b/api/src/routes/invites/index.ts
@@ -1,7 +1,8 @@
 import { Router, Request, Response } from "express";
-import { getPermission, Guild, Invite, Member, PublicInviteRelation } from "@fosscord/util";
+import { emitEvent, getPermission, Guild, Invite, InviteDeleteEvent, Member, PublicInviteRelation } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import { HTTPError } from "lambert-server";
+
 const router: Router = Router();
 
 router.get("/:code", route({}), async (req: Request, res: Response) => {
@@ -35,7 +36,19 @@ router.delete("/:code", route({}), async (req: Request, res: Response) => {
 	if (!permission.has("MANAGE_GUILD") && !permission.has("MANAGE_CHANNELS"))
 		throw new HTTPError("You missing the MANAGE_GUILD or MANAGE_CHANNELS permission", 401);
 
-	await Promise.all([Invite.delete({ code }), Guild.update({ vanity_url_code: code }, { vanity_url_code: undefined })]);
+	await Promise.all([
+		Invite.delete({ code }),
+		Guild.update({ vanity_url_code: code }, { vanity_url_code: undefined }),
+		emitEvent({
+			event: "INVITE_DELETE",
+			guild_id: guild_id,
+			data: {
+				channel_id: channel_id,
+				guild_id: guild_id,
+				code: code
+			}
+		} as InviteDeleteEvent)
+	]);
 
 	res.json({ invite: invite });
 });
diff --git a/api/src/routes/store/applications.ts b/api/src/routes/store/applications.ts
new file mode 100644
index 00000000..69cd716d
--- /dev/null
+++ b/api/src/routes/store/applications.ts
@@ -0,0 +1,11 @@
+import { Request, Response, Router } from "express";
+
+const router: Router = Router();
+
+router.get("/applications/:id", async (req: Request, res: Response) => {
+	//TODO 
+    const { id } = req.params;
+	res.json([]).status(200);
+});
+
+export default router;
\ No newline at end of file
diff --git a/api/src/routes/store/skus.ts b/api/src/routes/store/skus.ts
new file mode 100644
index 00000000..5c37850d
--- /dev/null
+++ b/api/src/routes/store/skus.ts
@@ -0,0 +1,11 @@
+import { Request, Response, Router } from "express";
+
+const router: Router = Router();
+
+router.get("/skus/:id", async (req: Request, res: Response) => {
+	//TODO
+    const { id } = req.params;
+	res.json([]).status(200);
+});
+
+export default router;
\ No newline at end of file
diff --git a/api/src/routes/users/@me/index.ts b/api/src/routes/users/@me/index.ts
index abab9f5f..c0002d79 100644
--- a/api/src/routes/users/@me/index.ts
+++ b/api/src/routes/users/@me/index.ts
@@ -1,5 +1,5 @@
 import { Router, Request, Response } from "express";
-import { User, PrivateUserProjection } from "@fosscord/util";
+import { User, PrivateUserProjection, emitEvent, UserUpdateEvent } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import { handleFile } from "@fosscord/api";
 
@@ -33,8 +33,16 @@ router.patch("/", route({ body: "UserModifySchema" }), async (req: Request, res:
 	if (body.avatar) body.avatar = await handleFile(`/avatars/${req.user_id}`, body.avatar as string);
 	if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string);
 
-	const user = await new User({ ...body, id: req.user_id }).save();
-	// TODO: dispatch user update event
+	await new User({ ...body, id: req.user_id }).save();
+
+	//Need to reload user from db due to https://github.com/typeorm/typeorm/issues/3490
+	const user = await User.findOneOrFail({ where: { id: req.user_id }, select: PrivateUserProjection });
+	// TODO: send update member list event in gateway
+	await emitEvent({
+		event: "USER_UPDATE",
+		user_id: req.user_id,
+		data: user
+	} as UserUpdateEvent);
 
 	res.json(user);
 });
diff --git a/api/src/util/Attachments.ts b/api/src/util/Attachments.ts
new file mode 100644
index 00000000..addda97f
--- /dev/null
+++ b/api/src/util/Attachments.ts
@@ -0,0 +1,12 @@
+import { Attachment } from "@fosscord/util";
+import { deleteFile } from "@fosscord/api";
+import { URL } from "url";
+
+export async function deleteMessageAttachments(messageId: string, keep?: Attachment[]) {
+	let attachments = await Attachment.find({ message_id: messageId });
+	if (keep)
+		attachments = attachments.filter(x => !keep.map(k => k.id).includes(x.id));
+	await Promise.all(attachments.map(a => a.remove()));
+
+	attachments.forEach(a => deleteFile((new URL(a.url)).pathname)); //We don't need to await since this is done on the cdn
+}
diff --git a/api/src/util/cdn.ts b/api/src/util/cdn.ts
index 3c71d980..88b0ea0d 100644
--- a/api/src/util/cdn.ts
+++ b/api/src/util/cdn.ts
@@ -38,3 +38,16 @@ export async function handleFile(path: string, body?: string): Promise<string |
 		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;
+}