diff --git a/api/assets/schemas.json b/api/assets/schemas.json
index c2149836..4f1ab9a8 100644
--- a/api/assets/schemas.json
+++ b/api/assets/schemas.json
@@ -2887,47 +2887,321 @@
},
"$schema": "http://json-schema.org/draft-07/schema#"
},
- "EmojiListResponse": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "animated": {
- "type": "boolean"
- },
- "available": {
- "type": "boolean"
- },
- "id": {
- "type": "string"
- },
- "managed": {
- "type": "boolean"
- },
- "name": {
- "type": "string"
- },
- "require_colons": {
- "type": "boolean"
- },
- "guild_id": {
+ "EmojiCreateSchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "image": {
+ "type": "string"
+ },
+ "require_colons": {
+ "type": [
+ "null",
+ "boolean"
+ ]
+ },
+ "roles": {
+ "type": "array",
+ "items": {
"type": "string"
- },
- "roles": {
- "type": "array",
- "items": {
+ }
+ }
+ },
+ "definitions": {
+ "ChannelPermissionOverwriteType": {
+ "enum": [
+ 0,
+ 1
+ ],
+ "type": "number"
+ },
+ "Embed": {
+ "type": "object",
+ "properties": {
+ "title": {
"type": "string"
+ },
+ "type": {
+ "enum": [
+ "article",
+ "gifv",
+ "image",
+ "link",
+ "rich",
+ "video"
+ ],
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ },
+ "timestamp": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "color": {
+ "type": "integer"
+ },
+ "footer": {
+ "type": "object",
+ "properties": {
+ "text": {
+ "type": "string"
+ },
+ "icon_url": {
+ "type": "string"
+ },
+ "proxy_icon_url": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "text"
+ ]
+ },
+ "image": {
+ "$ref": "#/definitions/EmbedImage"
+ },
+ "thumbnail": {
+ "$ref": "#/definitions/EmbedImage"
+ },
+ "video": {
+ "$ref": "#/definitions/EmbedImage"
+ },
+ "provider": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ }
+ }
+ },
+ "author": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ },
+ "icon_url": {
+ "type": "string"
+ },
+ "proxy_icon_url": {
+ "type": "string"
+ }
+ }
+ },
+ "fields": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ },
+ "inline": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "name",
+ "value"
+ ]
+ }
}
}
},
- "required": [
- "animated",
- "available",
- "id",
- "managed",
- "name",
- "require_colons"
- ]
+ "EmbedImage": {
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string"
+ },
+ "proxy_url": {
+ "type": "string"
+ },
+ "height": {
+ "type": "integer"
+ },
+ "width": {
+ "type": "integer"
+ }
+ }
+ },
+ "ChannelModifySchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "maxLength": 100,
+ "type": "string"
+ },
+ "type": {
+ "enum": [
+ 0,
+ 1,
+ 10,
+ 11,
+ 12,
+ 13,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6
+ ],
+ "type": "number"
+ },
+ "topic": {
+ "type": "string"
+ },
+ "icon": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "bitrate": {
+ "type": "integer"
+ },
+ "user_limit": {
+ "type": "integer"
+ },
+ "rate_limit_per_user": {
+ "type": "integer"
+ },
+ "position": {
+ "type": "integer"
+ },
+ "permission_overwrites": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "type": {
+ "$ref": "#/definitions/ChannelPermissionOverwriteType"
+ },
+ "allow": {
+ "type": "string"
+ },
+ "deny": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "allow",
+ "deny",
+ "id",
+ "type"
+ ]
+ }
+ },
+ "parent_id": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string"
+ },
+ "nsfw": {
+ "type": "boolean"
+ },
+ "rtc_region": {
+ "type": "string"
+ },
+ "default_auto_archive_duration": {
+ "type": "integer"
+ }
+ }
+ },
+ "UserPublic": {
+ "type": "object",
+ "properties": {
+ "username": {
+ "type": "string"
+ },
+ "discriminator": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string"
+ },
+ "public_flags": {
+ "type": "integer"
+ },
+ "avatar": {
+ "type": "string"
+ },
+ "accent_color": {
+ "type": "integer"
+ },
+ "banner": {
+ "type": "string"
+ },
+ "bio": {
+ "type": "string"
+ },
+ "bot": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "bio",
+ "bot",
+ "discriminator",
+ "id",
+ "public_flags",
+ "username"
+ ]
+ },
+ "PublicConnectedAccount": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "verifie": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "name",
+ "type",
+ "verifie"
+ ]
+ }
+ },
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ },
+ "EmojiModifySchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "roles": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
},
"definitions": {
"ChannelPermissionOverwriteType": {
diff --git a/api/src/routes/guilds/#guild_id/emoji.ts b/api/src/routes/guilds/#guild_id/emoji.ts
deleted file mode 100644
index 000c9949..00000000
--- a/api/src/routes/guilds/#guild_id/emoji.ts
+++ /dev/null
@@ -1,137 +0,0 @@
-import { Router, Request, Response } from "express";
-import {
- Config,
- DiscordApiErrors,
- emitEvent,
- Emoji,
- GuildEmojiUpdateEvent,
- handleFile,
- Member,
- Snowflake,
- User
-} from "@fosscord/util";
-import { route } from "@fosscord/api";
-
-const router = Router();
-
-export interface EmojiCreateSchema {
- name?: string;
- image?: string;
- require_colons?: boolean | null;
- roles?: string[];
-}
-
-export interface EmojiModifySchema {
- name?: string;
- roles?: string[];
-}
-
-router.get("/", route({}), async (req: Request, res: Response) => {
- const guild_id = req.params.guild_id;
-
- await Member.IsInGuildOrFail(req.user_id, guild_id);
-
- const emojis = await Emoji.find({ guild_id: guild_id });
-
- return res.json(emojis);
-});
-
-router.get("/:emoji_id", route({}), async (req: Request, res: Response) => {
- const guild_id = req.params.guild_id;
- const emoji_id = req.params.emoji_id;
-
- await Member.IsInGuildOrFail(req.user_id, guild_id);
-
- const emoji = await Emoji.findOneOrFail({ guild_id: guild_id, id: emoji_id });
-
- return res.json(emoji);
-});
-
-router.post("/", route({ body: "EmojiCreateSchema", permission: "MANAGE_EMOJIS_AND_STICKERS" }), async (req: Request, res: Response) => {
- const guild_id = req.params.guild_id;
- const body = req.body as EmojiCreateSchema;
-
- const emoji_count = await Emoji.count({ guild_id: guild_id });
- const { maxEmojis } = Config.get().limits.guild;
-
- if (emoji_count >= maxEmojis) throw DiscordApiErrors.MAXIMUM_NUMBER_OF_EMOJIS_REACHED.withParams(maxEmojis);
-
- const id = Snowflake.generate();
-
- if (!body.image) {
- throw DiscordApiErrors.GENERAL_ERROR.withParams("No image provided");
- }
-
- if (body.require_colons === null) body.require_colons = true;
-
- const user = await User.findOneOrFail({ id: req.user_id });
-
- body.image = await handleFile(`/emojis/${id}`, body.image);
-
- const emoji = new Emoji({
- id: id,
- guild_id: guild_id,
- ...body,
- user: user,
- managed: false,
- animated: false, // TODO: Add support animated emojis
- available: true
- });
-
- await Promise.all([
- emoji.save(),
- emitEvent({
- event: "GUILD_EMOJI_UPDATE",
- guild_id: guild_id,
- data: {
- guild_id: guild_id,
- emojis: await Emoji.find({ guild_id: guild_id })
- }
- } as GuildEmojiUpdateEvent)
- ]);
-});
-
-router.patch("/:emoji_id", route({ body: "EmojiModifySchema", permission: "MANAGE_EMOJIS_AND_STICKERS" }), async (req: Request, res: Response) => {
- const { emoji_id, guild_id } = req.params;
- const body = req.body as EmojiModifySchema;
-
- const emoji = new Emoji({ ...body, id: emoji_id, guild_id: guild_id });
-
- await Promise.all([
- emoji.save(),
- emitEvent({
- event: "GUILD_EMOJI_UPDATE",
- guild_id: guild_id,
- data: {
- guild_id: guild_id,
- emojis: await Emoji.find({ guild_id: guild_id })
- }
- } as GuildEmojiUpdateEvent)
- ]);
-
- return res.json(emoji);
-});
-
-router.delete("/:emoji_id", route({ permission: "MANAGE_EMOJIS_AND_STICKERS" }), async (req: Request, res: Response) => {
- const guild_id = req.params.guild_id;
- const { emoji_id } = req.params;
-
- await Promise.all([
- Emoji.delete({
- id: emoji_id,
- guild_id: guild_id
- }),
- emitEvent({
- event: "GUILD_EMOJI_UPDATE",
- guild_id: guild_id,
- data: {
- guild_id: guild_id,
- emojis: await Emoji.find({ guild_id: guild_id })
- }
- } as GuildEmojiUpdateEvent)
- ])
-
- res.sendStatus(204);
-});
-
-export default router;
diff --git a/api/src/routes/guilds/#guild_id/emojis.ts b/api/src/routes/guilds/#guild_id/emojis.ts
new file mode 100644
index 00000000..ff565cd4
--- /dev/null
+++ b/api/src/routes/guilds/#guild_id/emojis.ts
@@ -0,0 +1,121 @@
+import { Router, Request, Response } from "express";
+import { Config, DiscordApiErrors, emitEvent, Emoji, GuildEmojisUpdateEvent, handleFile, Member, Snowflake, User } from "@fosscord/util";
+import { route } from "@fosscord/api";
+
+const router = Router();
+
+export interface EmojiCreateSchema {
+ name?: string;
+ image: string;
+ require_colons?: boolean | null;
+ roles?: string[];
+}
+
+export interface EmojiModifySchema {
+ name?: string;
+ roles?: string[];
+}
+
+router.get("/", route({}), async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
+
+ const emojis = await Emoji.find({ where: { guild_id: guild_id }, relations: ["user"] });
+
+ return res.json(emojis);
+});
+
+router.get("/:emoji_id", route({}), async (req: Request, res: Response) => {
+ const { guild_id, emoji_id } = req.params;
+
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
+
+ const emoji = await Emoji.findOneOrFail({ where: { guild_id: guild_id, id: emoji_id }, relations: ["user"] });
+
+ return res.json(emoji);
+});
+
+router.post("/", route({ body: "EmojiCreateSchema", permission: "MANAGE_EMOJIS_AND_STICKERS" }), async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const body = req.body as EmojiCreateSchema;
+
+ const emoji_count = await Emoji.count({ guild_id: guild_id });
+ const { maxEmojis } = Config.get().limits.guild;
+
+ if (emoji_count >= maxEmojis) throw DiscordApiErrors.MAXIMUM_NUMBER_OF_EMOJIS_REACHED.withParams(maxEmojis);
+
+ const id = Snowflake.generate();
+
+ if (body.require_colons == null) body.require_colons = true;
+
+ const user = await User.findOneOrFail({ id: req.user_id });
+
+ body.image = (await handleFile(`/emojis/${id}`, body.image)) as string;
+
+ const emoji = await new Emoji({
+ id: id,
+ guild_id: guild_id,
+ ...body,
+ user: user,
+ managed: false,
+ animated: false, // TODO: Add support animated emojis
+ available: true,
+ roles: []
+ }).save();
+
+ await emitEvent({
+ event: "GUILD_EMOJIS_UPDATE",
+ guild_id: guild_id,
+ data: {
+ guild_id: guild_id,
+ emojis: await Emoji.find({ guild_id: guild_id })
+ }
+ } as GuildEmojisUpdateEvent);
+
+ return res.status(201).json(emoji);
+});
+
+router.patch(
+ "/:emoji_id",
+ route({ body: "EmojiModifySchema", permission: "MANAGE_EMOJIS_AND_STICKERS" }),
+ async (req: Request, res: Response) => {
+ const { emoji_id, guild_id } = req.params;
+ const body = req.body as EmojiModifySchema;
+
+ const emoji = await new Emoji({ ...body, id: emoji_id, guild_id: guild_id }).save();
+
+ await emitEvent({
+ event: "GUILD_EMOJIS_UPDATE",
+ guild_id: guild_id,
+ data: {
+ guild_id: guild_id,
+ emojis: await Emoji.find({ guild_id: guild_id })
+ }
+ } as GuildEmojisUpdateEvent);
+
+ return res.json(emoji);
+ }
+);
+
+router.delete("/:emoji_id", route({ permission: "MANAGE_EMOJIS_AND_STICKERS" }), async (req: Request, res: Response) => {
+ const { emoji_id, guild_id } = req.params;
+
+ await Emoji.delete({
+ id: emoji_id,
+ guild_id: guild_id
+ });
+
+ await emitEvent({
+ event: "GUILD_EMOJIS_UPDATE",
+ guild_id: guild_id,
+ data: {
+ guild_id: guild_id,
+ emojis: await Emoji.find({ guild_id: guild_id })
+ }
+ } as GuildEmojisUpdateEvent);
+
+ res.sendStatus(204);
+});
+
+export default router;
|