@xmanrui/dsh-im 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +3 -3
- package/README.md +3 -3
- package/lib/index.js +168 -158
- package/package.json +1 -1
- package/src/channels/dingtalk/dingtalk-api.mjs +103 -81
- package/src/channels/dingtalk/dingtalk-bridge.mjs +34 -70
- package/src/channels/feishu/bridge.mjs +38 -57
- package/src/channels/feishu/feishu-channel.mjs +52 -17
- package/src/channels/qq/markdown-reply.mjs +176 -0
- package/src/channels/qq/qq-bridge.mjs +136 -105
- package/src/channels/shared/harness-client.mjs +66 -13
- package/src/channels/shared/semantic/artifact-delivery.mjs +170 -0
- package/src/channels/shared/semantic/artifact.mjs +2 -2
- package/src/channels/shared/semantic/delivery.mjs +2 -0
- package/src/channels/shared/text-harness-bridge.mjs +24 -73
- package/src/channels/telegram/telegram-api.mjs +39 -13
- package/src/channels/telegram/telegram-runtime.mjs +10 -0
- package/src/channels/wecom/wecom-bridge.mjs +95 -98
- package/src/channels/weixin/weixin-api.mjs +140 -107
- package/src/channels/weixin/weixin-bridge.mjs +36 -74
- package/src/channels/whatsapp/whatsapp-runtime.mjs +42 -9
|
@@ -457,6 +457,123 @@ function validateLoginResponse(value) {
|
|
|
457
457
|
export function createWeixinApi({ fetchImpl = fetch } = {}) {
|
|
458
458
|
if (typeof fetchImpl !== 'function') throw new TypeError('fetchImpl must be a function');
|
|
459
459
|
|
|
460
|
+
async function sendArtifact({
|
|
461
|
+
baseUrl,
|
|
462
|
+
token,
|
|
463
|
+
toUserId,
|
|
464
|
+
file,
|
|
465
|
+
contextToken,
|
|
466
|
+
runId,
|
|
467
|
+
signal,
|
|
468
|
+
}, { mediaType, createItem }) {
|
|
469
|
+
const recipient = nonEmptyString(toUserId);
|
|
470
|
+
if (!recipient || !file || typeof file !== 'object'
|
|
471
|
+
|| typeof file.fileName !== 'string' || !file.fileName
|
|
472
|
+
|| !Buffer.isBuffer(file.bytes)) {
|
|
473
|
+
throw new TypeError('toUserId and a file are required');
|
|
474
|
+
}
|
|
475
|
+
signal?.throwIfAborted();
|
|
476
|
+
const fileKey = randomBytes(16).toString('hex');
|
|
477
|
+
const aesKey = randomBytes(16);
|
|
478
|
+
const rawMd5 = createHash('md5').update(file.bytes).digest('hex');
|
|
479
|
+
let upload;
|
|
480
|
+
try {
|
|
481
|
+
upload = await requestJson(fetchImpl, {
|
|
482
|
+
method: 'POST',
|
|
483
|
+
baseUrl,
|
|
484
|
+
endpoint: 'ilink/bot/getuploadurl',
|
|
485
|
+
token,
|
|
486
|
+
signal,
|
|
487
|
+
body: {
|
|
488
|
+
filekey: fileKey,
|
|
489
|
+
media_type: mediaType,
|
|
490
|
+
to_user_id: recipient,
|
|
491
|
+
rawsize: file.bytes.byteLength,
|
|
492
|
+
rawfilemd5: rawMd5,
|
|
493
|
+
filesize: aesEcbPaddedSize(file.bytes.byteLength),
|
|
494
|
+
no_need_thumb: true,
|
|
495
|
+
aeskey: aesKey.toString('hex'),
|
|
496
|
+
base_info: baseInfo(),
|
|
497
|
+
},
|
|
498
|
+
});
|
|
499
|
+
} catch (error) {
|
|
500
|
+
if (signal?.aborted) throw abortError(signal);
|
|
501
|
+
const status = Number(error?.status);
|
|
502
|
+
const fallback = error?.code === 'http-error' && status >= 400 && status < 500
|
|
503
|
+
? 'artifact-provider-rejected'
|
|
504
|
+
: 'artifact-provider-failed';
|
|
505
|
+
throw weixinArtifactError(error, { fallback });
|
|
506
|
+
}
|
|
507
|
+
const uploadRejection = rejectedProviderResponse(upload);
|
|
508
|
+
if (uploadRejection) {
|
|
509
|
+
throw weixinArtifactError(new WeixinApiError(
|
|
510
|
+
'upload-url-rejected',
|
|
511
|
+
'微信服务拒绝了文件上传请求。',
|
|
512
|
+
{ providerCode: uploadRejection },
|
|
513
|
+
));
|
|
514
|
+
}
|
|
515
|
+
const uploadUrl = weixinCdnUploadUrl(upload, fileKey);
|
|
516
|
+
const ciphertext = encryptWeixinUpload(file.bytes, aesKey);
|
|
517
|
+
let downloadParam;
|
|
518
|
+
try {
|
|
519
|
+
downloadParam = await uploadWeixinCdn(fetchImpl, uploadUrl, ciphertext, { signal });
|
|
520
|
+
} catch (error) {
|
|
521
|
+
if (signal?.aborted) throw abortError(signal);
|
|
522
|
+
const status = Number(error?.status);
|
|
523
|
+
const fallback = error?.code === 'upload-rejected' || (status >= 400 && status < 500)
|
|
524
|
+
? 'artifact-provider-rejected'
|
|
525
|
+
: 'artifact-provider-failed';
|
|
526
|
+
throw weixinArtifactError(error, { fallback });
|
|
527
|
+
}
|
|
528
|
+
signal?.throwIfAborted();
|
|
529
|
+
const deliverySeed = nonEmptyString(file.deliveryKey) ?? nonEmptyString(file.artifactId)
|
|
530
|
+
?? randomUUID();
|
|
531
|
+
const clientIdSeed = mediaType === 3 ? deliverySeed : `${deliverySeed}\u0000${mediaType}`;
|
|
532
|
+
const clientId = `dsh-weixin-${createHash('sha256')
|
|
533
|
+
.update(clientIdSeed)
|
|
534
|
+
.digest('hex')
|
|
535
|
+
.slice(0, 32)}`;
|
|
536
|
+
const media = {
|
|
537
|
+
encrypt_query_param: downloadParam,
|
|
538
|
+
aes_key: Buffer.from(aesKey.toString('hex')).toString('base64'),
|
|
539
|
+
encrypt_type: 1,
|
|
540
|
+
};
|
|
541
|
+
let response;
|
|
542
|
+
try {
|
|
543
|
+
response = await requestJson(fetchImpl, {
|
|
544
|
+
method: 'POST',
|
|
545
|
+
baseUrl,
|
|
546
|
+
endpoint: 'ilink/bot/sendmessage',
|
|
547
|
+
token,
|
|
548
|
+
signal,
|
|
549
|
+
body: {
|
|
550
|
+
msg: {
|
|
551
|
+
from_user_id: '',
|
|
552
|
+
to_user_id: recipient,
|
|
553
|
+
client_id: clientId,
|
|
554
|
+
message_type: 2,
|
|
555
|
+
message_state: 2,
|
|
556
|
+
item_list: [createItem({ file, media, ciphertextSize: ciphertext.byteLength })],
|
|
557
|
+
...(nonEmptyString(contextToken) ? { context_token: contextToken.trim() } : {}),
|
|
558
|
+
...(nonEmptyString(runId) ? { run_id: runId.trim() } : {}),
|
|
559
|
+
},
|
|
560
|
+
base_info: baseInfo(),
|
|
561
|
+
},
|
|
562
|
+
});
|
|
563
|
+
} catch (error) {
|
|
564
|
+
throw classifyWeixinFinalDeliveryError(error, signal);
|
|
565
|
+
}
|
|
566
|
+
const sendRejection = rejectedProviderResponse(response);
|
|
567
|
+
if (sendRejection) {
|
|
568
|
+
throw weixinArtifactError(new WeixinApiError(
|
|
569
|
+
'send-rejected',
|
|
570
|
+
'微信服务拒绝了文件消息。',
|
|
571
|
+
{ providerCode: sendRejection },
|
|
572
|
+
));
|
|
573
|
+
}
|
|
574
|
+
return { messageId: clientId };
|
|
575
|
+
}
|
|
576
|
+
|
|
460
577
|
return Object.freeze({
|
|
461
578
|
inboundImages(message) {
|
|
462
579
|
return extractWeixinImages(message, { fetchImpl });
|
|
@@ -549,115 +666,31 @@ export function createWeixinApi({ fetchImpl = fetch } = {}) {
|
|
|
549
666
|
return true;
|
|
550
667
|
},
|
|
551
668
|
|
|
552
|
-
async sendFile(
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
const aesKey = randomBytes(16);
|
|
562
|
-
const rawMd5 = createHash('md5').update(file.bytes).digest('hex');
|
|
563
|
-
let upload;
|
|
564
|
-
try {
|
|
565
|
-
upload = await requestJson(fetchImpl, {
|
|
566
|
-
method: 'POST',
|
|
567
|
-
baseUrl,
|
|
568
|
-
endpoint: 'ilink/bot/getuploadurl',
|
|
569
|
-
token,
|
|
570
|
-
signal,
|
|
571
|
-
body: {
|
|
572
|
-
filekey: fileKey,
|
|
573
|
-
media_type: 3,
|
|
574
|
-
to_user_id: recipient,
|
|
575
|
-
rawsize: file.bytes.byteLength,
|
|
576
|
-
rawfilemd5: rawMd5,
|
|
577
|
-
filesize: aesEcbPaddedSize(file.bytes.byteLength),
|
|
578
|
-
no_need_thumb: true,
|
|
579
|
-
aeskey: aesKey.toString('hex'),
|
|
580
|
-
base_info: baseInfo(),
|
|
669
|
+
async sendFile(request) {
|
|
670
|
+
return sendArtifact(request, {
|
|
671
|
+
mediaType: 3,
|
|
672
|
+
createItem: ({ file, media }) => ({
|
|
673
|
+
type: 4,
|
|
674
|
+
file_item: {
|
|
675
|
+
media,
|
|
676
|
+
file_name: file.fileName,
|
|
677
|
+
len: String(file.bytes.byteLength),
|
|
581
678
|
},
|
|
582
|
-
})
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
'upload-url-rejected',
|
|
595
|
-
'微信服务拒绝了文件上传请求。',
|
|
596
|
-
{ providerCode: uploadRejection },
|
|
597
|
-
));
|
|
598
|
-
}
|
|
599
|
-
const uploadUrl = weixinCdnUploadUrl(upload, fileKey);
|
|
600
|
-
const ciphertext = encryptWeixinUpload(file.bytes, aesKey);
|
|
601
|
-
let downloadParam;
|
|
602
|
-
try {
|
|
603
|
-
downloadParam = await uploadWeixinCdn(fetchImpl, uploadUrl, ciphertext, { signal });
|
|
604
|
-
} catch (error) {
|
|
605
|
-
if (signal?.aborted) throw abortError(signal);
|
|
606
|
-
const status = Number(error?.status);
|
|
607
|
-
const fallback = error?.code === 'upload-rejected' || (status >= 400 && status < 500)
|
|
608
|
-
? 'artifact-provider-rejected'
|
|
609
|
-
: 'artifact-provider-failed';
|
|
610
|
-
throw weixinArtifactError(error, { fallback });
|
|
611
|
-
}
|
|
612
|
-
signal?.throwIfAborted();
|
|
613
|
-
const deliverySeed = nonEmptyString(file.deliveryKey) ?? nonEmptyString(file.artifactId)
|
|
614
|
-
?? randomUUID();
|
|
615
|
-
const clientId = `dsh-weixin-${createHash('sha256').update(deliverySeed).digest('hex').slice(0, 32)}`;
|
|
616
|
-
let response;
|
|
617
|
-
try {
|
|
618
|
-
response = await requestJson(fetchImpl, {
|
|
619
|
-
method: 'POST',
|
|
620
|
-
baseUrl,
|
|
621
|
-
endpoint: 'ilink/bot/sendmessage',
|
|
622
|
-
token,
|
|
623
|
-
signal,
|
|
624
|
-
body: {
|
|
625
|
-
msg: {
|
|
626
|
-
from_user_id: '',
|
|
627
|
-
to_user_id: recipient,
|
|
628
|
-
client_id: clientId,
|
|
629
|
-
message_type: 2,
|
|
630
|
-
message_state: 2,
|
|
631
|
-
item_list: [{
|
|
632
|
-
type: 4,
|
|
633
|
-
file_item: {
|
|
634
|
-
media: {
|
|
635
|
-
encrypt_query_param: downloadParam,
|
|
636
|
-
aes_key: Buffer.from(aesKey.toString('hex')).toString('base64'),
|
|
637
|
-
encrypt_type: 1,
|
|
638
|
-
},
|
|
639
|
-
file_name: file.fileName,
|
|
640
|
-
len: String(file.bytes.byteLength),
|
|
641
|
-
},
|
|
642
|
-
}],
|
|
643
|
-
...(nonEmptyString(contextToken) ? { context_token: contextToken.trim() } : {}),
|
|
644
|
-
...(nonEmptyString(runId) ? { run_id: runId.trim() } : {}),
|
|
645
|
-
},
|
|
646
|
-
base_info: baseInfo(),
|
|
679
|
+
}),
|
|
680
|
+
});
|
|
681
|
+
},
|
|
682
|
+
|
|
683
|
+
async sendImage(request) {
|
|
684
|
+
return sendArtifact(request, {
|
|
685
|
+
mediaType: 1,
|
|
686
|
+
createItem: ({ media, ciphertextSize }) => ({
|
|
687
|
+
type: 2,
|
|
688
|
+
image_item: {
|
|
689
|
+
media,
|
|
690
|
+
mid_size: ciphertextSize,
|
|
647
691
|
},
|
|
648
|
-
})
|
|
649
|
-
}
|
|
650
|
-
throw classifyWeixinFinalDeliveryError(error, signal);
|
|
651
|
-
}
|
|
652
|
-
const sendRejection = rejectedProviderResponse(response);
|
|
653
|
-
if (sendRejection) {
|
|
654
|
-
throw weixinArtifactError(new WeixinApiError(
|
|
655
|
-
'send-rejected',
|
|
656
|
-
'微信服务拒绝了文件消息。',
|
|
657
|
-
{ providerCode: sendRejection },
|
|
658
|
-
));
|
|
659
|
-
}
|
|
660
|
-
return { messageId: clientId };
|
|
692
|
+
}),
|
|
693
|
+
});
|
|
661
694
|
},
|
|
662
695
|
|
|
663
696
|
async notifyStart({ baseUrl, token, signal }) {
|
|
@@ -38,14 +38,9 @@ import {
|
|
|
38
38
|
prefetchInboundFiles,
|
|
39
39
|
} from '../shared/inbound-file.mjs';
|
|
40
40
|
import { rememberConnectionTestTarget } from '../shared/connection-test.mjs';
|
|
41
|
+
import { deliverOutboundArtifacts } from '../shared/semantic/artifact-delivery.mjs';
|
|
41
42
|
import {
|
|
42
|
-
materializeOutboundArtifact,
|
|
43
|
-
releaseOutboundArtifact,
|
|
44
|
-
} from '../shared/semantic/artifact.mjs';
|
|
45
|
-
import {
|
|
46
|
-
createArtifactFailureReceipt,
|
|
47
43
|
createDeliveryReceipt,
|
|
48
|
-
mergeDeliveryReceipts,
|
|
49
44
|
providerMessageIdsFor,
|
|
50
45
|
} from '../shared/semantic/delivery.mjs';
|
|
51
46
|
|
|
@@ -869,73 +864,40 @@ export class WeixinHarnessBridge {
|
|
|
869
864
|
}
|
|
870
865
|
|
|
871
866
|
async #deliverArtifacts(toUserId, replyTo, artifacts, contextToken, runId, baseReceipt) {
|
|
872
|
-
const
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
);
|
|
908
|
-
let noticeSent = false;
|
|
909
|
-
const providerMessageIds = await this.#send(
|
|
910
|
-
toUserId,
|
|
911
|
-
artifactFailureText(artifact?.fileName, error),
|
|
912
|
-
contextToken,
|
|
913
|
-
runId,
|
|
914
|
-
).then((ids) => {
|
|
915
|
-
noticeSent = true;
|
|
916
|
-
return ids;
|
|
917
|
-
}).catch(() => []);
|
|
918
|
-
const failureReceipt = createArtifactFailureReceipt({
|
|
919
|
-
artifactId: artifact?.artifactId ?? 'unknown',
|
|
920
|
-
deliveryId: artifact?.deliveryKey ?? artifact?.artifactId ?? 'unknown',
|
|
921
|
-
error,
|
|
922
|
-
providerMessageIds,
|
|
923
|
-
});
|
|
924
|
-
receipts.push(failureReceipt);
|
|
925
|
-
if (noticeSent || failureReceipt.artifacts[0]?.outcome === 'unknown') userVisible = true;
|
|
926
|
-
} finally {
|
|
927
|
-
releaseOutboundArtifact(artifact);
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
const receipt = receipts.length === 0
|
|
931
|
-
? null
|
|
932
|
-
: receipts.length === 1
|
|
933
|
-
? receipts[0]
|
|
934
|
-
: mergeDeliveryReceipts({
|
|
935
|
-
deliveryId: replyTo,
|
|
936
|
-
presentation: baseReceipt ? 'weixin-text-and-files' : 'weixin-files',
|
|
937
|
-
receipts,
|
|
938
|
-
});
|
|
939
|
-
return { receipt, userVisible };
|
|
867
|
+
const sendArtifact = (method, file) => this.#api[method]({
|
|
868
|
+
baseUrl: this.#baseUrl,
|
|
869
|
+
token: this.#token,
|
|
870
|
+
toUserId,
|
|
871
|
+
file,
|
|
872
|
+
contextToken,
|
|
873
|
+
runId,
|
|
874
|
+
signal: this.#signal,
|
|
875
|
+
});
|
|
876
|
+
const delivery = await deliverOutboundArtifacts({
|
|
877
|
+
artifacts,
|
|
878
|
+
baseReceipt,
|
|
879
|
+
deliveryId: replyTo,
|
|
880
|
+
aggregatePresentation: baseReceipt ? 'weixin-text-and-files' : 'weixin-files',
|
|
881
|
+
channelKey: 'weixin',
|
|
882
|
+
signal: this.#signal,
|
|
883
|
+
sendImage: typeof this.#api.sendImage === 'function'
|
|
884
|
+
? (file) => sendArtifact('sendImage', file)
|
|
885
|
+
: undefined,
|
|
886
|
+
sendFile: typeof this.#api.sendFile === 'function'
|
|
887
|
+
? (file) => sendArtifact('sendFile', file)
|
|
888
|
+
: undefined,
|
|
889
|
+
sendFailureNotice: (artifact, error) => this.#send(
|
|
890
|
+
toUserId,
|
|
891
|
+
artifactFailureText(artifact?.fileName, error),
|
|
892
|
+
contextToken,
|
|
893
|
+
runId,
|
|
894
|
+
),
|
|
895
|
+
logger: this.#logger,
|
|
896
|
+
});
|
|
897
|
+
this.#status.artifactsSent = (this.#status.artifactsSent ?? 0)
|
|
898
|
+
+ delivery.artifactsSent;
|
|
899
|
+
this.#status.artifactSendErrors = (this.#status.artifactSendErrors ?? 0)
|
|
900
|
+
+ delivery.artifactSendErrors;
|
|
901
|
+
return { receipt: delivery.receipt, userVisible: delivery.userVisible };
|
|
940
902
|
}
|
|
941
903
|
}
|
|
@@ -313,12 +313,31 @@ function waitWithSignal(promise, signal) {
|
|
|
313
313
|
|
|
314
314
|
function uncertainArtifactDelivery(error) {
|
|
315
315
|
if (error?.code === 'artifact-delivery-uncertain') return error;
|
|
316
|
-
const uncertain = new Error('WhatsApp could not confirm
|
|
316
|
+
const uncertain = new Error('WhatsApp could not confirm artifact delivery.');
|
|
317
317
|
uncertain.code = 'artifact-delivery-uncertain';
|
|
318
318
|
uncertain.cause = error;
|
|
319
319
|
return uncertain;
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
+
function whatsappArtifactError(error) {
|
|
323
|
+
if (error?.code?.startsWith?.('artifact-')) return error;
|
|
324
|
+
const status = error?.output?.statusCode
|
|
325
|
+
?? error?.data?.statusCode
|
|
326
|
+
?? error?.statusCode;
|
|
327
|
+
let code;
|
|
328
|
+
if (status === 401 || status === 403) code = 'artifact-permission-required';
|
|
329
|
+
else if (status === 413) code = 'artifact-too-large';
|
|
330
|
+
else if (status === 429) code = 'artifact-rate-limited';
|
|
331
|
+
else if ([400, 404, 405, 406, 410, 415, 422].includes(status)) {
|
|
332
|
+
code = 'artifact-provider-rejected';
|
|
333
|
+
}
|
|
334
|
+
if (!code) return uncertainArtifactDelivery(error);
|
|
335
|
+
const wrapped = new Error('WhatsApp rejected artifact delivery.');
|
|
336
|
+
wrapped.code = code;
|
|
337
|
+
wrapped.cause = error;
|
|
338
|
+
return wrapped;
|
|
339
|
+
}
|
|
340
|
+
|
|
322
341
|
export class WhatsappBotClient {
|
|
323
342
|
#socket;
|
|
324
343
|
#outboundIds;
|
|
@@ -354,14 +373,32 @@ export class WhatsappBotClient {
|
|
|
354
373
|
}
|
|
355
374
|
|
|
356
375
|
async sendFile(target, file) {
|
|
376
|
+
return this.#sendArtifact(target, file, {
|
|
377
|
+
document: file.bytes,
|
|
378
|
+
mimetype: file.mediaType ?? 'application/octet-stream',
|
|
379
|
+
fileName: file.fileName,
|
|
380
|
+
}, 'file');
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async sendImage(target, file) {
|
|
384
|
+
return this.#sendArtifact(target, file, {
|
|
385
|
+
image: file.bytes,
|
|
386
|
+
mimetype: file.mediaType ?? 'image/jpeg',
|
|
387
|
+
}, 'image');
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
async #sendArtifact(target, file, content, presentation) {
|
|
357
391
|
this.#signal?.throwIfAborted();
|
|
358
392
|
await this.#stopTyping(target.jid);
|
|
359
393
|
this.#signal?.throwIfAborted();
|
|
360
394
|
const deliverySeed = typeof file.deliveryKey === 'string' && file.deliveryKey
|
|
361
395
|
? file.deliveryKey
|
|
362
396
|
: file.artifactId;
|
|
363
|
-
const
|
|
364
|
-
?
|
|
397
|
+
const messageIdSeed = presentation === 'image'
|
|
398
|
+
? `${deliverySeed}:image`
|
|
399
|
+
: deliverySeed;
|
|
400
|
+
const messageId = typeof messageIdSeed === 'string' && messageIdSeed
|
|
401
|
+
? createHash('sha256').update(messageIdSeed).digest('hex').slice(0, 20).toUpperCase()
|
|
365
402
|
: undefined;
|
|
366
403
|
const options = {
|
|
367
404
|
...(target.quoted ? { quoted: target.quoted } : {}),
|
|
@@ -375,11 +412,7 @@ export class WhatsappBotClient {
|
|
|
375
412
|
try {
|
|
376
413
|
const pending = this.#socket.sendMessage(
|
|
377
414
|
target.jid,
|
|
378
|
-
|
|
379
|
-
document: file.bytes,
|
|
380
|
-
mimetype: file.mediaType ?? 'application/octet-stream',
|
|
381
|
-
fileName: file.fileName,
|
|
382
|
-
},
|
|
415
|
+
content,
|
|
383
416
|
options,
|
|
384
417
|
);
|
|
385
418
|
trackOutboundArtifactProviderPromise(file, pending);
|
|
@@ -390,7 +423,7 @@ export class WhatsappBotClient {
|
|
|
390
423
|
result = await waitWithSignal(pending, waitSignal);
|
|
391
424
|
} catch (error) {
|
|
392
425
|
if (this.#signal?.aborted) throw abortReason(this.#signal);
|
|
393
|
-
throw
|
|
426
|
+
throw whatsappArtifactError(error);
|
|
394
427
|
}
|
|
395
428
|
this.#signal?.throwIfAborted();
|
|
396
429
|
this.#outboundIds.remember(result?.key?.id);
|