summary refs log tree commit diff
path: root/src/api
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2026-11-01 22:11:49 +0100
committerRory& <root@rory.gay>2026-11-01 22:11:49 +0100
commit0cd981e500f32636021b4f57461efcecede31765 (patch)
treecb09ed5cf933092755b9b6997ca97f1b1a60f34e /src/api
parentDe-flake gatewy related tests a bit (diff)
downloadserver-ts-0cd981e500f32636021b4f57461efcecede31765.tar.xz
Resolve some TODOs
Diffstat (limited to 'src/api')
-rw-r--r--src/api/middlewares/CORS.ts2
-rw-r--r--src/api/routes/applications/#application_id/commands/#command_id/index.ts7
-rw-r--r--src/api/routes/applications/#application_id/commands/index.ts12
-rw-r--r--src/api/routes/applications/#application_id/guilds/#guild_id/commands/#command_id/index.ts7
-rw-r--r--src/api/routes/applications/#application_id/guilds/#guild_id/commands/index.ts12
-rw-r--r--src/api/routes/beaker.ts1
-rw-r--r--src/api/routes/channels/#channel_id/invites.ts19
-rw-r--r--src/api/routes/channels/#channel_id/messages/index.ts3
-rw-r--r--src/api/routes/channels/#channel_id/post-data.ts18
-rw-r--r--src/api/routes/channels/#channel_id/thread-members.ts22
-rw-r--r--src/api/routes/guilds/#guild_id/application-command-index.ts5
-rw-r--r--src/api/routes/guilds/#guild_id/bans.ts1
-rw-r--r--src/api/routes/guilds/#guild_id/index.ts1
-rw-r--r--src/api/routes/guilds/#guild_id/regions.ts1
-rw-r--r--src/api/routes/guilds/index.ts2
-rw-r--r--src/api/routes/read-states/ack-bulk.ts2
-rw-r--r--src/api/routes/science.ts1
-rw-r--r--src/api/routes/teams.ts2
-rw-r--r--src/api/routes/users/@me/billing/payment-sources.ts75
-rw-r--r--src/api/routes/users/@me/delete.ts2
-rw-r--r--src/api/routes/users/@me/guilds/#guild_id/settings.ts8
-rw-r--r--src/api/routes/users/@me/index.ts1
-rw-r--r--src/api/routes/users/@me/mfa/totp/enable.ts3
-rw-r--r--src/api/util/handlers/Message.ts15
24 files changed, 118 insertions, 104 deletions
diff --git a/src/api/middlewares/CORS.ts b/src/api/middlewares/CORS.ts

