koishi-plugin-forward-hime 1.4.2-alpha.2 → 1.4.4-alpha.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/lib/index.js +56 -5
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -411,12 +411,23 @@ function pickDefaultMime(kind) {
|
|
|
411
411
|
return DEFAULT_IMAGE_MIME;
|
|
412
412
|
case "audio":
|
|
413
413
|
return DEFAULT_AUDIO_MIME;
|
|
414
|
-
case "video":
|
|
415
|
-
return DEFAULT_VIDEO_MIME;
|
|
416
414
|
default:
|
|
417
415
|
return DEFAULT_FILE_MIME;
|
|
418
416
|
}
|
|
419
417
|
}
|
|
418
|
+
function detectVideoMime(buffer) {
|
|
419
|
+
if (buffer.toString("ascii", 4, 8) === "ftyp") {
|
|
420
|
+
return buffer.toString("ascii", 8, 12) === "qt " ? "video/quicktime" : DEFAULT_VIDEO_MIME;
|
|
421
|
+
}
|
|
422
|
+
if (buffer.subarray(0, 4).equals(Buffer.from([26, 69, 223, 163]))) {
|
|
423
|
+
const header = buffer.toString("ascii", 0, 64);
|
|
424
|
+
if (header.includes("webm")) return "video/webm";
|
|
425
|
+
if (header.includes("matroska")) return "video/x-matroska";
|
|
426
|
+
}
|
|
427
|
+
if (buffer.toString("ascii", 0, 4) === "RIFF" && buffer.toString("ascii", 8, 12) === "AVI ") {
|
|
428
|
+
return "video/x-msvideo";
|
|
429
|
+
}
|
|
430
|
+
}
|
|
420
431
|
function pickFilename(element, src) {
|
|
421
432
|
const nameAttrs = ["filename", "name", "title", "file"];
|
|
422
433
|
for (const key of nameAttrs) {
|
|
@@ -433,6 +444,18 @@ function pickFilename(element, src) {
|
|
|
433
444
|
return "relay-file";
|
|
434
445
|
}
|
|
435
446
|
}
|
|
447
|
+
function pickVideoFilename(element, src, mime) {
|
|
448
|
+
const filename = pickFilename(element, src);
|
|
449
|
+
if (/^[^/\\:]+\.(mp4|mov|webm|mkv|avi)$/i.test(filename)) return filename;
|
|
450
|
+
const extensions = {
|
|
451
|
+
"video/mp4": "mp4",
|
|
452
|
+
"video/quicktime": "mov",
|
|
453
|
+
"video/webm": "webm",
|
|
454
|
+
"video/x-matroska": "mkv",
|
|
455
|
+
"video/x-msvideo": "avi"
|
|
456
|
+
};
|
|
457
|
+
return `video.${extensions[mime] || "bin"}`;
|
|
458
|
+
}
|
|
436
459
|
function getCacheKey(element) {
|
|
437
460
|
const mediaType = normalizeMediaType(element.type);
|
|
438
461
|
const src = mediaUrlFromElement(element);
|
|
@@ -459,6 +482,13 @@ function createRelayElement(kind, mime, buffer, filename, targetPlatform) {
|
|
|
459
482
|
const attrs = { file: filename, filename, title: filename };
|
|
460
483
|
return targetPlatform === "discord" ? import_koishi5.h.image(buffer, mime, attrs) : helperMap.file(buffer, mime, attrs);
|
|
461
484
|
}
|
|
485
|
+
if (kind === "video" && targetPlatform === "discord") {
|
|
486
|
+
return import_koishi5.h.image(buffer, mime, {
|
|
487
|
+
file: filename,
|
|
488
|
+
filename,
|
|
489
|
+
mode: "download"
|
|
490
|
+
});
|
|
491
|
+
}
|
|
462
492
|
if (helperMap[kind]) {
|
|
463
493
|
return helperMap[kind](buffer, mime);
|
|
464
494
|
}
|
|
@@ -569,8 +599,9 @@ async function downloadAndRelay(element, traceId, session, node) {
|
|
|
569
599
|
`\u5A92\u4F53\u6587\u4EF6\u8FC7\u5927\uFF08>${relayConfig.MaxFileSizeMB} MB\uFF09\uFF0C\u65E0\u6CD5\u4E2D\u8F6C\u53D1\u9001\u3002`
|
|
570
600
|
);
|
|
571
601
|
}
|
|
572
|
-
const
|
|
573
|
-
const
|
|
602
|
+
const responseMime = response.headers.get("content-type")?.split(";")[0].trim();
|
|
603
|
+
const mime = kind === "video" && (!responseMime || responseMime === DEFAULT_FILE_MIME) ? detectVideoMime(buffer) || DEFAULT_FILE_MIME : responseMime || pickDefaultMime(kind);
|
|
604
|
+
const filename = kind === "video" ? pickVideoFilename(element, src, mime) : kind === "file" || kind === "audio" ? pickFilename(element, src) : void 0;
|
|
574
605
|
const relayed = createRelayElement(kind, mime, buffer, filename, node?.Platform);
|
|
575
606
|
relayCache.set(cacheKey, {
|
|
576
607
|
expiresAt: Date.now() + relayConfig.CacheMinutes * 60 * 1e3,
|
|
@@ -631,9 +662,15 @@ async function relayForwardContent(content, traceId, session, node) {
|
|
|
631
662
|
}
|
|
632
663
|
|
|
633
664
|
// src/message.ts
|
|
665
|
+
var DeliveryUncertainError = class extends Error {
|
|
666
|
+
constructor(cause) {
|
|
667
|
+
super("message delivery status unknown", { cause });
|
|
668
|
+
}
|
|
669
|
+
};
|
|
634
670
|
async function MessageSendWithDecorator(ctx2, node, session, Deco, traceId, attempt) {
|
|
635
671
|
const startedAt = Date.now();
|
|
636
672
|
const uuid = session.channelId + ":" + session.messageId;
|
|
673
|
+
let submitted = false;
|
|
637
674
|
writeDiagnostic({
|
|
638
675
|
traceId,
|
|
639
676
|
phase: "send-attempt",
|
|
@@ -644,6 +681,7 @@ async function MessageSendWithDecorator(ctx2, node, session, Deco, traceId, atte
|
|
|
644
681
|
});
|
|
645
682
|
try {
|
|
646
683
|
const content = await Deco(session, node, traceId);
|
|
684
|
+
submitted = true;
|
|
647
685
|
const res = await ctx2.bots[`${node.Platform}:${node.BotID}`].sendMessage(
|
|
648
686
|
node.Guild,
|
|
649
687
|
content
|
|
@@ -686,7 +724,7 @@ async function MessageSendWithDecorator(ctx2, node, session, Deco, traceId, atte
|
|
|
686
724
|
logger.error(
|
|
687
725
|
`ERROR:<MessageSendWithDecorator ${node.Platform}> ctx=${ctx2} ${error}`
|
|
688
726
|
);
|
|
689
|
-
throw error;
|
|
727
|
+
throw submitted ? new DeliveryUncertainError(error) : error;
|
|
690
728
|
}
|
|
691
729
|
}
|
|
692
730
|
function sessionTypeArray(session) {
|
|
@@ -771,6 +809,10 @@ async function MessageForward(ctx2, node, session, timeoutSec, relayEnabled) {
|
|
|
771
809
|
logger.error(
|
|
772
810
|
`ERROR:<MessageSend ${node.Platform}> ctx=${ctx2} ${sessionTypeArray(session)} ${firstError}`
|
|
773
811
|
);
|
|
812
|
+
if (firstError instanceof DeliveryUncertainError) {
|
|
813
|
+
writeDiagnostic({ traceId, phase: "forward-uncertain", source, target });
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
774
816
|
if (relayEnabled !== false && firstError instanceof MediaRelayError) {
|
|
775
817
|
logger.info(
|
|
776
818
|
`[MessageForward] relay failed, retrying without relay: ${node.Platform}`
|
|
@@ -788,6 +830,15 @@ async function MessageForward(ctx2, node, session, timeoutSec, relayEnabled) {
|
|
|
788
830
|
logger.error(
|
|
789
831
|
`ERROR:<MessageSendDirect ${node.Platform}> ctx=${ctx2} ${sessionTypeArray(session)} ${secondError}`
|
|
790
832
|
);
|
|
833
|
+
if (secondError instanceof DeliveryUncertainError) {
|
|
834
|
+
writeDiagnostic({
|
|
835
|
+
traceId,
|
|
836
|
+
phase: "forward-uncertain",
|
|
837
|
+
source,
|
|
838
|
+
target
|
|
839
|
+
});
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
791
842
|
sendDegraded(reasonFromError(secondError));
|
|
792
843
|
});
|
|
793
844
|
} else {
|