Discord: refine voice message handling

This commit is contained in:
Shadow
2026-02-13 12:33:45 -06:00
committed by Shadow
parent 76ab377a19
commit 1c9c01ff49
5 changed files with 93 additions and 39 deletions

View File

@@ -229,21 +229,26 @@ export async function handleDiscordMessagingAction(
throw new Error("Discord message sends are disabled.");
}
const to = readStringParam(params, "to", { required: true });
const content = readStringParam(params, "content", {
required: true,
allowEmpty: true,
});
const mediaUrl = readStringParam(params, "mediaUrl");
const replyTo = readStringParam(params, "replyTo");
const asVoice = params.asVoice === true;
const silent = params.silent === true;
const content = readStringParam(params, "content", {
required: !asVoice,
allowEmpty: true,
});
const mediaUrl =
readStringParam(params, "mediaUrl", { trim: false }) ??
readStringParam(params, "path", { trim: false }) ??
readStringParam(params, "filePath", { trim: false });
const replyTo = readStringParam(params, "replyTo");
const embeds =
Array.isArray(params.embeds) && params.embeds.length > 0 ? params.embeds : undefined;
// Handle voice message sending
if (asVoice) {
if (!mediaUrl) {
throw new Error("Voice messages require a media file path (mediaUrl).");
throw new Error(
"Voice messages require a local media file path (mediaUrl, path, or filePath).",
);
}
if (content && content.trim()) {
throw new Error(
@@ -263,7 +268,7 @@ export async function handleDiscordMessagingAction(
return jsonResult({ ok: true, result, voiceMessage: true });
}
const result = await sendMessageDiscord(to, content, {
const result = await sendMessageDiscord(to, content ?? "", {
...(accountId ? { accountId } : {}),
mediaUrl,
replyTo,

View File

@@ -32,6 +32,7 @@ const removeOwnReactionsDiscord = vi.fn(async () => ({ removed: ["👍"] }));
const removeReactionDiscord = vi.fn(async () => ({}));
const searchMessagesDiscord = vi.fn(async () => ({}));
const sendMessageDiscord = vi.fn(async () => ({}));
const sendVoiceMessageDiscord = vi.fn(async () => ({}));
const sendPollDiscord = vi.fn(async () => ({}));
const sendStickerDiscord = vi.fn(async () => ({}));
const setChannelPermissionDiscord = vi.fn(async () => ({ ok: true }));
@@ -64,6 +65,7 @@ vi.mock("../../discord/send.js", () => ({
removeReactionDiscord: (...args: unknown[]) => removeReactionDiscord(...args),
searchMessagesDiscord: (...args: unknown[]) => searchMessagesDiscord(...args),
sendMessageDiscord: (...args: unknown[]) => sendMessageDiscord(...args),
sendVoiceMessageDiscord: (...args: unknown[]) => sendVoiceMessageDiscord(...args),
sendPollDiscord: (...args: unknown[]) => sendPollDiscord(...args),
sendStickerDiscord: (...args: unknown[]) => sendStickerDiscord(...args),
setChannelPermissionDiscord: (...args: unknown[]) => setChannelPermissionDiscord(...args),
@@ -235,6 +237,43 @@ describe("handleDiscordMessagingAction", () => {
);
});
it("sends voice messages from a local file path", async () => {
sendVoiceMessageDiscord.mockClear();
sendMessageDiscord.mockClear();
await handleDiscordMessagingAction(
"sendMessage",
{
to: "channel:123",
path: "/tmp/voice.mp3",
asVoice: true,
silent: true,
},
enableAllActions,
);
expect(sendVoiceMessageDiscord).toHaveBeenCalledWith("channel:123", "/tmp/voice.mp3", {
replyTo: undefined,
silent: true,
});
expect(sendMessageDiscord).not.toHaveBeenCalled();
});
it("rejects voice messages that include content", async () => {
await expect(
handleDiscordMessagingAction(
"sendMessage",
{
to: "channel:123",
mediaUrl: "/tmp/voice.mp3",
asVoice: true,
content: "hello",
},
enableAllActions,
),
).rejects.toThrow(/Voice messages cannot include text content/);
});
it("forwards optional thread content", async () => {
createThreadDiscord.mockClear();
await handleDiscordMessagingAction(