fix(feishu): use msg_type "audio" for opus files instead of "media" (openclaw#28269) thanks @Glucksberg

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
Glucksberg
2026-02-27 20:23:19 -04:00
committed by GitHub
parent 60ef923051
commit 0e755ad99a
3 changed files with 8 additions and 7 deletions

View File

@@ -16,6 +16,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Feishu/Probe status caching: cache successful `probeFeishu()` bot-info results for 10 minutes (bounded cache with per-account keying) to reduce repeated status/onboarding probe API calls, while bypassing cache for failures and exceptions. (#28907) Thanks @Glucksberg.
- Feishu/Opus media send type: send `.opus` attachments with `msg_type: "audio"` (instead of `"media"`) so Feishu voice messages deliver correctly while `.mp4` remains `msg_type: "media"` and documents remain `msg_type: "file"`. (#28269) Thanks @Glucksberg.
- Feishu/Local media sends: propagate `mediaLocalRoots` through Feishu outbound media sending into `loadWebMedia` so local path attachments work with post-CVE local-root enforcement. (#27884) Thanks @joelnishanth.
- Security/Feishu webhook ingress: bound unauthenticated webhook rate-limit state with stale-window pruning and a hard key cap to prevent unbounded pre-auth memory growth from rotating source keys. (#26050) Thanks @bmendonca3.
- Telegram/Reply media context: include replied media files in inbound context when replying to media, defer reply-media downloads to debounce flush, gate reply-media fetch behind DM authorization, and preserve replied media when non-vision sticker fallback runs (including cached-sticker paths). (#28488) Thanks @obviyus.

View File

@@ -129,7 +129,7 @@ describe("sendMediaFeishu msg_type routing", () => {
);
});
it("uses msg_type=media for opus", async () => {
it("uses msg_type=audio for opus", async () => {
await sendMediaFeishu({
cfg: {} as any,
to: "user:ou_target",
@@ -145,7 +145,7 @@ describe("sendMediaFeishu msg_type routing", () => {
expect(messageCreateMock).toHaveBeenCalledWith(
expect.objectContaining({
data: expect.objectContaining({ msg_type: "media" }),
data: expect.objectContaining({ msg_type: "audio" }),
}),
);
});

View File

@@ -306,8 +306,8 @@ export async function sendFileFeishu(params: {
cfg: ClawdbotConfig;
to: string;
fileKey: string;
/** Use "media" for audio/video files, "file" for documents */
msgType?: "file" | "media";
/** Use "media" for video, "audio" for audio, "file" for documents */
msgType?: "file" | "media" | "audio";
replyToMessageId?: string;
accountId?: string;
}): Promise<SendMediaResult> {
@@ -433,13 +433,13 @@ export async function sendMediaFeishu(params: {
fileType,
accountId,
});
// Feishu requires msg_type "media" for audio/video, "file" for documents
const isMedia = fileType === "mp4" || fileType === "opus";
// Feishu API: opus -> "audio", mp4 -> "media", everything else -> "file"
const msgType = fileType === "opus" ? "audio" : fileType === "mp4" ? "media" : "file";
return sendFileFeishu({
cfg,
to,
fileKey,
msgType: isMedia ? "media" : "file",
msgType,
replyToMessageId,
accountId,
});