koishi-plugin-forward-hime 1.4.2-alpha.1 → 1.4.3
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/decorator.d.ts +2 -2
- package/lib/index.js +82 -15
- package/lib/relay.d.ts +2 -2
- package/package.json +1 -1
package/lib/decorator.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Session, Element } from "koishi";
|
|
1
|
+
import { Context, Session, Element } from "koishi";
|
|
2
2
|
import { ConfigSet, ForwardNode } from "./config";
|
|
3
3
|
interface ForwardMsg {
|
|
4
4
|
head: Element[];
|
|
5
5
|
content: Element[];
|
|
6
6
|
}
|
|
7
|
-
export declare function decoratorInit(cfg: ConfigSet): void;
|
|
7
|
+
export declare function decoratorInit(ctx: Context, cfg: ConfigSet): void;
|
|
8
8
|
export declare function defaultDecorator({ head, content }: ForwardMsg): Element[];
|
|
9
9
|
export declare function defaultMiddleware(session: Session): ForwardMsg;
|
|
10
10
|
export declare function MsgMiddlewareCache(session: Session): Promise<void>;
|
package/lib/index.js
CHANGED
|
@@ -362,8 +362,21 @@ var MediaRelayError = class extends Error {
|
|
|
362
362
|
this.userMessage = userMessage;
|
|
363
363
|
}
|
|
364
364
|
};
|
|
365
|
-
function relayInit(cfg) {
|
|
365
|
+
function relayInit(ctx2, cfg) {
|
|
366
366
|
relayConfig = cfg.MediaRelay;
|
|
367
|
+
ctx2.on("http/file", (url, options) => {
|
|
368
|
+
const { filename, file } = options;
|
|
369
|
+
if (typeof filename !== "string" || file !== filename) return;
|
|
370
|
+
const match = /^data:([\w.+/-]+);base64,(.*)$/.exec(url);
|
|
371
|
+
if (match) {
|
|
372
|
+
return {
|
|
373
|
+
data: Buffer.from(match[2], "base64"),
|
|
374
|
+
type: match[1],
|
|
375
|
+
mime: match[1],
|
|
376
|
+
filename
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
});
|
|
367
380
|
}
|
|
368
381
|
function cleanupExpiredRelayCache() {
|
|
369
382
|
const now = Date.now();
|
|
@@ -425,16 +438,26 @@ function getCacheKey(element) {
|
|
|
425
438
|
const src = mediaUrlFromElement(element);
|
|
426
439
|
return `${mediaType}:${src}`;
|
|
427
440
|
}
|
|
428
|
-
function relayElementFromCache(item) {
|
|
429
|
-
return createRelayElement(
|
|
441
|
+
function relayElementFromCache(item, targetPlatform) {
|
|
442
|
+
return createRelayElement(
|
|
443
|
+
item.kind,
|
|
444
|
+
item.mime,
|
|
445
|
+
item.buffer,
|
|
446
|
+
item.filename,
|
|
447
|
+
targetPlatform
|
|
448
|
+
);
|
|
430
449
|
}
|
|
431
|
-
function createRelayElement(kind, mime, buffer, filename) {
|
|
450
|
+
function createRelayElement(kind, mime, buffer, filename, targetPlatform) {
|
|
432
451
|
const helperMap = import_koishi5.h;
|
|
433
452
|
if (kind === "img") {
|
|
434
453
|
return import_koishi5.h.image(buffer, mime);
|
|
435
454
|
}
|
|
455
|
+
if (kind === "audio") {
|
|
456
|
+
return import_koishi5.h.audio(buffer, mime, { file: filename });
|
|
457
|
+
}
|
|
436
458
|
if (kind === "file") {
|
|
437
|
-
|
|
459
|
+
const attrs = { file: filename, filename, title: filename };
|
|
460
|
+
return targetPlatform === "discord" ? import_koishi5.h.image(buffer, mime, attrs) : helperMap.file(buffer, mime, attrs);
|
|
438
461
|
}
|
|
439
462
|
if (helperMap[kind]) {
|
|
440
463
|
return helperMap[kind](buffer, mime);
|
|
@@ -495,7 +518,7 @@ async function downloadAndRelay(element, traceId, session, node) {
|
|
|
495
518
|
...context
|
|
496
519
|
});
|
|
497
520
|
}
|
|
498
|
-
return relayElementFromCache(cacheItem);
|
|
521
|
+
return relayElementFromCache(cacheItem, node?.Platform);
|
|
499
522
|
}
|
|
500
523
|
const timeoutSignal = typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(relayConfig.RequestTimeoutSec * 1e3) : void 0;
|
|
501
524
|
const response = await fetch(src, { signal: timeoutSignal });
|
|
@@ -546,9 +569,9 @@ async function downloadAndRelay(element, traceId, session, node) {
|
|
|
546
569
|
`\u5A92\u4F53\u6587\u4EF6\u8FC7\u5927\uFF08>${relayConfig.MaxFileSizeMB} MB\uFF09\uFF0C\u65E0\u6CD5\u4E2D\u8F6C\u53D1\u9001\u3002`
|
|
547
570
|
);
|
|
548
571
|
}
|
|
549
|
-
const mime = response.headers.get("content-type") || pickDefaultMime(kind);
|
|
550
|
-
const filename = kind === "file" ? pickFilename(element, src) : void 0;
|
|
551
|
-
const relayed = createRelayElement(kind, mime, buffer, filename);
|
|
572
|
+
const mime = response.headers.get("content-type")?.split(";")[0].trim() || pickDefaultMime(kind);
|
|
573
|
+
const filename = kind === "file" || kind === "audio" ? pickFilename(element, src) : void 0;
|
|
574
|
+
const relayed = createRelayElement(kind, mime, buffer, filename, node?.Platform);
|
|
552
575
|
relayCache.set(cacheKey, {
|
|
553
576
|
expiresAt: Date.now() + relayConfig.CacheMinutes * 60 * 1e3,
|
|
554
577
|
kind,
|
|
@@ -608,9 +631,15 @@ async function relayForwardContent(content, traceId, session, node) {
|
|
|
608
631
|
}
|
|
609
632
|
|
|
610
633
|
// src/message.ts
|
|
634
|
+
var DeliveryUncertainError = class extends Error {
|
|
635
|
+
constructor(cause) {
|
|
636
|
+
super("message delivery status unknown", { cause });
|
|
637
|
+
}
|
|
638
|
+
};
|
|
611
639
|
async function MessageSendWithDecorator(ctx2, node, session, Deco, traceId, attempt) {
|
|
612
640
|
const startedAt = Date.now();
|
|
613
641
|
const uuid = session.channelId + ":" + session.messageId;
|
|
642
|
+
let submitted = false;
|
|
614
643
|
writeDiagnostic({
|
|
615
644
|
traceId,
|
|
616
645
|
phase: "send-attempt",
|
|
@@ -621,6 +650,7 @@ async function MessageSendWithDecorator(ctx2, node, session, Deco, traceId, atte
|
|
|
621
650
|
});
|
|
622
651
|
try {
|
|
623
652
|
const content = await Deco(session, node, traceId);
|
|
653
|
+
submitted = true;
|
|
624
654
|
const res = await ctx2.bots[`${node.Platform}:${node.BotID}`].sendMessage(
|
|
625
655
|
node.Guild,
|
|
626
656
|
content
|
|
@@ -663,7 +693,7 @@ async function MessageSendWithDecorator(ctx2, node, session, Deco, traceId, atte
|
|
|
663
693
|
logger.error(
|
|
664
694
|
`ERROR:<MessageSendWithDecorator ${node.Platform}> ctx=${ctx2} ${error}`
|
|
665
695
|
);
|
|
666
|
-
throw error;
|
|
696
|
+
throw submitted ? new DeliveryUncertainError(error) : error;
|
|
667
697
|
}
|
|
668
698
|
}
|
|
669
699
|
function sessionTypeArray(session) {
|
|
@@ -748,6 +778,10 @@ async function MessageForward(ctx2, node, session, timeoutSec, relayEnabled) {
|
|
|
748
778
|
logger.error(
|
|
749
779
|
`ERROR:<MessageSend ${node.Platform}> ctx=${ctx2} ${sessionTypeArray(session)} ${firstError}`
|
|
750
780
|
);
|
|
781
|
+
if (firstError instanceof DeliveryUncertainError) {
|
|
782
|
+
writeDiagnostic({ traceId, phase: "forward-uncertain", source, target });
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
751
785
|
if (relayEnabled !== false && firstError instanceof MediaRelayError) {
|
|
752
786
|
logger.info(
|
|
753
787
|
`[MessageForward] relay failed, retrying without relay: ${node.Platform}`
|
|
@@ -765,6 +799,15 @@ async function MessageForward(ctx2, node, session, timeoutSec, relayEnabled) {
|
|
|
765
799
|
logger.error(
|
|
766
800
|
`ERROR:<MessageSendDirect ${node.Platform}> ctx=${ctx2} ${sessionTypeArray(session)} ${secondError}`
|
|
767
801
|
);
|
|
802
|
+
if (secondError instanceof DeliveryUncertainError) {
|
|
803
|
+
writeDiagnostic({
|
|
804
|
+
traceId,
|
|
805
|
+
phase: "forward-uncertain",
|
|
806
|
+
source,
|
|
807
|
+
target
|
|
808
|
+
});
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
768
811
|
sendDegraded(reasonFromError(secondError));
|
|
769
812
|
});
|
|
770
813
|
} else {
|
|
@@ -795,11 +838,11 @@ function MsgUUIDFromSession(session) {
|
|
|
795
838
|
var defaultPrefix = "";
|
|
796
839
|
var defaultFallback = "";
|
|
797
840
|
var defaultPrefixNewline = true;
|
|
798
|
-
function decoratorInit(cfg) {
|
|
841
|
+
function decoratorInit(ctx2, cfg) {
|
|
799
842
|
defaultPrefix = cfg.DefaultDecorator.Prefix;
|
|
800
843
|
defaultPrefixNewline = cfg.DefaultDecorator.Newline;
|
|
801
844
|
defaultFallback = cfg.DefaultFallbackMsgPrefix;
|
|
802
|
-
relayInit(cfg);
|
|
845
|
+
relayInit(ctx2, cfg);
|
|
803
846
|
}
|
|
804
847
|
function renderTemplate(template, data) {
|
|
805
848
|
return template.replace(/\$\{(\w+)\}/g, (_, key) => {
|
|
@@ -816,7 +859,10 @@ function defaultMiddleware(session) {
|
|
|
816
859
|
if (defaultPrefixNewline) {
|
|
817
860
|
head.push((0, import_koishi6.h)("br"));
|
|
818
861
|
}
|
|
819
|
-
|
|
862
|
+
const content = session.platform === "discord" ? session.elements.map(
|
|
863
|
+
(element) => element.type === "record" ? (0, import_koishi6.h)("audio", element.attrs, element.children) : element
|
|
864
|
+
) : session.elements;
|
|
865
|
+
return { head, content };
|
|
820
866
|
}
|
|
821
867
|
var localDecorators = [atTranslator, quoteTranslator];
|
|
822
868
|
var msgMiddleCache = [];
|
|
@@ -842,6 +888,19 @@ function MsgToMiddleware(session) {
|
|
|
842
888
|
}
|
|
843
889
|
return defaultMiddleware(session);
|
|
844
890
|
}
|
|
891
|
+
function discordAudioAttachments(session, node, content) {
|
|
892
|
+
if (session.platform !== "onebot" || node.Platform !== "discord") {
|
|
893
|
+
return content;
|
|
894
|
+
}
|
|
895
|
+
return content.map((element) => {
|
|
896
|
+
if (element.type !== "audio") return element;
|
|
897
|
+
const src = element.attrs.src || element.attrs.url;
|
|
898
|
+
if (typeof src !== "string") return element;
|
|
899
|
+
const name2 = element.attrs.filename || element.attrs.file;
|
|
900
|
+
const filename = typeof name2 === "string" && /^[^/\\:]+\.[a-z\d]+$/i.test(name2) ? name2 : "voice.bin";
|
|
901
|
+
return import_koishi6.h.image(src, { file: filename, mode: "download" });
|
|
902
|
+
});
|
|
903
|
+
}
|
|
845
904
|
async function MsgMiddlewareCache(session) {
|
|
846
905
|
const elems = MsgToMiddleware(session);
|
|
847
906
|
msgMiddleCacheAppend({ UUID: MsgUUIDFromSession(session), msg: elems });
|
|
@@ -863,7 +922,11 @@ async function MsgDecorator(session, node, traceId) {
|
|
|
863
922
|
}
|
|
864
923
|
elems = {
|
|
865
924
|
head: elems.head,
|
|
866
|
-
content:
|
|
925
|
+
content: discordAudioAttachments(
|
|
926
|
+
session,
|
|
927
|
+
node,
|
|
928
|
+
await relayForwardContent(elems.content, traceId, session, node)
|
|
929
|
+
)
|
|
867
930
|
};
|
|
868
931
|
if (_platform_out && typeof _platform_out.Decorator === "function") {
|
|
869
932
|
return _platform_out.Decorator(elems);
|
|
@@ -884,6 +947,10 @@ async function MsgDecoratorNoRelay(session, node) {
|
|
|
884
947
|
elems = await fn(session, node, elems);
|
|
885
948
|
}
|
|
886
949
|
logger.debug(`[MsgDecoratorNoRelay] fallback to direct forward`);
|
|
950
|
+
elems = {
|
|
951
|
+
head: elems.head,
|
|
952
|
+
content: discordAudioAttachments(session, node, elems.content)
|
|
953
|
+
};
|
|
887
954
|
if (_platform_out && typeof _platform_out.Decorator === "function") {
|
|
888
955
|
return _platform_out.Decorator(elems);
|
|
889
956
|
} else {
|
|
@@ -993,7 +1060,7 @@ function apply(ctx2, cfg) {
|
|
|
993
1060
|
diagnosticsInit(ctx2);
|
|
994
1061
|
consoleInit(ctx2);
|
|
995
1062
|
msgCacheInit(ctx2, cfg);
|
|
996
|
-
decoratorInit(cfg);
|
|
1063
|
+
decoratorInit(ctx2, cfg);
|
|
997
1064
|
ctx2.on("message-created", async (session) => {
|
|
998
1065
|
const hitGroup = [];
|
|
999
1066
|
for (const g in cfg.ForwardGroups) {
|
package/lib/relay.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Element } from "koishi";
|
|
1
|
+
import { Context, Element } from "koishi";
|
|
2
2
|
import { ConfigSet } from "./config";
|
|
3
3
|
import { Session } from "koishi";
|
|
4
4
|
import { ForwardNode } from "./config";
|
|
@@ -6,5 +6,5 @@ export declare class MediaRelayError extends Error {
|
|
|
6
6
|
userMessage: string;
|
|
7
7
|
constructor(message: string, userMessage: string);
|
|
8
8
|
}
|
|
9
|
-
export declare function relayInit(cfg: ConfigSet): void;
|
|
9
|
+
export declare function relayInit(ctx: Context, cfg: ConfigSet): void;
|
|
10
10
|
export declare function relayForwardContent(content: Element[], traceId?: string, session?: Session, node?: ForwardNode): Promise<Element[]>;
|