summary refs log tree commit diff
path: root/src/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/api')
-rw-r--r--src/api/routes/auth/generate-registration-tokens.ts4
-rw-r--r--src/api/routes/channels/#channel_id/attachments.ts100
-rw-r--r--src/api/routes/channels/#channel_id/invites.ts4
-rw-r--r--src/api/routes/guilds/#guild_id/widget.json.ts4
-rw-r--r--src/api/util/utility/RandomInviteID.ts2
5 files changed, 107 insertions, 7 deletions
diff --git a/src/api/routes/auth/generate-registration-tokens.ts b/src/api/routes/auth/generate-registration-tokens.ts

index 303c6ab5..ca5020fb 100644 --- a/src/api/routes/auth/generate-registration-tokens.ts +++ b/src/api/routes/auth/generate-registration-tokens.ts
@@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { random, route } from "@spacebar/api"; +import { randomString, route } from "@spacebar/api"; import { Config, ValidRegistrationToken } from "@spacebar/util"; import { Request, Response, Router } from "express"; @@ -51,7 +51,7 @@ router.get( for (let i = 0; i < count; i++) { const token = ValidRegistrationToken.create({ - token: random(length), + token: randomString(length), expires_at: new Date( Date.now() + Config.get().security diff --git a/src/api/routes/channels/#channel_id/attachments.ts b/src/api/routes/channels/#channel_id/attachments.ts new file mode 100644
index 00000000..5da1a778 --- /dev/null +++ b/src/api/routes/channels/#channel_id/attachments.ts
@@ -0,0 +1,100 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2025 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 { generateCode, randomString, route } from "@spacebar/api"; +import { + Attachment, + Channel, + Config, + emitEvent, + GreetRequestSchema, + Message, + MessageCreateEvent, + MessageType, + Permissions, + Sticker, + UploadAttachmentRequestSchema, + UploadAttachmentResponseSchema, + User, +} from "@spacebar/util"; +import { Request, Response, Router } from "express"; +import { In } from "typeorm"; +import { CloudAttachment } from "../../../../util/entities/CloudAttachment"; + +const router: Router = Router(); + +router.post( + "/", + route({ + requestBody: "UploadAttachmentRequestSchema", + responses: { + 200: { + body: "UploadAttachmentResponseSchema", + }, + 404: {}, + 400: { + body: "APIErrorResponse", + }, + }, + }), + async (req: Request, res: Response) => { + const payload = req.body as UploadAttachmentRequestSchema; + const { channel_id } = req.params; + + const user = await User.findOneOrFail({ where: { id: req.user_id } }); + const channel = await Channel.findOneOrFail({ where: { id: channel_id } }); + + if (!(await channel.getUserPermissions({ user_id: req.user_id })).has(Permissions.FLAGS.ATTACH_FILES)) { + return res.status(403).json({ + code: 403, + message: "Missing Permissions: ATTACH_FILES", + }); + } + + const cdnUrl = Config.get().cdn.endpointPublic; + const batchId = `CLOUD_${user.id}_${randomString(128)}`; + const attachments = await Promise.all( + payload.files.map(async (attachment) => { + attachment.filename = attachment.filename.replaceAll(" ", "_").replace(/[^a-zA-Z0-9._]+/g, ""); + const uploadFilename = `${batchId}/${attachment.id}/${attachment.filename}`; + const newAttachment = CloudAttachment.create({ + user: user, + channel: channel, + uploadFilename: uploadFilename, + userAttachmentId: attachment.id, + userFilename: attachment.filename, + userFileSize: attachment.file_size, + userIsClip: attachment.is_clip, + userOriginalContentType: attachment.original_content_type, + }); + await newAttachment.save(); + return newAttachment; + }), + ); + + res.send({attachments: attachments.map(a => { + return { + id: a.userAttachmentId, + upload_filename: a.uploadFilename, + upload_url: `${cdnUrl}/attachments/${a.uploadFilename}`, + } + })} as UploadAttachmentResponseSchema); + }, +); + +export default router; diff --git a/src/api/routes/channels/#channel_id/invites.ts b/src/api/routes/channels/#channel_id/invites.ts
index ae32e80d..e8602729 100644 --- a/src/api/routes/channels/#channel_id/invites.ts +++ b/src/api/routes/channels/#channel_id/invites.ts
@@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { random, route } from "@spacebar/api"; +import { randomString, route } from "@spacebar/api"; import { Channel, Guild, @@ -70,7 +70,7 @@ router.post( : new Date(body.max_age * 1000 + Date.now()); const invite = await Invite.create({ - code: random(), + code: randomString(), temporary: body.temporary || true, uses: 0, max_uses: body.max_uses ? Math.max(0, body.max_uses) : 0, diff --git a/src/api/routes/guilds/#guild_id/widget.json.ts b/src/api/routes/guilds/#guild_id/widget.json.ts
index 5d9f28c2..f0518184 100644 --- a/src/api/routes/guilds/#guild_id/widget.json.ts +++ b/src/api/routes/guilds/#guild_id/widget.json.ts
@@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { random, route } from "@spacebar/api"; +import { randomString, route } from "@spacebar/api"; import { Channel, DiscordApiErrors, @@ -77,7 +77,7 @@ router.get( const expires_at = new Date(max_age * 1000 + Date.now()); invite = await Invite.create({ - code: random(), + code: randomString(), temporary: false, uses: 0, max_uses: 0, diff --git a/src/api/util/utility/RandomInviteID.ts b/src/api/util/utility/RandomInviteID.ts
index 926750d3..bd50ed92 100644 --- a/src/api/util/utility/RandomInviteID.ts +++ b/src/api/util/utility/RandomInviteID.ts
@@ -22,7 +22,7 @@ import crypto from "crypto"; // TODO: 'random'? seriously? who named this? // And why is this even here? Just use cryto.randomBytes? -export function random(length = 6) { +export function randomString(length = 6) { // Declare all characters const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";