fix(imessage): preserve threaded voice sends

This commit is contained in:
Omar Shahine
2026-06-06 05:17:24 +00:00
parent 46f1d2e340
commit 258d2d73f3
2 changed files with 41 additions and 1 deletions

View File

@@ -200,6 +200,42 @@ describe("sendMessageIMessage receipts", () => {
expect(client["request"]).not.toHaveBeenCalled();
});
it("preserves audioAsVoice media when replying to an iMessage thread", async () => {
const client = createClient({ message_id: 12345 });
const runCliJson = vi.fn().mockResolvedValueOnce({ messageId: "p:0/threaded-voice-guid" });
const result = await sendMessageIMessage("chat_guid:chat-1", "", {
config: IMESSAGE_TEST_CFG,
client,
mediaUrl: "/tmp/voice.caf",
audioAsVoice: true,
replyToId: "p:0/reply-guid",
resolveAttachmentImpl: async () => ({ path: "/tmp/voice.caf", contentType: "audio/x-caf" }),
runCliJson,
});
expect(result.messageId).toBe("p:0/threaded-voice-guid");
expect(runCliJson.mock.calls).toEqual([
[
[
"send-attachment",
"--chat",
"chat-1",
"--file",
"/tmp/voice.caf",
"--audio",
"--reply-to",
"p:0/reply-guid",
"--transport",
"auto",
],
],
]);
expect(result.receipt.replyToId).toBe("p:0/reply-guid");
expect(result.receipt.parts.map((part) => part.kind)).toEqual(["voice"]);
expect(client["request"]).not.toHaveBeenCalled();
});
it("resolves chat_id media-only payloads before using send-attachment", async () => {
const client = createClient({ message_id: 12345 });
const runCliJson = vi

View File

@@ -731,6 +731,7 @@ async function trySendAttachmentForTarget(params: {
service?: IMessageService;
filePath: string;
audioAsVoice?: boolean;
replyToId?: string;
echoText?: string;
runCliJson: (args: readonly string[]) => Promise<Record<string, unknown>>;
resolveMessageGuidImpl?: IMessageSendOpts["resolveMessageGuidImpl"];
@@ -761,6 +762,7 @@ async function trySendAttachmentForTarget(params: {
"--file",
params.filePath,
...(params.audioAsVoice ? ["--audio"] : []),
...(params.replyToId ? ["--reply-to", params.replyToId] : []),
"--transport",
"auto",
]);
@@ -826,6 +828,7 @@ async function trySendAttachmentForTarget(params: {
messageId,
target: params.target,
kind: params.audioAsVoice ? "voice" : "media",
...(params.replyToId ? { replyToId: params.replyToId } : {}),
}),
};
}
@@ -908,7 +911,7 @@ export async function sendMessageIMessage(
opts.runCliJson ??
((args: readonly string[]) => runIMessageCliJson(cliPath, dbPath, args, timeoutMs));
if (filePath && !resolvedReplyToId) {
if (filePath && (!resolvedReplyToId || opts.audioAsVoice)) {
const attachmentEchoText = message.trim()
? resolveOutboundEchoText("", mediaContentType)
: echoText;
@@ -919,6 +922,7 @@ export async function sendMessageIMessage(
service,
filePath,
audioAsVoice: opts.audioAsVoice,
...(resolvedReplyToId ? { replyToId: resolvedReplyToId } : {}),
echoText: attachmentEchoText,
runCliJson,
resolveMessageGuidImpl: opts.resolveMessageGuidImpl,