fix(discord): send initial message for non-forum thread creation (#18117)
Co-authored-by: Shadow <shadow@openclaw.ai>
This commit is contained in:
parent
7c240a2b58
commit
81d2a91a90
@ -53,6 +53,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Discord: send initial content when creating non-forum threads so `thread-create` content is delivered. (#18117) Thanks @zerone0x.
|
||||
- Security: replace deprecated SHA-1 sandbox configuration hashing with SHA-256 for deterministic sandbox cache identity and recreation checks. Thanks @kexinoh.
|
||||
- Security/Logging: redact Telegram bot tokens from error messages and uncaught stack traces to prevent accidental secret leakage into logs. Thanks @aether-ai-agent.
|
||||
- Sandbox/Security: block dangerous sandbox Docker config (bind mounts, host networking, unconfined seccomp/apparmor) to prevent container escape via config injection. Thanks @aether-ai-agent.
|
||||
|
||||
@ -107,6 +107,61 @@ describe("sendMessageDiscord", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("sends initial message for non-forum threads with content", async () => {
|
||||
const { rest, getMock, postMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValue({ type: ChannelType.GuildText });
|
||||
postMock.mockResolvedValue({ id: "t1" });
|
||||
await createThreadDiscord(
|
||||
"chan1",
|
||||
{ name: "thread", content: "Hello thread!" },
|
||||
{ rest, token: "t" },
|
||||
);
|
||||
expect(postMock).toHaveBeenCalledTimes(2);
|
||||
// First call: create thread
|
||||
expect(postMock).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
Routes.threads("chan1"),
|
||||
expect.objectContaining({
|
||||
body: expect.objectContaining({ name: "thread", type: ChannelType.PublicThread }),
|
||||
}),
|
||||
);
|
||||
// Second call: send message to thread
|
||||
expect(postMock).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
Routes.channelMessages("t1"),
|
||||
expect.objectContaining({
|
||||
body: { content: "Hello thread!" },
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("sends initial message for message-attached threads with content", async () => {
|
||||
const { rest, getMock, postMock } = makeDiscordRest();
|
||||
postMock.mockResolvedValue({ id: "t1" });
|
||||
await createThreadDiscord(
|
||||
"chan1",
|
||||
{ name: "thread", messageId: "m1", content: "Discussion here" },
|
||||
{ rest, token: "t" },
|
||||
);
|
||||
// Should not detect channel type for message-attached threads
|
||||
expect(getMock).not.toHaveBeenCalled();
|
||||
expect(postMock).toHaveBeenCalledTimes(2);
|
||||
// First call: create thread from message
|
||||
expect(postMock).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
Routes.threads("chan1", "m1"),
|
||||
expect.objectContaining({ body: { name: "thread" } }),
|
||||
);
|
||||
// Second call: send message to thread
|
||||
expect(postMock).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
Routes.channelMessages("t1"),
|
||||
expect.objectContaining({
|
||||
body: { content: "Discussion here" },
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("lists active threads by guild", async () => {
|
||||
const { rest, getMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValue({ threads: [] });
|
||||
|
||||
@ -134,7 +134,17 @@ export async function createThreadDiscord(
|
||||
const route = payload.messageId
|
||||
? Routes.threads(channelId, payload.messageId)
|
||||
: Routes.threads(channelId);
|
||||
return await rest.post(route, { body });
|
||||
const thread = (await rest.post(route, { body })) as { id: string };
|
||||
|
||||
// For non-forum channels, send the initial message separately after thread creation.
|
||||
// Forum channels handle this via the `message` field in the request body.
|
||||
if (!isForumLike && payload.content?.trim()) {
|
||||
await rest.post(Routes.channelMessages(thread.id), {
|
||||
body: { content: payload.content },
|
||||
});
|
||||
}
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
export async function listThreadsDiscord(payload: DiscordThreadList, opts: DiscordReactOpts = {}) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user