Skip to content

Commit 3dd5c18

Browse files
tzy-17steipete
andauthored
fix(discord): honor forum archive defaults (#103033)
Carry typed forum/media parent metadata through the message-send path so implicit thread creation uses the configured default archive duration. Co-authored-by: Peter Steinberger <[email protected]>
1 parent 9108868 commit 3dd5c18

4 files changed

Lines changed: 24 additions & 13 deletions

File tree

extensions/discord/src/send.components.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import {
3232
buildDiscordSendError,
3333
createDiscordClient,
3434
resolveChannelId,
35-
resolveDiscordChannelType,
35+
resolveDiscordChannel,
3636
toDiscordFileBlob,
3737
stripUndefinedFields,
3838
SUPPRESS_NOTIFICATIONS_FLAG,
@@ -299,9 +299,9 @@ export async function sendDiscordComponentMessage(
299299
const recipient = await parseAndResolveChannelRecipient(to, cfg, opts.accountId);
300300
const { channelId } = await resolveChannelId(rest, recipient, request);
301301

302-
const channelType = await resolveDiscordChannelType(rest, channelId);
302+
const channel = await resolveDiscordChannel(rest, channelId);
303303

304-
if (channelType && DISCORD_FORUM_LIKE_TYPES.has(channelType)) {
304+
if (channel && DISCORD_FORUM_LIKE_TYPES.has(channel.type)) {
305305
throw new Error("Discord components are not supported in forum-style channels");
306306
}
307307

extensions/discord/src/send.outbound.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Discord plugin module implements send.outbound behavior.
2+
import type { APIChannel, APIGuildForumChannel, APIGuildMediaChannel } from "discord-api-types/v10";
23
import { ChannelType } from "discord-api-types/v10";
34
import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
45
import type { MarkdownTableMode, OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
@@ -28,7 +29,7 @@ import {
2829
normalizeStickerIds,
2930
resolveDiscordMessageFlags,
3031
resolveChannelId,
31-
resolveDiscordChannelType,
32+
resolveDiscordChannel,
3233
resolveDiscordSendComponents,
3334
resolveDiscordSendEmbeds,
3435
sendDiscordMedia,
@@ -121,8 +122,10 @@ function deriveForumThreadName(text: string): string {
121122
}
122123

123124
/** Forum/Media channels cannot receive regular messages; detect them here. */
124-
function isForumLikeType(channelType?: number): boolean {
125-
return channelType === ChannelType.GuildForum || channelType === ChannelType.GuildMedia;
125+
function isForumLikeChannel(
126+
channel?: APIChannel,
127+
): channel is APIGuildForumChannel | APIGuildMediaChannel {
128+
return channel?.type === ChannelType.GuildForum || channel?.type === ChannelType.GuildMedia;
126129
}
127130

128131
function toDiscordSendResult(
@@ -199,9 +202,9 @@ export async function sendMessageDiscord(
199202
const { channelId } = await resolveChannelId(rest, recipient, request);
200203

201204
// Forum/Media channels reject POST /messages; auto-create a thread post instead.
202-
const channelType = await resolveDiscordChannelType(rest, channelId);
205+
const channel = await resolveDiscordChannel(rest, channelId);
203206

204-
if (isForumLikeType(channelType)) {
207+
if (isForumLikeChannel(channel)) {
205208
const threadName = deriveForumThreadName(textWithTables);
206209
const chunks = buildDiscordTextChunks(textWithMentions, {
207210
maxLinesPerMessage,
@@ -236,6 +239,11 @@ export async function sendMessageDiscord(
236239
{
237240
body: {
238241
name: threadName,
242+
// Discord clients preselect the parent default; the REST endpoint otherwise
243+
// falls back to 4320 minutes, so carry the fetched parent value explicitly.
244+
...(channel.default_auto_archive_duration === undefined
245+
? {}
246+
: { auto_archive_duration: channel.default_auto_archive_duration }),
239247
message: starterBody,
240248
},
241249
},

extensions/discord/src/send.sends-basic-channel-messages.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,10 @@ describe("sendMessageDiscord", () => {
432432
it("auto-creates a forum thread when target is a Forum channel", async () => {
433433
const { rest, postMock, getMock } = makeDiscordRest();
434434
// Channel type lookup returns a Forum channel.
435-
getMock.mockResolvedValueOnce({ type: ChannelType.GuildForum });
435+
getMock.mockResolvedValueOnce({
436+
type: ChannelType.GuildForum,
437+
default_auto_archive_duration: 1440,
438+
});
436439
postMock.mockResolvedValue({
437440
id: "thread1",
438441
message: { id: "starter1", channel_id: "thread1" },
@@ -453,6 +456,7 @@ describe("sendMessageDiscord", () => {
453456
expectRestRoute(postMock, 0, Routes.threads("forum1"));
454457
expect(requireRestBody(postMock)).toEqual({
455458
name: "Discussion topic",
459+
auto_archive_duration: 1440,
456460
message: {
457461
content: "Discussion topic\nBody of the post",
458462
flags: MessageFlags.SuppressEmbeds,

extensions/discord/src/send.shared.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,13 +278,12 @@ async function resolveDiscordTargetChannelId(
278278
return await resolveChannelId(rest, recipient, request);
279279
}
280280

281-
export async function resolveDiscordChannelType(
281+
export async function resolveDiscordChannel(
282282
rest: RequestClient,
283283
channelId: string,
284-
): Promise<number | undefined> {
284+
): Promise<APIChannel | undefined> {
285285
try {
286-
const channel = (await getChannel(rest, channelId)) as APIChannel | undefined;
287-
return channel?.type;
286+
return await getChannel(rest, channelId);
288287
} catch {
289288
return undefined;
290289
}

0 commit comments

Comments
 (0)