From 1699d9ae2afe8b56bccd7c0723380065aef8bc81 Mon Sep 17 00:00:00 2001 From: MathMan05 Date: Thu, 5 Feb 2026 11:32:50 -0600 Subject: [PATCH] post with tags --- .../routes/channels/#channel_id/threads.ts | 33 ++++++++++++++++++- src/util/util/ChannelFlags.ts | 30 +++++++++++++++++ src/util/util/index.ts | 1 + 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/util/util/ChannelFlags.ts diff --git a/src/api/routes/channels/#channel_id/threads.ts b/src/api/routes/channels/#channel_id/threads.ts index 3845b96da..8ef2c0fe8 100644 --- a/src/api/routes/channels/#channel_id/threads.ts +++ b/src/api/routes/channels/#channel_id/threads.ts @@ -17,7 +17,22 @@ */ import { handleMessage, postHandleMessage, route, sendMessage } from "@spacebar/api"; -import { Channel, emitEvent, User, uploadFile, Attachment, Member, ReadState, MessageCreateEvent, FieldErrors, getPermission, ThreadMember, Message } from "@spacebar/util"; +import { + Channel, + emitEvent, + User, + uploadFile, + Attachment, + Member, + ReadState, + MessageCreateEvent, + FieldErrors, + getPermission, + ThreadMember, + Message, + ChannelFlags, + DiscordApiErrors, +} from "@spacebar/util"; import { ChannelType, MessageType, ThreadCreationSchema, MessageCreateAttachment, MessageCreateCloudAttachment } from "@spacebar/schemas"; import { Request, Response, Router } from "express"; @@ -56,7 +71,22 @@ router.post( const channel = await Channel.findOneOrFail({ where: { id: channel_id }, + relations: ["available_tags"], }); + if (!body.applied_tags?.length) { + const required = channel.flags & Number(ChannelFlags.FLAGS.REQUIRE_TAG); + //TODO better error + if (required) throw new Error("Tag is required for this API"); + } else if (channel.available_tags) { + const realTags = new Map(channel.available_tags.map((tag) => [tag.id, tag])); + const bad = body.applied_tags.find((tag) => !realTags.has(tag)); + //TODO better error + if (bad) throw new Error("Invalid tag " + bad); + const permsNeeded = body.applied_tags.find((_) => realTags.get(_)?.moderated); + if (permsNeeded) { + req.permission?.hasThrow("MANAGE_THREADS"); + } + } const user = await User.findOneOrFail({ where: { id: req.user_id } }); const thread = await Channel.createChannel( @@ -72,6 +102,7 @@ router.post( rate_limit_per_user: body.rate_limit_per_user, type: body.type || (channel.threadOnly() ? ChannelType.GUILD_PUBLIC_THREAD : ChannelType.GUILD_PRIVATE_THREAD), recipients: [], + applied_tags: body.applied_tags || [], thread_metadata: { archived: false, auto_archive_duration: body.auto_archive_duration || channel.default_auto_archive_duration || 4320, diff --git a/src/util/util/ChannelFlags.ts b/src/util/util/ChannelFlags.ts new file mode 100644 index 000000000..e0bea4344 --- /dev/null +++ b/src/util/util/ChannelFlags.ts @@ -0,0 +1,30 @@ +// based on https://github.com/discordjs/discord.js/blob/master/src/util/MessageFlags.js +// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah, 2022 Erkin Alp Güney +// @fc-license-skip + +import { BitField } from "./BitField"; + +export class ChannelFlags extends BitField { + static FLAGS = { + GUILD_FEED_REMOVED: BigInt(1) << BigInt(0), + PINNED: BigInt(1) << BigInt(1), + ACTIVE_CHANNELS_REMOVED: BigInt(1) << BigInt(2), + REQUIRE_TAG: BigInt(1) << BigInt(3), + URGENT: BigInt(1) << BigInt(4), + IS_SPAM: BigInt(1) << BigInt(5), + //Missing 6 + IS_GUILD_RESOURCE_CHANNEL: BigInt(1) << BigInt(7), + CLYDE_AI: BigInt(1) << BigInt(8), + IS_SCHEDULED_FOR_DELETION: BigInt(1) << BigInt(9), + //Unused 10 + SUMMARIES_DISABLED: BigInt(1) << BigInt(11), + //Deprecated 12 + IS_ROLE_SUBSCRIPTION_TEMPLATE_PREVIEW_CHANNEL: BigInt(1) << BigInt(13), + IS_BROADCASTING: BigInt(1) << BigInt(14), + HIDE_MEDIA_DOWNLOAD_OPTIONS: BigInt(1) << BigInt(15), + IS_JOIN_REQUEST_INTERVIEW_CHANNEL: BigInt(1) << BigInt(16), + OBFUSCATED: BigInt(1) << BigInt(17), + //Missing 18 + IS_MODERATOR_REPORT_CHANNEL: BigInt(1) << BigInt(19), + }; +} diff --git a/src/util/util/index.ts b/src/util/util/index.ts index b2cfc568b..aac4e3c03 100644 --- a/src/util/util/index.ts +++ b/src/util/util/index.ts @@ -47,6 +47,7 @@ export * from "./Timespan"; export * from "./Token"; export * from "./TraverseDirectory"; export * from "./WebAuthn"; +export * from "./ChannelFlags"; export * from "./Gifs"; export * from "./Application"; export * from "./NameValidation";