fix(discord): route thread messages with per-thread conversations (#564)

This commit is contained in:
Cameron
2026-03-11 16:54:19 -07:00
committed by GitHub
parent 13426396ac
commit fb32a4c3cd
2 changed files with 11 additions and 8 deletions

View File

@@ -318,7 +318,7 @@ Ask the bot owner to approve with:
let commandForcePerChat = false; let commandForcePerChat = false;
if (isGroup && this.config.groups) { if (isGroup && this.config.groups) {
const threadMode = resolveDiscordThreadMode(this.config.groups, keys); const threadMode = resolveDiscordThreadMode(this.config.groups, keys);
commandForcePerChat = threadMode === 'thread-only'; commandForcePerChat = threadMode === 'thread-only' || isThreadMessage;
if (commandForcePerChat && !isThreadMessage) { if (commandForcePerChat && !isThreadMessage) {
const shouldCreateThread = const shouldCreateThread =
wasMentioned && resolveDiscordAutoCreateThreadOnMention(this.config.groups, keys); wasMentioned && resolveDiscordAutoCreateThreadOnMention(this.config.groups, keys);
@@ -464,7 +464,8 @@ Ask the bot owner to approve with:
serverId: message.guildId || undefined, serverId: message.guildId || undefined,
wasMentioned, wasMentioned,
isListeningMode, isListeningMode,
forcePerChat: isThreadOnly || undefined, threadId: isThreadMessage ? effectiveChatId : undefined,
forcePerChat: (isThreadOnly || isThreadMessage) || undefined,
attachments, attachments,
formatterHints: this.getFormatterHints(), formatterHints: this.getFormatterHints(),
}); });
@@ -499,9 +500,10 @@ Ask the bot owner to approve with:
async sendMessage(msg: OutboundMessage): Promise<{ messageId: string }> { async sendMessage(msg: OutboundMessage): Promise<{ messageId: string }> {
if (!this.client) throw new Error('Discord not started'); if (!this.client) throw new Error('Discord not started');
const channel = await this.client.channels.fetch(msg.chatId); const targetChannelId = msg.threadId || msg.chatId;
const channel = await this.client.channels.fetch(targetChannelId);
if (!channel || !channel.isTextBased() || !('send' in channel)) { if (!channel || !channel.isTextBased() || !('send' in channel)) {
throw new Error(`Discord channel not found or not text-based: ${msg.chatId}`); throw new Error(`Discord channel not found or not text-based: ${targetChannelId}`);
} }
const sendable = channel as { send: (content: string) => Promise<{ id: string }> }; const sendable = channel as { send: (content: string) => Promise<{ id: string }> };
@@ -516,9 +518,10 @@ Ask the bot owner to approve with:
async sendFile(file: OutboundFile): Promise<{ messageId: string }> { async sendFile(file: OutboundFile): Promise<{ messageId: string }> {
if (!this.client) throw new Error('Discord not started'); if (!this.client) throw new Error('Discord not started');
const channel = await this.client.channels.fetch(file.chatId); const targetChannelId = file.threadId || file.chatId;
const channel = await this.client.channels.fetch(targetChannelId);
if (!channel || !channel.isTextBased() || !('send' in channel)) { if (!channel || !channel.isTextBased() || !('send' in channel)) {
throw new Error(`Discord channel not found or not text-based: ${file.chatId}`); throw new Error(`Discord channel not found or not text-based: ${targetChannelId}`);
} }
const payload = { const payload = {
@@ -697,7 +700,7 @@ Ask the bot owner to approve with:
groupName, groupName,
serverId: message.guildId || undefined, serverId: message.guildId || undefined,
isListeningMode, isListeningMode,
forcePerChat: reactionForcePerChat || undefined, forcePerChat: (reactionForcePerChat || isThreadMessage) || undefined,
reaction: { reaction: {
emoji, emoji,
messageId: message.id, messageId: message.id,

View File

@@ -125,7 +125,7 @@ export interface OutboundMessage {
chatId: string; chatId: string;
text: string; text: string;
replyToMessageId?: string; replyToMessageId?: string;
threadId?: string; // Slack thread_ts threadId?: string; // Thread ID (Slack thread_ts / Discord thread channel)
/** When set, tells the adapter which parse mode to use (e.g., 'MarkdownV2', /** When set, tells the adapter which parse mode to use (e.g., 'MarkdownV2',
* 'HTML') and to skip its default markdown conversion. Adapters that don't * 'HTML') and to skip its default markdown conversion. Adapters that don't
* support the specified mode ignore this and fall back to default. */ * support the specified mode ignore this and fall back to default. */