index 6cb2b1d8c..c4aa9cc08 100644 --- a/src/api/middlewares/CORS.ts +++ b/src/api/middlewares/CORS.ts
@@ -18,8 +18,6 @@ import { NextFunction, Request, Response } from "express"; -// TODO: config settings - export function CORS(req: Request, res: Response, next: NextFunction) { res.set("Access-Control-Allow-Credentials", "true"); res.set("Access-Control-Allow-Headers", req.header("Access-Control-Request-Headers") || "*"); diff --git a/src/api/routes/applications/#application_id/commands/#command_id/index.ts b/src/api/routes/applications/#application_id/commands/#command_id/index.ts
index 6fc4e28ed..3e4df62ff 100644 --- a/src/api/routes/applications/#application_id/commands/#command_id/index.ts +++ b/src/api/routes/applications/#application_id/commands/#command_id/index.ts
@@ -19,7 +19,7 @@ import { Request, Response, Router } from "express"; import { route } from "@spacebar/api/middlewares"; import { Application, ApplicationCommand } from "@spacebar/database"; -import { FieldErrors, Snowflake } from "@spacebar/util"; +import { Config, FieldErrors, Snowflake } from "@spacebar/util"; import { ApplicationCommandCreateSchema, ApplicationCommandSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -68,12 +68,11 @@ router.patch( body.type = 1; } - if (body.name.trim().length < 1 || body.name.trim().length > 32) { - // TODO: configurable? + if (body.name.trim().length < 1 || body.name.trim().length > Config.get().limits.application.commandLimits.maxNameLength) { throw FieldErrors({ name: { code: "BASE_TYPE_BAD_LENGTH", - message: `Must be between 1 and 32 in length.`, + message: `Must be between 1 and ${Config.get().limits.application.commandLimits.maxNameLength} in length.`, }, }); } diff --git a/src/api/routes/applications/#application_id/commands/index.ts b/src/api/routes/applications/#application_id/commands/index.ts
index 4891a180f..538ea7ea8 100644 --- a/src/api/routes/applications/#application_id/commands/index.ts +++ b/src/api/routes/applications/#application_id/commands/index.ts
@@ -21,7 +21,7 @@ import { IsNull } from "typeorm"; import { ApplicationCommandCreateSchema, ApplicationCommandSchema } from "@spacebar/schemas"; import { route } from "@spacebar/api/middlewares"; import { Application, ApplicationCommand } from "@spacebar/database"; -import { FieldErrors, Snowflake } from "@spacebar/util"; +import { Config, FieldErrors, Snowflake } from "@spacebar/util"; const router = Router({ mergeParams: true }); @@ -56,12 +56,11 @@ router.post( body.type = 1; } - if (body.name.trim().length < 1 || body.name.trim().length > 32) { - // TODO: configurable? + if (body.name.trim().length < 1 || body.name.trim().length > Config.get().limits.application.commandLimits.maxNameLength) { throw FieldErrors({ name: { code: "BASE_TYPE_BAD_LENGTH", - message: `Must be between 1 and 32 in length.`, + message: `Must be between 1 and ${Config.get().limits.application.commandLimits.maxNameLength} in length.`, }, }); } @@ -127,12 +126,11 @@ router.put( command.type = 1; } - if (command.name.trim().length < 1 || command.name.trim().length > 32) { - // TODO: configurable? + if (command.name.trim().length < 1 || command.name.trim().length > Config.get().limits.application.commandLimits.maxNameLength) { throw FieldErrors({ name: { code: "BASE_TYPE_BAD_LENGTH", - message: `Must be between 1 and 32 in length.`, + message: `Must be between 1 and ${Config.get().limits.application.commandLimits.maxNameLength} in length.`, }, }); } diff --git a/src/api/routes/applications/#application_id/guilds/#guild_id/commands/#command_id/index.ts b/src/api/routes/applications/#application_id/guilds/#guild_id/commands/#command_id/index.ts
index 6cbd4ae06..eea17006f 100644 --- a/src/api/routes/applications/#application_id/guilds/#guild_id/commands/#command_id/index.ts +++ b/src/api/routes/applications/#application_id/guilds/#guild_id/commands/#command_id/index.ts
@@ -19,7 +19,7 @@ import { Request, Response, Router } from "express"; import { route } from "@spacebar/api/middlewares"; import { Application, ApplicationCommand, Guild, Member } from "@spacebar/database"; -import { FieldErrors, Snowflake } from "@spacebar/util"; +import { Config, FieldErrors, Snowflake } from "@spacebar/util"; import { ApplicationCommandCreateSchema, ApplicationCommandSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -87,12 +87,11 @@ router.patch( body.type = 1; } - if (body.name.trim().length < 1 || body.name.trim().length > 32) { - // TODO: configurable? + if (body.name.trim().length < 1 || body.name.trim().length > Config.get().limits.application.commandLimits.maxNameLength) { throw FieldErrors({ name: { code: "BASE_TYPE_BAD_LENGTH", - message: `Must be between 1 and 32 in length.`, + message: `Must be between 1 and ${Config.get().limits.application.commandLimits.maxNameLength} in length.`, }, }); } diff --git a/src/api/routes/applications/#application_id/guilds/#guild_id/commands/index.ts b/src/api/routes/applications/#application_id/guilds/#guild_id/commands/index.ts
index 19444d3a8..520ca9995 100644 --- a/src/api/routes/applications/#application_id/guilds/#guild_id/commands/index.ts +++ b/src/api/routes/applications/#application_id/guilds/#guild_id/commands/index.ts
@@ -19,7 +19,7 @@ import { Request, Response, Router } from "express"; import { route } from "@spacebar/api/middlewares"; import { Application, ApplicationCommand, Guild, Member } from "@spacebar/database"; -import { FieldErrors, Snowflake } from "@spacebar/util"; +import { Config, FieldErrors, Snowflake } from "@spacebar/util"; import { ApplicationCommandCreateSchema, ApplicationCommandSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -79,12 +79,11 @@ router.post( body.type = 1; } - if (body.name.trim().length < 1 || body.name.trim().length > 32) { - // TODO: configurable? + if (body.name.trim().length < 1 || body.name.trim().length > Config.get().limits.application.commandLimits.maxNameLength) { throw FieldErrors({ name: { code: "BASE_TYPE_BAD_LENGTH", - message: `Must be between 1 and 32 in length.`, + message: `Must be between 1 and ${Config.get().limits.application.commandLimits.maxNameLength} in length.`, }, }); } @@ -165,12 +164,11 @@ router.put( command.type = 1; } - if (command.name.trim().length < 1 || command.name.trim().length > 32) { - // TODO: configurable? + if (command.name.trim().length < 1 || command.name.trim().length > Config.get().limits.application.commandLimits.maxNameLength) { throw FieldErrors({ name: { code: "BASE_TYPE_BAD_LENGTH", - message: `Must be between 1 and 32 in length.`, + message: `Must be between 1 and ${Config.get().limits.application.commandLimits.maxNameLength} in length.`, }, }); } diff --git a/src/api/routes/beaker.ts b/src/api/routes/beaker.ts
index 88cc72c09..393c89d64 100644 --- a/src/api/routes/beaker.ts +++ b/src/api/routes/beaker.ts
@@ -31,7 +31,6 @@ router.post( spacebarOnly: false, // Not part of public openapi }), (req: Request, res: Response) => { - // TODO: res.sendStatus(204); }, ); diff --git a/src/api/routes/channels/#channel_id/invites.ts b/src/api/routes/channels/#channel_id/invites.ts
index c16b9f955..d57b4f2be 100644 --- a/src/api/routes/channels/#channel_id/invites.ts +++ b/src/api/routes/channels/#channel_id/invites.ts
@@ -21,9 +21,9 @@ import { HTTPError } from "lambert-server/HTTPError"; import { route } from "@spacebar/api/middlewares"; import { Channel, Guild, Invite, PublicInviteRelation, User } from "@spacebar/database"; import { InviteCreateEvent, emitEvent } from "@spacebar/util"; -import { InviteCreateSchema, isTextChannel } from "@spacebar/schemas"; +import { InviteCreateSchema, isTextChannel, PublicUserProjection } from "@spacebar/schemas"; import { Random } from "@spacebar/extensions"; -import { InviteListResponse } from "@spacebar/schemas/api/guilds/Invite"; +import { InviteListResponse, PublicInvite } from "@spacebar/schemas/api/guilds/Invite"; const router: Router = Router({ mergeParams: true }); @@ -35,7 +35,7 @@ router.post( right: "CREATE_INVITES", responses: { 201: { - body: "Invite", + body: "PublicInvite", }, 404: {}, 400: { @@ -71,21 +71,20 @@ router.post( guild_id, channel_id: channel_id, inviter_id: user_id, + inviter: await User.findOneOrFail({ + where: { id: req.user_id }, + select: Object.fromEntries(PublicUserProjection.map((i) => [i, true])), // TODO: clean up + }), flags: body.flags ?? 0, }).save(); - const data = invite.toJSON(); - data.inviter = await User.getPublicUser(req.user_id); - data.guild = await Guild.findOne({ where: { id: guild_id } }); - data.channel = channel; - await emitEvent({ event: "INVITE_CREATE", - data, + data: invite.toGatewayInviteCreateData(), guild_id, } satisfies InviteCreateEvent); - res.status(201).send(data); + res.status(201).send(invite.toPublicJSON()); }, ); diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts
index 1816aa6db..d85b05119 100644 --- a/src/api/routes/channels/#channel_id/messages/index.ts +++ b/src/api/routes/channels/#channel_id/messages/index.ts
@@ -18,7 +18,7 @@ import { handleMessage, postHandleMessage } from "@spacebar/api/util"; import { route } from "@spacebar/api/middlewares"; -import { Attachment, Channel, Member, Message, ReadState, Relationship, User, ThreadMember, ThreadMemberFlags } from "@spacebar/database"; +import { Attachment, Channel, Member, Message, ReadState, Relationship, User, ThreadMember } from "@spacebar/database"; import { Config, DiscordApiErrors, @@ -52,6 +52,7 @@ import { Reaction, ReadStateType, RelationshipType, + ThreadMemberFlags, } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/channels/#channel_id/post-data.ts b/src/api/routes/channels/#channel_id/post-data.ts
index 202cce99b..72d582546 100644 --- a/src/api/routes/channels/#channel_id/post-data.ts +++ b/src/api/routes/channels/#channel_id/post-data.ts
@@ -21,7 +21,7 @@ import { messageUpload } from "./messages"; import { In } from "typeorm"; import { route } from "@spacebar/api/middlewares"; import { Channel, Member, Message } from "@spacebar/database"; -import { PostDataSchema, PublicMessage } from "@spacebar/schemas"; +import { PostDataResponse, PostDataSchema, PublicMessage } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -43,7 +43,9 @@ router.post( requestBody: "PostDataSchema", permission: "VIEW_CHANNEL", responses: { - 200: {}, + 200: { + body: "PostDataResponse", + }, 403: {}, }, }), @@ -54,6 +56,7 @@ router.post( id: In(body), }, }); + const [messages, members] = await Promise.all([ Message.find({ where: { @@ -81,17 +84,18 @@ router.post( }, }), ]); + await Message.fillReplies(messages); - const objRet: { threads: Record<string, { first_message: null | PublicMessage; owner: null | Member }> } = { threads: {} }; + const threadPostData: PostDataResponse = { threads: {} }; for (const thread of threads) { - const owner = members.find(({ id }) => id === thread.owner_id)?.toJSON() || null; - const first_message = messages.find(({ channel_id }) => channel_id === thread.id)?.toJSON() || null; - objRet.threads[thread.id] = { + const owner = members.find(({ id }) => id === thread.owner_id)?.toPublicMember() ?? null; + const first_message = messages.find(({ channel_id }) => channel_id === thread.id)?.toJSON() ?? null; + threadPostData.threads[thread.id] = { owner, first_message, }; } - return res.json(objRet); + return res.json(threadPostData); }, ); diff --git a/src/api/routes/channels/#channel_id/thread-members.ts b/src/api/routes/channels/#channel_id/thread-members.ts
index f1d2a6cf1..f6ed628ec 100644 --- a/src/api/routes/channels/#channel_id/thread-members.ts +++ b/src/api/routes/channels/#channel_id/thread-members.ts
@@ -19,9 +19,9 @@ import { Request, Response, Router } from "express"; import { MoreThan } from "typeorm"; import { route } from "@spacebar/api/middlewares"; -import { Channel, Member, ThreadMember, ThreadMemberFlags } from "@spacebar/database"; +import { Channel, Member, ThreadMember } from "@spacebar/database"; import { emitEvent, Permissions, ThreadCreateEvent, ThreadDeleteEvent, ThreadMembersUpdateEvent } from "@spacebar/util"; -import { ChannelType, Snowflake } from "@spacebar/schemas"; +import { ChannelType, Snowflake, ThreadMemberFlags } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -29,7 +29,9 @@ router.get( "/", route({ responses: { - 200: {}, + 200: { + body: "PublicThreadMembersResponse", + }, 403: {}, }, permission: "VIEW_CHANNEL", @@ -51,12 +53,14 @@ router.get( } return res.send( - await ThreadMember.find({ - where: { channel: { id: channel_id }, ...(after ? { user_id: MoreThan(after) } : {}) }, - take: limit ? parseInt(limit) : 50, - order: { member_idx: "ASC" }, - relations: { ...(with_member ? { member: true } : {}) }, - }), + ( + await ThreadMember.find({ + where: { channel: { id: channel_id }, ...(after ? { user_id: MoreThan(after) } : {}) }, + take: limit ? parseInt(limit) : 50, + order: { member_idx: "ASC" }, + relations: { ...(with_member ? { member: true } : {}) }, + }) + ).map((m) => m.toJSON()), ); }, ); diff --git a/src/api/routes/guilds/#guild_id/application-command-index.ts b/src/api/routes/guilds/#guild_id/application-command-index.ts
index 758392fe8..10f404e47 100644 --- a/src/api/routes/guilds/#guild_id/application-command-index.ts +++ b/src/api/routes/guilds/#guild_id/application-command-index.ts
@@ -64,10 +64,11 @@ router.get("/", route({}), async (req: Request, res: Response) => { guild_id: command.guild_id, name: command.name, name_localizations: command.name_localizations, - // name_localized: // TODO: make this work + name_localized: (command.name_localizations && req.user.settings?.locale ? command.name_localizations[req.user.settings.locale] : null) ?? command.name, description: command.description, description_localizations: command.description_localizations, - // description_localized: // TODO: make this work + description_localized: + (command.description_localizations && req.user.settings?.locale ? command.description_localizations[req.user.settings.locale] : null) ?? command.description, options: command.type === ApplicationCommandType.CHAT_INPUT ? command.options : undefined, default_member_permissions: command.default_member_permissions, dm_permission: command.dm_permission, diff --git a/src/api/routes/guilds/#guild_id/bans.ts b/src/api/routes/guilds/#guild_id/bans.ts
index 821746654..1a4890b8a 100644 --- a/src/api/routes/guilds/#guild_id/bans.ts +++ b/src/api/routes/guilds/#guild_id/bans.ts
@@ -26,6 +26,7 @@ import { BanCreateSchema, BanRegistrySchema, GuildBanResponse, GuildBansResponse const router: Router = Router({ mergeParams: true }); /* TODO: Deleting the secrets is just a temporary go-around. Views should be implemented for both safety and better handling. */ +// Emma [it/its] @ Rory& - 2026-11-01 - what secrets? router.get( "/", diff --git a/src/api/routes/guilds/#guild_id/index.ts b/src/api/routes/guilds/#guild_id/index.ts
index 9fa61a4d3..c4eb05515 100644 --- a/src/api/routes/guilds/#guild_id/index.ts +++ b/src/api/routes/guilds/#guild_id/index.ts
@@ -109,7 +109,6 @@ router.patch( if (body.features) { const diff = guild.features.filter((x) => !body.features?.includes(x)).concat(body.features.filter((x) => !guild.features.includes(x))); - // TODO move these const MUTABLE_FEATURES = ["COMMUNITY", "INVITES_DISABLED", "DISCOVERABLE"]; for (const feature of diff) { diff --git a/src/api/routes/guilds/#guild_id/regions.ts b/src/api/routes/guilds/#guild_id/regions.ts
index 025ea7c44..8709c9c00 100644 --- a/src/api/routes/guilds/#guild_id/regions.ts +++ b/src/api/routes/guilds/#guild_id/regions.ts
@@ -38,7 +38,6 @@ router.get( async (req: Request, res: Response) => { const { guild_id } = req.params as { [key: string]: string }; const guild = await Guild.findOneOrFail({ where: { id: guild_id } }); - //TODO we should use an enum for guild's features and not hardcoded strings return res.json(await getVoiceRegions(req.ip!, guild.features.includes("VIP_REGIONS"))); }, ); diff --git a/src/api/routes/guilds/index.ts b/src/api/routes/guilds/index.ts
index 231ba9041..6e6bf2099 100644 --- a/src/api/routes/guilds/index.ts +++ b/src/api/routes/guilds/index.ts
@@ -24,8 +24,6 @@ import { GuildCreateSchema } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); -//TODO: create default channel - router.post( "/", route({ diff --git a/src/api/routes/read-states/ack-bulk.ts b/src/api/routes/read-states/ack-bulk.ts
index 5a1cef184..07fcec962 100644 --- a/src/api/routes/read-states/ack-bulk.ts +++ b/src/api/routes/read-states/ack-bulk.ts
@@ -37,8 +37,6 @@ router.post( async (req: Request, res: Response) => { const body = req.body as AckBulkSchema; - // TODO: what is read_state_type ? - await Promise.all([ // for every new state ...body.read_states.map(async (x) => { diff --git a/src/api/routes/science.ts b/src/api/routes/science.ts
index 34f342883..012a78989 100644 --- a/src/api/routes/science.ts +++ b/src/api/routes/science.ts
@@ -30,7 +30,6 @@ router.post( authentication: "never", }), (req: Request, res: Response) => { - // TODO: res.sendStatus(204); }, ); diff --git a/src/api/routes/teams.ts b/src/api/routes/teams.ts
index 16fd5d3a5..1370c1eea 100644 --- a/src/api/routes/teams.ts +++ b/src/api/routes/teams.ts
@@ -84,7 +84,7 @@ router.post( role: TeamMemberRole.ADMIN, }).save(); - res.json(team.toJSON() satisfies Team); + res.json(team.toJSON()); }, ); diff --git a/src/api/routes/users/@me/billing/payment-sources.ts b/src/api/routes/users/@me/billing/payment-sources.ts
index 3c6008cf7..ec68efd12 100644 --- a/src/api/routes/users/@me/billing/payment-sources.ts +++ b/src/api/routes/users/@me/billing/payment-sources.ts
@@ -47,34 +47,63 @@ const example = { default: false, }; -router.get("/", route({}), (req: Request, res: Response) => { - // TODO: schema - res.json([example]).status(200); -}); +router.get( + "/", + route({ + responses: { + 200: { body: "PaymentSourceListResponse" }, + }, + }), + (req: Request, res: Response) => { + res.json([example]).status(200); + }, +); -router.post("/", route({}), (req: Request, res: Response) => { - // TODO: schema - res.json([example]).status(200); -}); +router.post( + "/", + route({ + responses: { + 200: { body: "PaymentSourceListResponse" }, + }, + }), + // TODO: request schema + (req: Request, res: Response) => { + res.json([example]).status(200); + }, +); -router.get("/:payment_source_id", route({}), (req: Request, res: Response) => { - // TODO: schema - res.json({ - ...example, - id: req.route.payment_source_id, - }).status(200); -}); +router.get( + "/:payment_source_id", + route({ + responses: { + 200: { body: "PaymentSource" }, + }, + }), + (req: Request, res: Response) => { + res.json({ + ...example, + id: req.route.payment_source_id, + }).status(200); + }, +); -router.patch("/:payment_source_id", route({}), (req: Request, res: Response) => { - // TODO: schema - res.json({ - ...example, - id: req.route.payment_source_id, - }).status(200); -}); +router.patch( + "/:payment_source_id", + route({ + responses: { + 200: { body: "PaymentSourceListResponse" }, + }, + }), + (req: Request, res: Response) => { + // TODO: request schema + res.json({ + ...example, + id: req.route.payment_source_id, + }).status(200); + }, +); router.delete("/:payment_source_id", route({}), (req: Request, res: Response) => { - // TODO: schema res.status(204); }); diff --git a/src/api/routes/users/@me/delete.ts b/src/api/routes/users/@me/delete.ts
index e0887900a..ec29a5fa6 100644 --- a/src/api/routes/users/@me/delete.ts +++ b/src/api/routes/users/@me/delete.ts
@@ -52,8 +52,6 @@ router.post( } } - // TODO: decrement guild member count - if (correctpass) { // Check if the user owns any guilds. const ownedGuilds = await Guild.findOne({ where: { owner_id: req.user_id } }); diff --git a/src/api/routes/users/@me/guilds/#guild_id/settings.ts b/src/api/routes/users/@me/guilds/#guild_id/settings.ts
index eb3694b59..fb2f794ed 100644 --- a/src/api/routes/users/@me/guilds/#guild_id/settings.ts +++ b/src/api/routes/users/@me/guilds/#guild_id/settings.ts
@@ -21,6 +21,8 @@ import { route } from "@spacebar/api/middlewares"; import { Channel, Member } from "@spacebar/database"; import { OrmUtils } from "@spacebar/util"; import { UserGuildSettingsSchema } from "@spacebar/schemas"; +import { In } from "typeorm"; +import { HTTPError } from "lambert-server"; const router = Router({ mergeParams: true }); @@ -60,10 +62,8 @@ router.patch( const body = req.body as UserGuildSettingsSchema; if (body.channel_overrides) { - // TODO: rewrite to a single query? - for (const channel in body.channel_overrides) { - await Channel.findOneOrFail({ where: { id: channel } }); - } + const channels = await Channel.find({ where: { id: In(Object.keys(body.channel_overrides)), guild_id: req.params.guild_id as string } }); + if (channels.length != Object.keys(body.channel_overrides).length) throw new HTTPError("Could not find one or more channels.", 404); } const user = await Member.findOneOrFail({ diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts
index 341dbf1f3..59565480e 100644 --- a/src/api/routes/users/@me/index.ts +++ b/src/api/routes/users/@me/index.ts
@@ -153,7 +153,6 @@ router.patch( } if (body.discriminator) { - // TODO: HACK - maybe make this optional? if (!/^\d{4}$/.test(body.discriminator)) { throw FieldErrors({ discriminator: { diff --git a/src/api/routes/users/@me/mfa/totp/enable.ts b/src/api/routes/users/@me/mfa/totp/enable.ts
index a55a9ff65..660778c8e 100644 --- a/src/api/routes/users/@me/mfa/totp/enable.ts +++ b/src/api/routes/users/@me/mfa/totp/enable.ts
@@ -51,12 +51,11 @@ router.post( select: { id: true, data: true, email: true }, }); - // TODO: Are guests allowed to enable 2fa? if (user.data.hash) { if (!(await bcrypt.compare(body.password, user.data.hash))) { throw new HTTPError(req.t("auth:login.INVALID_PASSWORD")); } - } + } else throw new HTTPError("Guests cannot enable 2FA, please set a password first!", 403); if (!body.secret) throw new HTTPError(req.t("auth:login.INVALID_TOTP_SECRET"), 60005); diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 2940b3064..3be73067e 100644 --- a/src/api/util/handlers/Message.ts +++ b/src/api/util/handlers/Message.ts
@@ -558,7 +558,6 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { return message; } -// TODO: cache link result in db export async function postHandleMessage(message: Message) { message.clean_data(); @@ -773,25 +772,21 @@ async function handleMessageMentionsAsync(message: Message) { mention_roles: true, }, }); + if (referencedMessage && referencedMessage.author_id !== message.author_id) { - message.mentions.push( - // @ts-expect-error it does not like the .toPublicUser() lol - (await User.findOne({ where: { id: referencedMessage.author_id } }))!.toPublicUser(), - ); + const user = await User.findOne({ where: { id: referencedMessage.author_id } }); + if (user) message.mentions.push(user); } if (message.embeds[0]?.type === EmbedType.poll_result) { - message.mentions.push( - // @ts-expect-error it does not like the .toPublicUser() lol - (await User.findOne({ where: { id: message.author_id } }))!.toPublicUser(), - ); + const user = await User.findOne({ where: { id: message.author_id } }); + if (user) message.mentions.push(user); } if (message.message_reference.type === MessageReferenceType.FORWARD) { message.type = MessageType.DEFAULT; if (message.referenced_message) { - // TODO: mention_roles and mentions arrays - not needed it seems, but discord still returns that message.message_snapshots = [message.referenced_message.toSnapshot()]; } }