summary refs log tree commit diff
diff options
context:
space:
mode:
authorCyberL1 <cyber.hf18@gmail.com>2026-06-25 01:18:06 +0200
committerRory& <root@rory.gay>2026-06-25 17:56:49 +0200
commita12224536e8c4d0074ddc2c47a3917d61568a3eb (patch)
tree084427403c0c30c9853d501f1e17dab265ea68e8
parentfeat: add route to get voters for an answer (diff)
downloadserver-ts-a12224536e8c4d0074ddc2c47a3917d61568a3eb.tar.xz
feat: add route to expire a poll
-rw-r--r--assets/openapi.json85
-rw-r--r--src/api/routes/channels/#channel_id/polls/#poll_id/expire.ts49
-rw-r--r--src/util/util/Constants.ts1
3 files changed, 135 insertions, 0 deletions
diff --git a/assets/openapi.json b/assets/openapi.json

index 5de9ed29..f9f6f540 100644 --- a/assets/openapi.json +++ b/assets/openapi.json
@@ -24824,6 +24824,44 @@ ] } }, + "/channels/{channel_id}/polls/{poll_id}/expire/": { + "post": { + "x-permission-required": "VIEW_CHANNEL", + "security": [ + { + "bearer": [] + } + ], + "responses": { + "default": { + "description": "No description available" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "poll_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "poll_id" + } + ], + "tags": [ + "channels" + ] + } + }, "/channels/{channel_id}/polls/{poll_id}/answers/@me/": { "put": { "x-permission-required": "VIEW_CHANNEL", @@ -24872,6 +24910,53 @@ ] } }, + "/channels/{channel_id}/polls/{poll_id}/answers/{answer_id}/": { + "get": { + "x-permission-required": "VIEW_CHANNEL", + "security": [ + { + "bearer": [] + } + ], + "responses": { + "default": { + "description": "No description available" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "poll_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "poll_id" + }, + { + "name": "answer_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "answer_id" + } + ], + "tags": [ + "channels" + ] + } + }, "/channels/{channel_id}/pins/{message_id}": { "put": { "x-permission-required": "VIEW_CHANNEL", diff --git a/src/api/routes/channels/#channel_id/polls/#poll_id/expire.ts b/src/api/routes/channels/#channel_id/polls/#poll_id/expire.ts new file mode 100644
index 00000000..9ac12886 --- /dev/null +++ b/src/api/routes/channels/#channel_id/polls/#poll_id/expire.ts
@@ -0,0 +1,49 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2026 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +import { Request, Response, Router } from "express"; +import { route } from "@spacebar/api/util/handlers/route"; +import { Message } from "#database"; +import { DiscordApiErrors } from "#util"; + +const router: Router = Router({ mergeParams: true }); + +router.post("/", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: Response) => { + const { poll_id } = req.params as { [key: string]: string }; + + const message = await Message.findOne({ where: { id: poll_id } }); + + if (!message) { + throw DiscordApiErrors.UNKNOWN_MESSAGE; + } + + if (!message.poll) { + throw DiscordApiErrors.NON_POLL_MESSAGE_CANNOT_EXPIRE; + } + + if (new Date() > new Date(message.poll.expiry)) { + throw DiscordApiErrors.POLL_EXPIRED; + } + + message.poll.expiry = new Date(); + + await message.save(); + res.send(message); +}); + +export default router; diff --git a/src/util/util/Constants.ts b/src/util/util/Constants.ts
index b605d1a9..78c73897 100644 --- a/src/util/util/Constants.ts +++ b/src/util/util/Constants.ts
@@ -663,6 +663,7 @@ export const DiscordApiErrors = { POLL_EXPIRED: new ApiError("Poll expired", 520001), POLL_INVALID_CHANNEL_TYPE: new ApiError("Invalid channel type for poll creation", 520002), POLL_CANNOT_EDIT_MESSAGE: new ApiError("Cannot edit a poll message", 520003), + NON_POLL_MESSAGE_CANNOT_EXPIRE: new ApiError("Cannot expire a non-poll message", 520006), //Other errors UNKNOWN_VOICE_STATE: new ApiError("Unknown Voice State", 10065, 404),