Create and Manage Forum Channels
Recognize forum and media channels, create them with tags and post settings, change one tag at a time and read their posts
A forum channel holds posts instead of messages. Each post is a public thread with its own first message. A media channel is a forum channel that can also hide media download options
The examples use the default API. The Effect entry point exports the same names
Recognize a Forum Channel
Compare type with Channel or Channel. Both shapes share the post settings below, and only a forum channel has default
import { ChannelFlags, ChannelType } from "@neontechspace/fluxerly"
export function forumSummary(channel) {
if (channel.type !== ChannelType.Forum && channel.type !== ChannelType.Media)
return undefined
return {
guidelines: channel.topic,
tags: (channel.availableTags ?? []).map((tag) => tag.name),
requiresTag: ((channel.flags ?? 0) & ChannelFlags.RequireTag) !== 0,
}
}
import { ChannelFlags, ChannelType, type GuildChannel } from "@neontechspace/fluxerly"
export function forumSummary(channel: GuildChannel) {
if (channel.type !== ChannelType.Forum && channel.type !== ChannelType.Media) return undefined
return {
guidelines: channel.topic,
tags: (channel.availableTags ?? []).map((tag) => tag.name),
requiresTag: ((channel.flags ?? 0) & ChannelFlags.RequireTag) !== 0,
}
}
The channels method lists forum and media channels but never their posts. The channels method returns a post as a thread shape when the ID names one, and channels can return one when the cache holds it, so compare type or use is before reading fields that only some shapes have
Read Post Settings
Fluxer leaves the post settings out of some payloads, such as the guild event. Each setting is therefore optional, and its absence means that it is unavailable, not that it has its default
available: The tags a post can carry, at most 20. Only members who can manage threads may apply or remove aTags moderatedtagdefault: The reaction clients show on each post, or nullReaction Emoji default: ASort Order Forumvalue, or nullSort Order default: AForum Layout Forumvalue, on a forum channel onlyLayout default: How a post search matches tags,Tag Setting "match_orsome" "match_all" defaultandAuto Archive Minutes default: Defaults for new posts. Fluxer stores the archive period but does not apply it to a new postThread Rate Limit Per User flags:Channel, andFlags .Require Tag Channelon a media channelFlags .Hide Media Download Options
Flag bits, sort orders, layouts and tag settings that this SDK version does not name are kept as Fluxer sent them. Audit-log entries for forum channel changes record available_ as Forum values and default_ as a Forum
Read Posts
Each post is a Guild whose parent is the forum or media channel. The applied field lists the post's tags, and Channel in flags marks the channel's pinned post. Read threads covers the fields every thread shares
import { ChannelType } from "@neontechspace/fluxerly"
export function postTagNames(forum, post) {
if (post.type !== ChannelType.PublicThread || post.parentId !== forum.id)
return []
const names = new Map((forum.availableTags ?? []).map((tag) => [tag.id, tag.name]))
return (post.appliedTagIds ?? []).map((id) => names.get(id) ?? id)
}
import { ChannelType, type GuildForumChannel, type GuildThreadChannel } from "@neontechspace/fluxerly"
export function postTagNames(forum: GuildForumChannel, post: GuildThreadChannel) {
if (post.type !== ChannelType.PublicThread || post.parentId !== forum.id) return []
const names = new Map((forum.availableTags ?? []).map((tag) => [tag.id, tag.name]))
return (post.appliedTagIds ?? []).map((id) => names.get(id) ?? id)
}
Create a Forum or Media Channel
A channels call takes Channel or Channel together with the channel's tags and post settings. The bot needs Manage, and Fluxer rejects forum and media channels in a community where threads are not active, which threads on guilds reports
import { ChannelFlags, ChannelType, ForumLayout, ForumSortOrder } from "@neontechspace/fluxerly"
export async function createHelpForum(client, guildId) {
const result = await client.channels.create(guildId, {
type: ChannelType.Forum,
name: "help",
topic: "Ask one question per post and say what was already tried",
availableTags: [
{ name: "bug", emojiName: "🐛" },
{ name: "question" },
{ name: "staff", moderated: true },
],
defaultSortOrder: ForumSortOrder.CreationTime,
defaultForumLayout: ForumLayout.List,
flags: ChannelFlags.RequireTag,
})
return result.map((channel) => channel.id)
}
import { ChannelFlags, ChannelType, ForumLayout, ForumSortOrder, type Client } from "@neontechspace/fluxerly"
export async function createHelpForum(client: Client, guildId: string) {
const result = await client.channels.create(guildId, {
type: ChannelType.Forum,
name: "help",
topic: "Ask one question per post and say what was already tried",
availableTags: [
{ name: "bug", emojiName: "🐛" },
{ name: "question" },
{ name: "staff", moderated: true },
],
defaultSortOrder: ForumSortOrder.CreationTime,
defaultForumLayout: ForumLayout.List,
flags: ChannelFlags.RequireTag,
})
return result.map((channel) => channel.id)
}
These settings are specific to forum and media channels, and the SDK rejects a setting that the created channel type cannot have before it sends anything
topic: Posting guidelines of up to 4,096 characters, where other channels allow 1,024available: Up to 20 tags. A tag has aTags nameof 1 to 50 characters that no other tag of the channel uses, an optionalmoderatedflag, and at most one ofemoji, a custom emoji of the community, andId emoji, a single Unicode emojiName default: The reaction on each post, with the same two emoji fieldsReaction Emoji default,Sort Order defaultandForum Layout default: The defaults thatTag Setting Forum,Sort Order Forumand the tag setting names describe. A media channel has no layoutLayout flags:Channelmakes every post carry a tag, which needs at least one tag that is notFlags .Require Tag moderated.Channelis valid on a media channel onlyFlags .Hide Media Download Options
Set Thread Defaults on Any Thread Parent
Text, announcement, forum and media channels accept default, one of the Thread values, and default, a slowmode in seconds from 0 to 21,600. A new thread copies the slowmode when its creation sets none. Fluxer stores the archive period but does not apply it, so a new thread uses Thread unless its creation sets another period. In a community where threads are not active, Fluxer ignores both settings on text and announcement channels. Pass null to clear a default
Change a Forum Channel
A channels call accepts the same settings as creation, and it leaves every omitted setting unchanged. Passing null resets default, default, default and default. The flags value replaces all flags, so include Channel to keep it
The available list replaces the whole tag list. An entry with an id keeps that tag and replaces its settings, an entry without one adds a tag, and a tag left out is deleted, after which posts stop showing it. A received Forum is valid input, so passing back forum keeps every tag. An edit cannot see the channel's type, so Fluxer ignores a setting that does not belong to it, such as available sent for a text channel
Change One Tag
Changing a single tag through a full list risks overwriting a concurrent change. The channels, channels and channels methods change one tag and return the updated channel. Each needs Manage and accepts an audit
export async function addTag(client, forumId, name) {
const updated = await client.channels.createForumTag(forumId, { name })
return updated.map((channel) => channel.availableTags?.find((tag) => tag.name === name)?.id)
}
export async function moderateTag(client, forum, tagName) {
const tag = forum.availableTags?.find((candidate) => candidate.name === tagName)
if (tag === undefined)
return undefined
// Editing a tag replaces all of its settings, so the received tag supplies the ones that stay
return await client.channels.editForumTag(forum.id, tag.id, { ...tag, moderated: true })
}
export async function removeTag(client, forumId, tagId) {
return await client.channels.deleteForumTag(forumId, tagId)
}
import type { Client, GuildForumChannel } from "@neontechspace/fluxerly"
export async function addTag(client: Client, forumId: string, name: string) {
const updated = await client.channels.createForumTag(forumId, { name })
return updated.map((channel) => channel.availableTags?.find((tag) => tag.name === name)?.id)
}
export async function moderateTag(client: Client, forum: GuildForumChannel, tagName: string) {
const tag = forum.availableTags?.find((candidate) => candidate.name === tagName)
if (tag === undefined) return undefined
// Editing a tag replaces all of its settings, so the received tag supplies the ones that stay
return await client.channels.editForumTag(forum.id, tag.id, { ...tag, moderated: true })
}
export async function removeTag(client: Client, forumId: string, tagId: string) {
return await client.channels.deleteForumTag(forumId, tagId)
}
Fluxer assigns the ID of a new tag, so read it from the returned channel by name. An edit without moderated or an emoji resets them to false or none. Deleting an unknown tag fails, which includes a second delete of the same tag. Fluxer also rejects a change that would leave a channel with Channel without a tag that is not moderated
Start Posts
Read threads covers posts started with the bot. A webhook that belongs to a forum or media channel can start a post with thread, as the webhook guide shows