diff options
author | Puyodead1 <puyodead@proton.me> | 2023-03-23 11:56:17 -0400 |
---|---|---|
committer | Puyodead1 <puyodead@proton.me> | 2023-04-13 15:04:56 -0400 |
commit | 4a7811a25ce78a108e9a42fcb6c86ac0ed6e09eb (patch) | |
tree | 538718dc98a4dea8c21a0a29ea219a7304e08eb3 /src/api/routes/channels/#channel_id | |
parent | applications (diff) | |
download | server-4a7811a25ce78a108e9a42fcb6c86ac0ed6e09eb.tar.xz |
channels
Diffstat (limited to 'src/api/routes/channels/#channel_id')
14 files changed, 537 insertions, 255 deletions
diff --git a/src/api/routes/channels/#channel_id/index.ts b/src/api/routes/channels/#channel_id/index.ts index db0d4242..74e21a02 100644 --- a/src/api/routes/channels/#channel_id/index.ts +++ b/src/api/routes/channels/#channel_id/index.ts @@ -16,18 +16,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +import { route } from "@spacebar/api"; import { Channel, ChannelDeleteEvent, + ChannelModifySchema, ChannelType, ChannelUpdateEvent, - emitEvent, Recipient, + emitEvent, handleFile, - ChannelModifySchema, } from "@spacebar/util"; import { Request, Response, Router } from "express"; -import { route } from "@spacebar/api"; const router: Router = Router(); // TODO: delete channel @@ -35,7 +35,15 @@ const router: Router = Router(); router.get( "/", - route({ permission: "VIEW_CHANNEL" }), + route({ + permission: "VIEW_CHANNEL", + responses: { + 200: { + body: "Channel", + }, + 404: {}, + }, + }), async (req: Request, res: Response) => { const { channel_id } = req.params; @@ -49,7 +57,15 @@ router.get( router.delete( "/", - route({ permission: "MANAGE_CHANNELS" }), + route({ + permission: "MANAGE_CHANNELS", + responses: { + 200: { + body: "Channel", + }, + 404: {}, + }, + }), async (req: Request, res: Response) => { const { channel_id } = req.params; @@ -90,7 +106,19 @@ router.delete( router.patch( "/", - route({ body: "ChannelModifySchema", permission: "MANAGE_CHANNELS" }), + route({ + body: "ChannelModifySchema", + permission: "MANAGE_CHANNELS", + responses: { + 200: { + body: "Channel", + }, + 404: {}, + 400: { + body: "APIErrorResponse", + }, + }, + }), async (req: Request, res: Response) => { const payload = req.body as ChannelModifySchema; const { channel_id } = req.params; diff --git a/src/api/routes/channels/#channel_id/invites.ts b/src/api/routes/channels/#channel_id/invites.ts index 9f247fe8..35cdbca8 100644 --- a/src/api/routes/channels/#channel_id/invites.ts +++ b/src/api/routes/channels/#channel_id/invites.ts @@ -16,19 +16,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { Router, Request, Response } from "express"; -import { HTTPError } from "lambert-server"; -import { route } from "@spacebar/api"; -import { random } from "@spacebar/api"; +import { random, route } from "@spacebar/api"; import { Channel, + Guild, Invite, InviteCreateEvent, - emitEvent, - User, - Guild, PublicInviteRelation, + User, + emitEvent, } from "@spacebar/util"; +import { Request, Response, Router } from "express"; +import { HTTPError } from "lambert-server"; import { isTextChannel } from "./messages"; const router: Router = Router(); @@ -39,6 +38,15 @@ router.post( body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE", right: "CREATE_INVITES", + responses: { + 201: { + body: "Invite", + }, + 404: {}, + 400: { + body: "APIErrorResponse", + }, + }, }), async (req: Request, res: Response) => { const { user_id } = req; @@ -84,7 +92,15 @@ router.post( router.get( "/", - route({ permission: "MANAGE_CHANNELS" }), + route({ + permission: "MANAGE_CHANNELS", + responses: { + 200: { + body: "ChannelInvitesResponse", + }, + 404: {}, + }, + }), async (req: Request, res: Response) => { const { channel_id } = req.params; const channel = await Channel.findOneOrFail({ diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts b/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts index f098fa8e..f11fdcb2 100644 --- a/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts +++ b/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts @@ -16,6 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +import { route } from "@spacebar/api"; import { emitEvent, getPermission, @@ -23,7 +24,6 @@ import { ReadState, } from "@spacebar/util"; import { Request, Response, Router } from "express"; -import { route } from "@spacebar/api"; const router = Router(); @@ -33,7 +33,13 @@ const router = Router(); router.post( "/", - route({ body: "MessageAcknowledgeSchema" }), + route({ + body: "MessageAcknowledgeSchema", + responses: { + 200: {}, + 403: {}, + }, + }), async (req: Request, res: Response) => { const { channel_id, message_id } = req.params; diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts b/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts index 909a459e..5ca645c0 100644 --- a/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts +++ b/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts @@ -16,14 +16,21 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { Router, Response, Request } from "express"; import { route } from "@spacebar/api"; +import { Request, Response, Router } from "express"; const router = Router(); router.post( "/", - route({ permission: "MANAGE_MESSAGES" }), + route({ + permission: "MANAGE_MESSAGES", + responses: { + 200: { + body: "Message", + }, + }, + }), (req: Request, res: Response) => { // TODO: res.json({ diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts index cd4b243e..77bc1e0e 100644 --- a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts +++ b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts @@ -19,24 +19,23 @@ import { Attachment, Channel, - emitEvent, - SpacebarApiErrors, - getPermission, - getRights, Message, MessageCreateEvent, + MessageCreateSchema, MessageDeleteEvent, + MessageEditSchema, MessageUpdateEvent, Snowflake, + SpacebarApiErrors, + emitEvent, + getPermission, + getRights, uploadFile, - MessageCreateSchema, - MessageEditSchema, } from "@spacebar/util"; -import { Router, Response, Request } from "express"; -import multer from "multer"; -import { route } from "@spacebar/api"; -import { handleMessage, postHandleMessage } from "@spacebar/api"; +import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; +import multer from "multer"; +import { handleMessage, postHandleMessage, route } from "../../../../../util"; const router = Router(); // TODO: message content/embed string length limit @@ -56,6 +55,16 @@ router.patch( body: "MessageEditSchema", permission: "SEND_MESSAGES", right: "SEND_MESSAGES", + responses: { + 200: { + body: "Message", + }, + 400: { + body: "APIErrorResponse", + }, + 403: {}, + 404: {}, + }, }), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; @@ -146,6 +155,16 @@ router.put( body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_BACKDATED_EVENTS", + responses: { + 200: { + body: "Message", + }, + 400: { + body: "APIErrorResponse", + }, + 403: {}, + 404: {}, + }, }), async (req: Request, res: Response) => { const { channel_id, message_id } = req.params; @@ -230,7 +249,19 @@ router.put( router.get( "/", - route({ permission: "VIEW_CHANNEL" }), + route({ + permission: "VIEW_CHANNEL", + responses: { + 200: { + body: "Message", + }, + 400: { + body: "APIErrorResponse", + }, + 403: {}, + 404: {}, + }, + }), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; @@ -252,38 +283,54 @@ router.get( }, ); -router.delete("/", route({}), async (req: Request, res: Response) => { - const { message_id, channel_id } = req.params; +router.delete( + "/", + route({ + responses: { + 204: {}, + 400: { + body: "APIErrorResponse", + }, + 404: {}, + }, + }), + async (req: Request, res: Response) => { + const { message_id, channel_id } = req.params; - const channel = await Channel.findOneOrFail({ where: { id: channel_id } }); - const message = await Message.findOneOrFail({ where: { id: message_id } }); + const channel = await Channel.findOneOrFail({ + where: { id: channel_id }, + }); + const message = await Message.findOneOrFail({ + where: { id: message_id }, + }); - const rights = await getRights(req.user_id); + const rights = await getRights(req.user_id); - if (message.author_id !== req.user_id) { - if (!rights.has("MANAGE_MESSAGES")) { - const permission = await getPermission( - req.user_id, - channel.guild_id, - channel_id, - ); - permission.hasThrow("MANAGE_MESSAGES"); - } - } else rights.hasThrow("SELF_DELETE_MESSAGES"); + if (message.author_id !== req.user_id) { + if (!rights.has("MANAGE_MESSAGES")) { + const permission = await getPermission( + req.user_id, + channel.guild_id, + channel_id, + ); + permission.hasThrow("MANAGE_MESSAGES"); + } + } else rights.hasThrow("SELF_DELETE_MESSAGES"); - await Message.delete({ id: message_id }); + await Message.delete({ id: message_id }); - await emitEvent({ - event: "MESSAGE_DELETE", - channel_id, - data: { - id: message_id, + await emitEvent({ + event: "MESSAGE_DELETE", channel_id, - guild_id: channel.guild_id, - }, - } as MessageDeleteEvent); + data: { + id: message_id, + channel_id, + guild_id: channel.guild_id, + }, + } as MessageDeleteEvent); - res.sendStatus(204); -}); + res.sendStatus(204); + }, +); export default router; diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts b/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts index cb66cd64..c6db772b 100644 --- a/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts +++ b/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts @@ -16,6 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +import { route } from "@spacebar/api"; import { Channel, emitEvent, @@ -32,8 +33,7 @@ import { PublicUserProjection, User, } from "@spacebar/util"; -import { route } from "@spacebar/api"; -import { Router, Response, Request } from "express"; +import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { In } from "typeorm"; @@ -57,7 +57,17 @@ function getEmoji(emoji: string): PartialEmoji { router.delete( "/", - route({ permission: "MANAGE_MESSAGES" }), + route({ + permission: "MANAGE_MESSAGES", + responses: { + 204: {}, + 400: { + body: "APIErrorResponse", + }, + 404: {}, + 403: {}, + }, + }), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; @@ -83,7 +93,17 @@ router.delete( router.delete( "/:emoji", - route({ permission: "MANAGE_MESSAGES" }), + route({ + permission: "MANAGE_MESSAGES", + responses: { + 204: {}, + 400: { + body: "APIErrorResponse", + }, + 404: {}, + 403: {}, + }, + }), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; const emoji = getEmoji(req.params.emoji); @@ -120,7 +140,19 @@ router.delete( router.get( "/:emoji", - route({ permission: "VIEW_CHANNEL" }), + route({ + permission: "VIEW_CHANNEL", + responses: { + 200: { + body: "UserPublic", + }, + 400: { + body: "APIErrorResponse", + }, + 404: {}, + 403: {}, + }, + }), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; const emoji = getEmoji(req.params.emoji); @@ -148,7 +180,18 @@ router.get( router.put( "/:emoji/:user_id", - route({ permission: "READ_MESSAGE_HISTORY", right: "SELF_ADD_REACTIONS" }), + route({ + permission: "READ_MESSAGE_HISTORY", + right: "SELF_ADD_REACTIONS", + responses: { + 204: {}, + 400: { + body: "APIErrorResponse", + }, + 404: {}, + 403: {}, + }, + }), async (req: Request, res: Response) => { const { message_id, channel_id, user_id } = req.params; if (user_id !== "@me") throw new HTTPError("Invalid user"); @@ -219,7 +262,16 @@ router.put( router.delete( "/:emoji/:user_id", - route({}), + route({ + responses: { + 204: {}, + 400: { + body: "APIErrorResponse", + }, + 404: {}, + 403: {}, + }, + }), async (req: Request, res: Response) => { let { user_id } = req.params; const { message_id, channel_id } = req.params; diff --git a/src/api/routes/channels/#channel_id/messages/bulk-delete.ts b/src/api/routes/channels/#channel_id/messages/bulk-delete.ts index 18476d5c..db1617e2 100644 --- a/src/api/routes/channels/#channel_id/messages/bulk-delete.ts +++ b/src/api/routes/channels/#channel_id/messages/bulk-delete.ts @@ -16,18 +16,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { Router, Response, Request } from "express"; +import { route } from "@spacebar/api"; import { Channel, Config, emitEvent, getPermission, getRights, - MessageDeleteBulkEvent, Message, + MessageDeleteBulkEvent, } from "@spacebar/util"; +import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; -import { route } from "@spacebar/api"; const router: Router = Router(); @@ -38,7 +38,17 @@ export default router; // https://discord.com/developers/docs/resources/channel#bulk-delete-messages router.post( "/", - route({ body: "BulkDeleteSchema" }), + route({ + body: "BulkDeleteSchema", + responses: { + 204: {}, + 400: { + body: "APIErrorResponse", + }, + 403: {}, + 404: {}, + }, + }), async (req: Request, res: Response) => { const { channel_id } = req.params; const channel = await Channel.findOneOrFail({ diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts index 7f0c9fb5..8e3c43d7 100644 --- a/src/api/routes/channels/#channel_id/messages/index.ts +++ b/src/api/routes/channels/#channel_id/messages/index.ts @@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { Router, Response, Request } from "express"; +import { handleMessage, postHandleMessage, route } from "@spacebar/api"; import { Attachment, Channel, @@ -26,19 +26,19 @@ import { emitEvent, FieldErrors, getPermission, + Member, Message, MessageCreateEvent, - Snowflake, - uploadFile, - Member, MessageCreateSchema, + Reaction, ReadState, Rights, - Reaction, + Snowflake, + uploadFile, User, } from "@spacebar/util"; +import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; -import { handleMessage, postHandleMessage, route } from "@spacebar/api"; import multer from "multer"; import { FindManyOptions, FindOperator, LessThan, MoreThan } from "typeorm"; import { URL } from "url"; @@ -73,108 +73,123 @@ export function isTextChannel(type: ChannelType): boolean { // https://discord.com/developers/docs/resources/channel#create-message // get messages -router.get("/", route({}), async (req: Request, res: Response) => { - const channel_id = req.params.channel_id; - const channel = await Channel.findOneOrFail({ - where: { id: channel_id }, - }); - if (!channel) throw new HTTPError("Channel not found", 404); - - isTextChannel(channel.type); - const around = req.query.around ? `${req.query.around}` : undefined; - const before = req.query.before ? `${req.query.before}` : undefined; - const after = req.query.after ? `${req.query.after}` : undefined; - const limit = Number(req.query.limit) || 50; - if (limit < 1 || limit > 100) - throw new HTTPError("limit must be between 1 and 100", 422); - - const halfLimit = Math.floor(limit / 2); - - const permissions = await getPermission( - req.user_id, - channel.guild_id, - channel_id, - ); - permissions.hasThrow("VIEW_CHANNEL"); - if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]); - - const query: FindManyOptions<Message> & { - where: { id?: FindOperator<string> | FindOperator<string>[] }; - } = { - order: { timestamp: "DESC" }, - take: limit, - where: { channel_id }, - relations: [ - "author", - "webhook", - "application", - "mentions", - "mention_roles", - "mention_channels", - "sticker_items", - "attachments", - ], - }; - - if (after) { - if (BigInt(after) > BigInt(Snowflake.generate())) - return res.status(422); - query.where.id = MoreThan(after); - } else if (before) { - if (BigInt(before) < BigInt(req.params.channel_id)) - return res.status(422); - query.where.id = LessThan(before); - } else if (around) { - query.where.id = [ - MoreThan((BigInt(around) - BigInt(halfLimit)).toString()), - LessThan((BigInt(around) + BigInt(halfLimit)).toString()), - ]; - - return res.json([]); // TODO: fix around - } +router.get( + "/", + route({ + responses: { + 200: { + body: "ChannelMessagesResponse", + }, + 400: { + body: "APIErrorResponse", + }, + 403: {}, + 404: {}, + }, + }), + async (req: Request, res: Response) => { + const channel_id = req.params.channel_id; + const channel = await Channel.findOneOrFail({ + where: { id: channel_id }, + }); + if (!channel) throw new HTTPError("Channel not found", 404); - const messages = await Message.find(query); - const endpoint = Config.get().cdn.endpointPublic; + isTextChannel(channel.type); + const around = req.query.around ? `${req.query.around}` : undefined; + const before = req.query.before ? `${req.query.before}` : undefined; + const after = req.query.after ? `${req.query.after}` : undefined; + const limit = Number(req.query.limit) || 50; + if (limit < 1 || limit > 100) + throw new HTTPError("limit must be between 1 and 100", 422); - return res.json( - messages.map((x: Partial<Message>) => { - (x.reactions || []).forEach((y: Partial<Reaction>) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore - if ((y.user_ids || []).includes(req.user_id)) y.me = true; - delete y.user_ids; - }); - if (!x.author) - x.author = User.create({ - id: "4", - discriminator: "0000", - username: "Spacebar Ghost", - public_flags: 0, + const halfLimit = Math.floor(limit / 2); + + const permissions = await getPermission( + req.user_id, + channel.guild_id, + channel_id, + ); + permissions.hasThrow("VIEW_CHANNEL"); + if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]); + + const query: FindManyOptions<Message> & { + where: { id?: FindOperator<string> | FindOperator<string>[] }; + } = { + order: { timestamp: "DESC" }, + take: limit, + where: { channel_id }, + relations: [ + "author", + "webhook", + "application", + "mentions", + "mention_roles", + "mention_channels", + "sticker_items", + "attachments", + ], + }; + + if (after) { + if (BigInt(after) > BigInt(Snowflake.generate())) + return res.status(422); + query.where.id = MoreThan(after); + } else if (before) { + if (BigInt(before) < BigInt(req.params.channel_id)) + return res.status(422); + query.where.id = LessThan(before); + } else if (around) { + query.where.id = [ + MoreThan((BigInt(around) - BigInt(halfLimit)).toString()), + LessThan((BigInt(around) + BigInt(halfLimit)).toString()), + ]; + + return res.json([]); // TODO: fix around + } + + const messages = await Message.find(query); + const endpoint = Config.get().cdn.endpointPublic; + + return res.json( + messages.map((x: Partial<Message>) => { + (x.reactions || []).forEach((y: Partial<Reaction>) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore + if ((y.user_ids || []).includes(req.user_id)) y.me = true; + delete y.user_ids; + }); + if (!x.author) + x.author = User.create({ + id: "4", + discriminator: "0000", + username: "Fosscord Ghost", + public_flags: 0, + }); + x.attachments?.forEach((y: Attachment) => { + // dynamically set attachment proxy_url in case the endpoint changed + const uri = y.proxy_url.startsWith("http") + ? y.proxy_url + : `https://example.org${y.proxy_url}`; + y.proxy_url = `${endpoint == null ? "" : endpoint}${ + new URL(uri).pathname + }`; }); - x.attachments?.forEach((y: Attachment) => { - // dynamically set attachment proxy_url in case the endpoint changed - const uri = y.proxy_url.startsWith("http") - ? y.proxy_url - : `https://example.org${y.proxy_url}`; - y.proxy_url = `${endpoint == null ? "" : endpoint}${ - new URL(uri).pathname - }`; - }); - /** + /** Some clients ( discord.js ) only check if a property exists within the response, which causes errors when, say, the `application` property is `null`. **/ - // for (var curr in x) { - // if (x[curr] === null) - // delete x[curr]; - // } + // for (var curr in x) { + // if (x[curr] === null) + // delete x[curr]; + // } - return x; - }), - ); -}); + return x; + }), + ); + }, +); // TODO: config max upload size const messageUpload = multer({ @@ -208,6 +223,16 @@ router.post( body: "MessageCreateSchema", permission: "SEND_MESSAGES", right: "SEND_MESSAGES", + responses: { + 200: { + body: "Message", + }, + 400: { + body: "APIErrorResponse", + }, + 403: {}, + 404: {}, + }, }), async (req: Request, res: Response) => { const { channel_id } = req.params; diff --git a/src/api/routes/channels/#channel_id/permissions.ts b/src/api/routes/channels/#channel_id/permissions.ts index 68dbc2f2..c6a9def6 100644 --- a/src/api/routes/channels/#channel_id/permissions.ts +++ b/src/api/routes/channels/#channel_id/permissions.ts @@ -19,13 +19,13 @@ import { Channel, ChannelPermissionOverwrite, + ChannelPermissionOverwriteSchema, ChannelUpdateEvent, emitEvent, Member, Role, - ChannelPermissionOverwriteSchema, } from "@spacebar/util"; -import { Router, Response, Request } from "express"; +import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { route } from "@spacebar/api"; @@ -38,6 +38,12 @@ router.put( route({ body: "ChannelPermissionOverwriteSchema", permission: "MANAGE_ROLES", + responses: { + 204: {}, + 404: {}, + 501: {}, + 400: { body: "APIErrorResponse" }, + }, }), async (req: Request, res: Response) => { const { channel_id, overwrite_id } = req.params; @@ -92,7 +98,7 @@ router.put( // TODO: check permission hierarchy router.delete( "/:overwrite_id", - route({ permission: "MANAGE_ROLES" }), + route({ permission: "MANAGE_ROLES", responses: { 204: {}, 404: {} } }), async (req: Request, res: Response) => { const { channel_id, overwrite_id } = req.params; diff --git a/src/api/routes/channels/#channel_id/pins.ts b/src/api/routes/channels/#channel_id/pins.ts index 32820916..7b379c30 100644 --- a/src/api/routes/channels/#channel_id/pins.ts +++ b/src/api/routes/channels/#channel_id/pins.ts @@ -16,23 +16,33 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +import { route } from "@spacebar/api"; import { Channel, ChannelPinsUpdateEvent, Config, + DiscordApiErrors, emitEvent, Message, MessageUpdateEvent, - DiscordApiErrors, } from "@spacebar/util"; -import { Router, Request, Response } from "express"; -import { route } from "@spacebar/api"; +import { Request, Response, Router } from "express"; const router: Router = Router(); router.put( "/:message_id", - route({ permission: "VIEW_CHANNEL" }), + route({ + permission: "VIEW_CHANNEL", + responses: { + 204: {}, + 403: {}, + 404: {}, + 400: { + body: "APIErrorResponse", + }, + }, + }), async (req: Request, res: Response) => { const { channel_id, message_id } = req.params; @@ -74,7 +84,17 @@ router.put( router.delete( "/:message_id", - route({ permission: "VIEW_CHANNEL" }), + route({ + permission: "VIEW_CHANNEL", + responses: { + 204: {}, + 403: {}, + 404: {}, + 400: { + body: "APIErrorResponse", + }, + }, + }), async (req: Request, res: Response) => { const { channel_id, message_id } = req.params; @@ -114,7 +134,17 @@ router.delete( router.get( "/", - route({ permission: ["READ_MESSAGE_HISTORY"] }), + route({ + permission: ["READ_MESSAGE_HISTORY"], + responses: { + 200: { + body: "ChannelPinsResponse", + }, + 400: { + body: "APIErrorResponse", + }, + }, + }), async (req: Request, res: Response) => { const { channel_id } = req.params; diff --git a/src/api/routes/channels/#channel_id/purge.ts b/src/api/routes/channels/#channel_id/purge.ts index c8da6760..cbd46bd0 100644 --- a/src/api/routes/channels/#channel_id/purge.ts +++ b/src/api/routes/channels/#channel_id/purge.ts @@ -16,20 +16,20 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { HTTPError } from "lambert-server"; import { route } from "@spacebar/api"; -import { isTextChannel } from "./messages"; -import { FindManyOptions, Between, Not, FindOperator } from "typeorm"; import { Channel, - emitEvent, - getPermission, - getRights, Message, MessageDeleteBulkEvent, PurgeSchema, + emitEvent, + getPermission, + getRights, } from "@spacebar/util"; -import { Router, Response, Request } from "express"; +import { Request, Response, Router } from "express"; +import { HTTPError } from "lambert-server"; +import { Between, FindManyOptions, FindOperator, Not } from "typeorm"; +import { isTextChannel } from "./messages"; const router: Router = Router(); @@ -42,6 +42,14 @@ router.post( "/", route({ /*body: "PurgeSchema",*/ + responses: { + 204: {}, + 400: { + body: "APIErrorResponse", + }, + 404: {}, + 403: {}, + }, }), async (req: Request, res: Response) => { const { channel_id } = req.params; diff --git a/src/api/routes/channels/#channel_id/recipients.ts b/src/api/routes/channels/#channel_id/recipients.ts index f1fb48af..569bb5cd 100644 --- a/src/api/routes/channels/#channel_id/recipients.ts +++ b/src/api/routes/channels/#channel_id/recipients.ts @@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { Request, Response, Router } from "express"; +import { route } from "@spacebar/api"; import { Channel, ChannelRecipientAddEvent, @@ -28,80 +28,98 @@ import { Recipient, User, } from "@spacebar/util"; -import { route } from "@spacebar/api"; +import { Request, Response, Router } from "express"; const router: Router = Router(); -router.put("/:user_id", route({}), async (req: Request, res: Response) => { - const { channel_id, user_id } = req.params; - const channel = await Channel.findOneOrFail({ - where: { id: channel_id }, - relations: ["recipients"], - }); +router.put( + "/:user_id", + route({ + responses: { + 201: {}, + 404: {}, + }, + }), + async (req: Request, res: Response) => { + const { channel_id, user_id } = req.params; + const channel = await Channel.findOneOrFail({ + where: { id: channel_id }, + relations: ["recipients"], + }); - if (channel.type !== ChannelType.GROUP_DM) { - const recipients = [ - ...(channel.recipients?.map((r) => r.user_id) || []), - user_id, - ].unique(); + if (channel.type !== ChannelType.GROUP_DM) { + const recipients = [ + ...(channel.recipients?.map((r) => r.user_id) || []), + user_id, + ].unique(); - const new_channel = await Channel.createDMChannel( - recipients, - req.user_id, - ); - return res.status(201).json(new_channel); - } else { - if (channel.recipients?.map((r) => r.user_id).includes(user_id)) { - throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error? - } + const new_channel = await Channel.createDMChannel( + recipients, + req.user_id, + ); + return res.status(201).json(new_channel); + } else { + if (channel.recipients?.map((r) => r.user_id).includes(user_id)) { + throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error? + } - channel.recipients?.push( - Recipient.create({ channel_id: channel_id, user_id: user_id }), - ); - await channel.save(); + channel.recipients?.push( + Recipient.create({ channel_id: channel_id, user_id: user_id }), + ); + await channel.save(); - await emitEvent({ - event: "CHANNEL_CREATE", - data: await DmChannelDTO.from(channel, [user_id]), - user_id: user_id, - }); + await emitEvent({ + event: "CHANNEL_CREATE", + data: await DmChannelDTO.from(channel, [user_id]), + user_id: user_id, + }); - await emitEvent({ - event: "CHANNEL_RECIPIENT_ADD", - data: { + await emitEvent({ + event: "CHANNEL_RECIPIENT_ADD", + data: { + channel_id: channel_id, + user: await User.findOneOrFail({ + where: { id: user_id }, + select: PublicUserProjection, + }), + }, channel_id: channel_id, - user: await User.findOneOrFail({ - where: { id: user_id }, - select: PublicUserProjection, - }), - }, - channel_id: channel_id, - } as ChannelRecipientAddEvent); - return res.sendStatus(204); - } -}); + } as ChannelRecipientAddEvent); + return res.sendStatus(204); + } + }, +); -router.delete("/:user_id", route({}), async (req: Request, res: Response) => { - const { channel_id, user_id } = req.params; - const channel = await Channel.findOneOrFail({ - where: { id: channel_id }, - relations: ["recipients"], - }); - if ( - !( - channel.type === ChannelType.GROUP_DM && - (channel.owner_id === req.user_id || user_id === req.user_id) +router.delete( + "/:user_id", + route({ + responses: { + 204: {}, + 404: {}, + }, + }), + async (req: Request, res: Response) => { + const { channel_id, user_id } = req.params; + const channel = await Channel.findOneOrFail({ + where: { id: channel_id }, + relations: ["recipients"], + }); + if ( + !( + channel.type === ChannelType.GROUP_DM && + (channel.owner_id === req.user_id || user_id === req.user_id) + ) ) - ) - throw DiscordApiErrors.MISSING_PERMISSIONS; + throw DiscordApiErrors.MISSING_PERMISSIONS; - if (!channel.recipients?.map((r) => r.user_id).includes(user_id)) { - throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error? - } + if (!channel.recipients?.map((r) => r.user_id).includes(user_id)) { + throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error? + } - await Channel.removeRecipientFromChannel(channel, user_id); + await Channel.removeRecipientFromChannel(channel, user_id); - return res.sendStatus(204); -}); + return res.sendStatus(204); + }, +); export default router; diff --git a/src/api/routes/channels/#channel_id/typing.ts b/src/api/routes/channels/#channel_id/typing.ts index 6a2fef39..b5d61d74 100644 --- a/src/api/routes/channels/#channel_id/typing.ts +++ b/src/api/routes/channels/#channel_id/typing.ts @@ -16,15 +16,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { Channel, emitEvent, Member, TypingStartEvent } from "@spacebar/util"; import { route } from "@spacebar/api"; -import { Router, Request, Response } from "express"; +import { Channel, emitEvent, Member, TypingStartEvent } from "@spacebar/util"; +import { Request, Response, Router } from "express"; const router: Router = Router(); router.post( "/", - route({ permission: "SEND_MESSAGES" }), + route({ + permission: "SEND_MESSAGES", + responses: { + 204: {}, + 404: {}, + 403: {}, + }, + }), async (req: Request, res: Response) => { const { channel_id } = req.params; const user_id = req.user_id; diff --git a/src/api/routes/channels/#channel_id/webhooks.ts b/src/api/routes/channels/#channel_id/webhooks.ts index 14791a1c..4e98a1c9 100644 --- a/src/api/routes/channels/#channel_id/webhooks.ts +++ b/src/api/routes/channels/#channel_id/webhooks.ts @@ -16,34 +16,56 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { Router, Response, Request } from "express"; import { route } from "@spacebar/api"; import { Channel, Config, - handleFile, - trimSpecial, + DiscordApiErrors, User, Webhook, WebhookCreateSchema, WebhookType, + handleFile, + trimSpecial, } from "@spacebar/util"; +import crypto from "crypto"; +import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { isTextChannel } from "./messages/index"; -import { DiscordApiErrors } from "@spacebar/util"; -import crypto from "crypto"; const router: Router = Router(); //TODO: implement webhooks -router.get("/", route({}), async (req: Request, res: Response) => { - res.json([]); -}); +router.get( + "/", + route({ + responses: { + 200: { + body: "ChannelWebhooksResponse", + }, + }, + }), + async (req: Request, res: Response) => { + res.json([]); + }, +); // TODO: use Image Data Type for avatar instead of String router.post( "/", - route({ body: "WebhookCreateSchema", permission: "MANAGE_WEBHOOKS" }), + route({ + body: "WebhookCreateSchema", + permission: "MANAGE_WEBHOOKS", + responses: { + 200: { + body: "WebhookCreateResponse", + }, + 400: { + body: "APIErrorResponse", + }, + 403: {}, + }, + }), async (req: Request, res: Response) => { const channel_id = req.params.channel_id; const channel = await Channel.findOneOrFail({ |