mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-14 09:40:45 +08:00
feat: support image prompts across IM channels
This commit is contained in:
parent
99a877c640
commit
65c842c045
40 changed files with 3806 additions and 274 deletions
|
|
@ -207,6 +207,127 @@ test('WhatsApp normalizes direct and explicitly mentioned group messages', () =>
|
|||
}, ACCOUNT_JID), null);
|
||||
});
|
||||
|
||||
test('WhatsApp exposes image media through a bounded Baileys download stream', async () => {
|
||||
const png = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
||||
const calls = [];
|
||||
const controller = new AbortController();
|
||||
const group = normalizeWhatsappMessage({
|
||||
key: {
|
||||
remoteJid: '120363000000000000@g.us',
|
||||
participant: '16505550999@s.whatsapp.net',
|
||||
id: 'group-image-1',
|
||||
fromMe: false,
|
||||
},
|
||||
message: {
|
||||
imageMessage: {
|
||||
mimetype: 'image/png',
|
||||
caption: '看看这张图',
|
||||
fileLength: { toString: () => String(png.length) },
|
||||
url: 'https://mmg.whatsapp.net/image',
|
||||
contextInfo: { mentionedJid: [ACCOUNT_JID] },
|
||||
},
|
||||
},
|
||||
}, ACCOUNT_JID, {
|
||||
download: async (raw, type, options) => {
|
||||
calls.push({ raw, type, options });
|
||||
return {
|
||||
async *[Symbol.asyncIterator]() { yield png; },
|
||||
};
|
||||
},
|
||||
});
|
||||
assert.equal(group.addressed, true);
|
||||
assert.equal(group.content, '看看这张图');
|
||||
assert.equal(group.images.length, 1);
|
||||
assert.equal(group.images[0].size, png.length);
|
||||
assert.deepEqual(await group.images[0].load({ signal: controller.signal, maxBytes: 100 }), png);
|
||||
assert.equal(calls[0].type, 'stream');
|
||||
assert.equal(calls[0].options.options.signal instanceof AbortSignal, true);
|
||||
|
||||
const downloadStarted = Promise.withResolvers();
|
||||
const lateStream = Promise.withResolvers();
|
||||
let lateStreamDestroyed = false;
|
||||
const cancelled = normalizeWhatsappMessage({
|
||||
key: { remoteJid: '16505550999@s.whatsapp.net', id: 'cancelled-1', fromMe: false },
|
||||
message: {
|
||||
imageMessage: { mimetype: 'image/png', url: 'https://mmg.whatsapp.net/cancelled' },
|
||||
},
|
||||
}, ACCOUNT_JID, {
|
||||
download: async () => {
|
||||
downloadStarted.resolve();
|
||||
return lateStream.promise;
|
||||
},
|
||||
});
|
||||
const cancelledController = new AbortController();
|
||||
const cancelledLoad = cancelled.images[0].load({
|
||||
signal: cancelledController.signal,
|
||||
maxBytes: 100,
|
||||
});
|
||||
await downloadStarted.promise;
|
||||
cancelledController.abort(new DOMException('Stopped', 'AbortError'));
|
||||
await assert.rejects(cancelledLoad, { name: 'AbortError' });
|
||||
lateStream.resolve({ destroy() { lateStreamDestroyed = true; } });
|
||||
await new Promise((resolve) => setImmediate(resolve));
|
||||
assert.equal(lateStreamDestroyed, true);
|
||||
|
||||
const document = normalizeWhatsappMessage({
|
||||
key: { remoteJid: '16505550999@s.whatsapp.net', id: 'document-image-1', fromMe: false },
|
||||
message: {
|
||||
documentMessage: {
|
||||
mimetype: 'image/webp', fileName: 'diagram.webp', fileLength: 2_000,
|
||||
url: 'https://mmg.whatsapp.net/document',
|
||||
},
|
||||
},
|
||||
}, ACCOUNT_JID);
|
||||
assert.equal(document.images[0].name, 'diagram.webp');
|
||||
assert.equal(document.images[0].mediaType, 'image/webp');
|
||||
|
||||
for (const [index, wrapper] of [
|
||||
'viewOnceMessage',
|
||||
'viewOnceMessageV2',
|
||||
'viewOnceMessageV2Extension',
|
||||
].entries()) {
|
||||
const wrappedMessage = {
|
||||
[wrapper]: {
|
||||
message: {
|
||||
imageMessage: {
|
||||
mimetype: 'image/jpeg', url: `https://mmg.whatsapp.net/view-once-${index}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const viewOnce = normalizeWhatsappMessage({
|
||||
key: {
|
||||
remoteJid: '16505550999@s.whatsapp.net',
|
||||
id: `view-once-${index}`,
|
||||
fromMe: false,
|
||||
},
|
||||
message: index === 1
|
||||
? { ephemeralMessage: { message: wrappedMessage } }
|
||||
: wrappedMessage,
|
||||
}, ACCOUNT_JID);
|
||||
assert.deepEqual(viewOnce.images, []);
|
||||
}
|
||||
|
||||
const oversized = normalizeWhatsappMessage({
|
||||
key: { remoteJid: '16505550999@s.whatsapp.net', id: 'oversized-1', fromMe: false },
|
||||
message: {
|
||||
imageMessage: { mimetype: 'image/jpeg', url: 'https://mmg.whatsapp.net/oversized' },
|
||||
},
|
||||
}, ACCOUNT_JID, {
|
||||
download: async () => ({
|
||||
async *[Symbol.asyncIterator]() {
|
||||
yield Buffer.alloc(4);
|
||||
yield Buffer.alloc(4);
|
||||
},
|
||||
destroy() {},
|
||||
}),
|
||||
});
|
||||
await assert.rejects(() => oversized.images[0].load({ maxBytes: 5 }), (error) => {
|
||||
assert.equal(error.code, 'image-too-large');
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
test('WhatsApp runtime connects a linked device and replies through Harness', async () => {
|
||||
let callbacks;
|
||||
const calls = [];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue