koishi-plugin-chat-patch 5.5.0 → 5.6.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/client/vue/index.vue +8 -1
- package/client/web/dist/assets/{Chat-DTEsebnY.css → Chat-BXVWj5Bd.css} +1 -1
- package/client/web/dist/assets/{Chat-Clqxn7CB.js → Chat-m4-U5uHa.js} +4 -4
- package/client/web/dist/assets/{MsgBody-C0TKsXhC.js → MsgBody-CzrxyiFO.js} +1 -1
- package/client/web/dist/assets/MsgBody.vue_vue_type_script_setup_true_lang-BBF1uxm6.js +67 -0
- package/client/web/dist/assets/{index-BA37EQGa.js → index-EJ2CcODr.js} +72 -78
- package/client/web/dist/assets/index-X9hFOAza.css +1 -0
- package/client/web/dist/index.html +2 -2
- package/client/web/src/App.vue +7 -0
- package/client/web/src/assets/css/chat.css +6 -4
- package/client/web/src/assets/l10n/zh-CN.po +0 -6
- package/client/web/src/components/History.vue +27 -0
- package/client/web/src/components/MsgBody.vue +18 -9
- package/client/web/src/function/connect.ts +208 -46
- package/client/web/src/function/msg.ts +8 -6
- package/client/web/src/function/option.ts +1 -1
- package/client/web/src/function/satori-model.ts +20 -2
- package/client/web/src/function/satori.ts +64 -0
- package/client/web/src/pages/Chat.vue +0 -4
- package/client/web/src/pages/Friends.vue +7 -9
- package/client/web/src/pages/Messages.vue +6 -7
- package/client/web/src/pages/options/OptDev.vue +1 -25
- package/client/web/src/pages/options/OptFunction.vue +23 -0
- package/client/web/tsconfig.tsbuildinfo +1 -1
- package/dist/index.js +1 -1
- package/dist/style.css +1 -1
- package/lib/bootstrap.d.ts +6 -0
- package/lib/database.d.ts +5 -2
- package/lib/gateway.d.ts +46 -0
- package/lib/index.js +1468 -131
- package/lib/recorder.d.ts +3 -5
- package/lib/satori.d.ts +3 -0
- package/lib/types.d.ts +17 -0
- package/package.json +4 -1
- package/src/bootstrap.ts +5 -10
- package/src/database.ts +745 -662
- package/src/gateway.ts +259 -0
- package/src/index.ts +63 -53
- package/src/recorder.ts +97 -77
- package/src/satori.ts +19 -0
- package/src/server.d.ts +26 -26
- package/src/types.ts +19 -0
- package/client/web/dist/assets/MsgBody.vue_vue_type_script_setup_true_lang-CCdBwlN_.js +0 -67
- package/client/web/dist/assets/index-B71pPwae.css +0 -1
package/lib/index.js
CHANGED
|
@@ -365,25 +365,93 @@ function isUsableGroupContact(item) {
|
|
|
365
365
|
return true;
|
|
366
366
|
}
|
|
367
367
|
__name(isUsableGroupContact, "isUsableGroupContact");
|
|
368
|
+
var sharedDatabases = /* @__PURE__ */ new Map();
|
|
369
|
+
async function acquireSharedDatabase(dir) {
|
|
370
|
+
let shared = sharedDatabases.get(dir);
|
|
371
|
+
if (shared?.closing) {
|
|
372
|
+
await shared.closing.catch(() => void 0);
|
|
373
|
+
shared = sharedDatabases.get(dir);
|
|
374
|
+
}
|
|
375
|
+
if (!shared) {
|
|
376
|
+
shared = {
|
|
377
|
+
dir,
|
|
378
|
+
db: new import_level.Level(dir, { keyEncoding: "utf8", valueEncoding: "utf8" }),
|
|
379
|
+
refs: 0,
|
|
380
|
+
opened: false
|
|
381
|
+
};
|
|
382
|
+
sharedDatabases.set(dir, shared);
|
|
383
|
+
}
|
|
384
|
+
shared.refs += 1;
|
|
385
|
+
return shared;
|
|
386
|
+
}
|
|
387
|
+
__name(acquireSharedDatabase, "acquireSharedDatabase");
|
|
388
|
+
async function releaseSharedDatabase(shared) {
|
|
389
|
+
shared.refs -= 1;
|
|
390
|
+
if (shared.refs > 0) return false;
|
|
391
|
+
if (shared.closing) {
|
|
392
|
+
await shared.closing;
|
|
393
|
+
return true;
|
|
394
|
+
}
|
|
395
|
+
if (!shared.opened) {
|
|
396
|
+
if (sharedDatabases.get(shared.dir) === shared) sharedDatabases.delete(shared.dir);
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
const closing = shared.db.close().catch(() => void 0).finally(() => {
|
|
400
|
+
shared.opened = false;
|
|
401
|
+
if (sharedDatabases.get(shared.dir) === shared) sharedDatabases.delete(shared.dir);
|
|
402
|
+
});
|
|
403
|
+
shared.closing = closing;
|
|
404
|
+
await closing;
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
__name(releaseSharedDatabase, "releaseSharedDatabase");
|
|
368
408
|
var _ChatDatabase = class _ChatDatabase {
|
|
369
409
|
constructor(ctx, config, logger) {
|
|
370
410
|
this.ctx = ctx;
|
|
371
411
|
this.config = config;
|
|
372
412
|
this.logger = logger;
|
|
373
|
-
this.
|
|
374
|
-
|
|
375
|
-
|
|
413
|
+
this.dir = import_node_path.default.resolve(ctx.baseDir, "data", "chat-patch", "db");
|
|
414
|
+
}
|
|
415
|
+
get db() {
|
|
416
|
+
if (!this.shared) throw new Error("LevelDB is not initialized");
|
|
417
|
+
return this.shared.db;
|
|
376
418
|
}
|
|
377
419
|
async initialize() {
|
|
378
|
-
await this.
|
|
379
|
-
|
|
380
|
-
|
|
420
|
+
this.shared = await acquireSharedDatabase(this.dir);
|
|
421
|
+
try {
|
|
422
|
+
await this.ensureOpen();
|
|
423
|
+
this.logger.logInfo("LevelDB 已打开:", this.shared.db.location);
|
|
424
|
+
} catch (error) {
|
|
425
|
+
await this.releaseShared();
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
381
428
|
}
|
|
382
429
|
async dispose() {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
430
|
+
const closed = await this.releaseShared();
|
|
431
|
+
if (closed) this.logger.logInfo("LevelDB closed");
|
|
432
|
+
}
|
|
433
|
+
async ensureOpen() {
|
|
434
|
+
const shared = this.shared;
|
|
435
|
+
if (!shared || shared.opened) return;
|
|
436
|
+
if (shared.opening) {
|
|
437
|
+
await shared.opening;
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const opening = shared.db.open().then(() => {
|
|
441
|
+
shared.opened = true;
|
|
442
|
+
});
|
|
443
|
+
shared.opening = opening;
|
|
444
|
+
try {
|
|
445
|
+
await opening;
|
|
446
|
+
} finally {
|
|
447
|
+
shared.opening = void 0;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
async releaseShared() {
|
|
451
|
+
const shared = this.shared;
|
|
452
|
+
this.shared = void 0;
|
|
453
|
+
if (shared) return releaseSharedDatabase(shared);
|
|
454
|
+
return false;
|
|
387
455
|
}
|
|
388
456
|
async clearAll() {
|
|
389
457
|
await this.db.clear();
|
|
@@ -842,100 +910,129 @@ var ChatDatabase = _ChatDatabase;
|
|
|
842
910
|
|
|
843
911
|
// src/recorder.ts
|
|
844
912
|
var MESSAGE_TYPES = /* @__PURE__ */ new Set(["message", "message-created"]);
|
|
913
|
+
function getObject(value) {
|
|
914
|
+
return typeof value === "object" && value !== null ? value : {};
|
|
915
|
+
}
|
|
916
|
+
__name(getObject, "getObject");
|
|
917
|
+
function getString2(value) {
|
|
918
|
+
return typeof value === "string" ? value : "";
|
|
919
|
+
}
|
|
920
|
+
__name(getString2, "getString");
|
|
921
|
+
function getNumber(value) {
|
|
922
|
+
const num = Number(value);
|
|
923
|
+
return Number.isFinite(num) ? num : 0;
|
|
924
|
+
}
|
|
925
|
+
__name(getNumber, "getNumber");
|
|
845
926
|
function normalizeGroupId2(value) {
|
|
846
927
|
return String(value);
|
|
847
928
|
}
|
|
848
929
|
__name(normalizeGroupId2, "normalizeGroupId");
|
|
930
|
+
function isPrivateChannelType3(value) {
|
|
931
|
+
const num = Number(value);
|
|
932
|
+
if (Number.isFinite(num)) return num === 1;
|
|
933
|
+
const text = String(value ?? "").toLowerCase();
|
|
934
|
+
return text === "direct" || text === "private";
|
|
935
|
+
}
|
|
936
|
+
__name(isPrivateChannelType3, "isPrivateChannelType");
|
|
849
937
|
var _Recorder = class _Recorder {
|
|
850
|
-
constructor(
|
|
851
|
-
this.ctx = ctx;
|
|
938
|
+
constructor(config, database, media, contactCache, logger) {
|
|
852
939
|
this.config = config;
|
|
853
940
|
this.database = database;
|
|
854
941
|
this.media = media;
|
|
855
942
|
this.contactCache = contactCache;
|
|
856
943
|
this.logger = logger;
|
|
857
944
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
}
|
|
945
|
+
// 后端直连 Satori 后,由 SatoriGateway 逐条送入原始事件
|
|
946
|
+
async handleEvent(body) {
|
|
947
|
+
const type = getString2(body.type);
|
|
948
|
+
const login = getObject(body.login);
|
|
949
|
+
const platform = getString2(body.platform) || getString2(login.platform);
|
|
950
|
+
if (this.isBlocked(platform)) return false;
|
|
951
|
+
if (type === "message-deleted") {
|
|
952
|
+
await this.handleMessageDeleted(body);
|
|
953
|
+
return true;
|
|
954
|
+
}
|
|
955
|
+
if (!MESSAGE_TYPES.has(type)) return false;
|
|
956
|
+
await this.handleMessageCreated(body);
|
|
957
|
+
return true;
|
|
868
958
|
}
|
|
869
959
|
isBlocked(platform) {
|
|
870
960
|
return (this.config.blockedPlatforms ?? []).some((item) => {
|
|
871
961
|
return item.exactMatch ? platform === item.platformName : platform.includes(item.platformName);
|
|
872
962
|
});
|
|
873
963
|
}
|
|
874
|
-
async
|
|
875
|
-
const
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
const
|
|
879
|
-
const message =
|
|
964
|
+
async handleMessageCreated(body) {
|
|
965
|
+
const login = getObject(body.login);
|
|
966
|
+
const loginUser = getObject(login.user);
|
|
967
|
+
const platform = getString2(body.platform) || getString2(login.platform);
|
|
968
|
+
const selfId = getString2(body.self_id) || getString2(body.selfId) || getString2(loginUser.id);
|
|
969
|
+
const message = getObject(body.message);
|
|
970
|
+
const channel = getObject(body.channel);
|
|
971
|
+
const guild = getObject(body.guild);
|
|
972
|
+
const user = getObject(body.user);
|
|
973
|
+
const sn = getNumber(body.sn);
|
|
974
|
+
const timestamp = getNumber(body.timestamp) || Date.now();
|
|
880
975
|
const record = {
|
|
881
|
-
id: message
|
|
882
|
-
sequence:
|
|
883
|
-
type:
|
|
976
|
+
id: getString2(message.id) || `satori-${sn}`,
|
|
977
|
+
sequence: sn,
|
|
978
|
+
type: getString2(body.type),
|
|
884
979
|
platform,
|
|
885
|
-
selfId
|
|
886
|
-
channelId:
|
|
887
|
-
guildId:
|
|
888
|
-
userId:
|
|
889
|
-
timestamp
|
|
890
|
-
timestampMs:
|
|
980
|
+
selfId,
|
|
981
|
+
channelId: getString2(channel.id) || void 0,
|
|
982
|
+
guildId: getString2(guild.id) || void 0,
|
|
983
|
+
userId: getString2(user.id) || void 0,
|
|
984
|
+
timestamp,
|
|
985
|
+
timestampMs: timestamp,
|
|
891
986
|
receivedAt: Date.now(),
|
|
892
|
-
content:
|
|
893
|
-
elements: message
|
|
894
|
-
raw:
|
|
987
|
+
content: getString2(message.content) || getString2(message.raw_message) || void 0,
|
|
988
|
+
elements: Array.isArray(message.elements) ? message.elements : void 0,
|
|
989
|
+
raw: body
|
|
895
990
|
};
|
|
896
991
|
try {
|
|
897
992
|
await this.database.appendMessage(record);
|
|
898
993
|
} catch (error) {
|
|
899
994
|
this.logger.warn("写入历史消息失败:", error);
|
|
900
995
|
}
|
|
901
|
-
void this.cacheMessageContacts(
|
|
996
|
+
void this.cacheMessageContacts(body).catch((error) => {
|
|
902
997
|
this.logger.warn("缓存消息联系人失败:", error);
|
|
903
998
|
});
|
|
904
|
-
void this.cacheMessageMedia(
|
|
999
|
+
void this.cacheMessageMedia(message, getString2(channel.id)).catch((error) => {
|
|
905
1000
|
this.logger.warn("异步缓存消息媒体失败:", error);
|
|
906
1001
|
});
|
|
907
1002
|
}
|
|
908
|
-
async handleMessageDeleted(
|
|
909
|
-
const
|
|
910
|
-
|
|
911
|
-
const
|
|
912
|
-
const
|
|
913
|
-
const
|
|
914
|
-
const
|
|
915
|
-
|
|
916
|
-
);
|
|
1003
|
+
async handleMessageDeleted(body) {
|
|
1004
|
+
const login = getObject(body.login);
|
|
1005
|
+
const loginUser = getObject(login.user);
|
|
1006
|
+
const platform = getString2(body.platform) || getString2(login.platform);
|
|
1007
|
+
const selfId = getString2(body.self_id) || getString2(body.selfId) || getString2(loginUser.id);
|
|
1008
|
+
const message = getObject(body.message);
|
|
1009
|
+
const channel = getObject(body.channel);
|
|
1010
|
+
const guild = getObject(body.guild);
|
|
1011
|
+
const messageId = getString2(message.id);
|
|
1012
|
+
const channelId = getString2(channel.id) || getString2(guild.id);
|
|
917
1013
|
if (!messageId || !channelId) return;
|
|
918
1014
|
const patch = { revoked: true, revokedAt: Date.now() };
|
|
919
|
-
await this.database.updateMessageRevoked(platform,
|
|
920
|
-
await this.database.updateSelfMessageByMessageId(platform,
|
|
921
|
-
}
|
|
922
|
-
async cacheMessageContacts(
|
|
923
|
-
const
|
|
924
|
-
const
|
|
925
|
-
const
|
|
926
|
-
const
|
|
927
|
-
const
|
|
928
|
-
const
|
|
929
|
-
const
|
|
930
|
-
const
|
|
931
|
-
const
|
|
932
|
-
const
|
|
933
|
-
const
|
|
1015
|
+
await this.database.updateMessageRevoked(platform, selfId, channelId, messageId, patch);
|
|
1016
|
+
await this.database.updateSelfMessageByMessageId(platform, selfId, channelId, messageId, patch);
|
|
1017
|
+
}
|
|
1018
|
+
async cacheMessageContacts(body) {
|
|
1019
|
+
const login = getObject(body.login);
|
|
1020
|
+
const loginUser = getObject(login.user);
|
|
1021
|
+
const platform = getString2(body.platform) || getString2(login.platform);
|
|
1022
|
+
const selfId = getString2(body.self_id) || getString2(body.selfId) || getString2(loginUser.id);
|
|
1023
|
+
const user = getObject(body.user);
|
|
1024
|
+
const guild = getObject(body.guild);
|
|
1025
|
+
const channel = getObject(body.channel);
|
|
1026
|
+
const member = getObject(body.member);
|
|
1027
|
+
const userId = getString2(user.id);
|
|
1028
|
+
const guildId = getString2(guild.id);
|
|
1029
|
+
const channelId = getString2(channel.id);
|
|
1030
|
+
const isPrivateChannel = isPrivateChannelType3(channel.type);
|
|
934
1031
|
const groupId = guildId || (isPrivateChannel ? "" : normalizeGroupId2(channelId)) || "";
|
|
935
|
-
const userName = user
|
|
936
|
-
const userAvatar = user
|
|
937
|
-
const groupName = guild
|
|
938
|
-
const groupAvatar = guild
|
|
1032
|
+
const userName = getString2(user.name) || getString2(user.nick) || getString2(member.nick) || getString2(member.name);
|
|
1033
|
+
const userAvatar = getString2(user.avatar) || getString2(member.avatar);
|
|
1034
|
+
const groupName = getString2(guild.name) || getString2(channel.name);
|
|
1035
|
+
const groupAvatar = getString2(guild.avatar);
|
|
939
1036
|
if (groupId) {
|
|
940
1037
|
const groupItem = await this.contactCache.getGroup(
|
|
941
1038
|
platform,
|
|
@@ -945,7 +1042,7 @@ var _Recorder = class _Recorder {
|
|
|
945
1042
|
channelId || groupId,
|
|
946
1043
|
groupName,
|
|
947
1044
|
groupAvatar,
|
|
948
|
-
channel
|
|
1045
|
+
channel.type
|
|
949
1046
|
);
|
|
950
1047
|
if (userId) {
|
|
951
1048
|
const userItem = await this.contactCache.getUser(
|
|
@@ -969,9 +1066,9 @@ var _Recorder = class _Recorder {
|
|
|
969
1066
|
id: userId,
|
|
970
1067
|
user_id: userId,
|
|
971
1068
|
nickname: userName || userItem?.name,
|
|
972
|
-
card: member
|
|
1069
|
+
card: member.nick || member.name || "",
|
|
973
1070
|
avatar: userItem?.avatar || userAvatar || void 0,
|
|
974
|
-
role: member
|
|
1071
|
+
role: member.title || ""
|
|
975
1072
|
}
|
|
976
1073
|
}
|
|
977
1074
|
);
|
|
@@ -989,16 +1086,1255 @@ var _Recorder = class _Recorder {
|
|
|
989
1086
|
);
|
|
990
1087
|
}
|
|
991
1088
|
}
|
|
992
|
-
async cacheMessageMedia(
|
|
993
|
-
|
|
994
|
-
event.channel?.id || event.guild?.id || ""
|
|
995
|
-
);
|
|
996
|
-
await this.media.cacheMessageMedia(event.message, channelId);
|
|
1089
|
+
async cacheMessageMedia(message, channelId) {
|
|
1090
|
+
await this.media.cacheMessageMedia(message, channelId);
|
|
997
1091
|
}
|
|
998
1092
|
};
|
|
999
1093
|
__name(_Recorder, "Recorder");
|
|
1000
1094
|
var Recorder = _Recorder;
|
|
1001
1095
|
|
|
1096
|
+
// ../../node_modules/cosmokit/lib/index.mjs
|
|
1097
|
+
var __defProp2 = Object.defineProperty;
|
|
1098
|
+
var __name2 = /* @__PURE__ */ __name((target, value) => __defProp2(target, "name", { value, configurable: true }), "__name");
|
|
1099
|
+
function noop() {
|
|
1100
|
+
}
|
|
1101
|
+
__name(noop, "noop");
|
|
1102
|
+
__name2(noop, "noop");
|
|
1103
|
+
function isNullable(value) {
|
|
1104
|
+
return value === null || value === void 0;
|
|
1105
|
+
}
|
|
1106
|
+
__name(isNullable, "isNullable");
|
|
1107
|
+
__name2(isNullable, "isNullable");
|
|
1108
|
+
function isNonNullable(value) {
|
|
1109
|
+
return !isNullable(value);
|
|
1110
|
+
}
|
|
1111
|
+
__name(isNonNullable, "isNonNullable");
|
|
1112
|
+
__name2(isNonNullable, "isNonNullable");
|
|
1113
|
+
function isPlainObject(data) {
|
|
1114
|
+
return data && typeof data === "object" && !Array.isArray(data);
|
|
1115
|
+
}
|
|
1116
|
+
__name(isPlainObject, "isPlainObject");
|
|
1117
|
+
__name2(isPlainObject, "isPlainObject");
|
|
1118
|
+
function filterKeys(object, filter2) {
|
|
1119
|
+
return Object.fromEntries(Object.entries(object).filter(([key, value]) => filter2(key, value)));
|
|
1120
|
+
}
|
|
1121
|
+
__name(filterKeys, "filterKeys");
|
|
1122
|
+
__name2(filterKeys, "filterKeys");
|
|
1123
|
+
function mapValues(object, transform) {
|
|
1124
|
+
return Object.fromEntries(Object.entries(object).map(([key, value]) => [key, transform(value, key)]));
|
|
1125
|
+
}
|
|
1126
|
+
__name(mapValues, "mapValues");
|
|
1127
|
+
__name2(mapValues, "mapValues");
|
|
1128
|
+
function pick(source, keys, forced) {
|
|
1129
|
+
if (!keys) return { ...source };
|
|
1130
|
+
const result = {};
|
|
1131
|
+
for (const key of keys) {
|
|
1132
|
+
if (forced || source[key] !== void 0) result[key] = source[key];
|
|
1133
|
+
}
|
|
1134
|
+
return result;
|
|
1135
|
+
}
|
|
1136
|
+
__name(pick, "pick");
|
|
1137
|
+
__name2(pick, "pick");
|
|
1138
|
+
function omit(source, keys) {
|
|
1139
|
+
if (!keys) return { ...source };
|
|
1140
|
+
const result = { ...source };
|
|
1141
|
+
for (const key of keys) {
|
|
1142
|
+
Reflect.deleteProperty(result, key);
|
|
1143
|
+
}
|
|
1144
|
+
return result;
|
|
1145
|
+
}
|
|
1146
|
+
__name(omit, "omit");
|
|
1147
|
+
__name2(omit, "omit");
|
|
1148
|
+
function defineProperty(object, key, value) {
|
|
1149
|
+
return Object.defineProperty(object, key, { writable: true, value, enumerable: false });
|
|
1150
|
+
}
|
|
1151
|
+
__name(defineProperty, "defineProperty");
|
|
1152
|
+
__name2(defineProperty, "defineProperty");
|
|
1153
|
+
function contain(array1, array2) {
|
|
1154
|
+
return array2.every((item) => array1.includes(item));
|
|
1155
|
+
}
|
|
1156
|
+
__name(contain, "contain");
|
|
1157
|
+
__name2(contain, "contain");
|
|
1158
|
+
function intersection(array1, array2) {
|
|
1159
|
+
return array1.filter((item) => array2.includes(item));
|
|
1160
|
+
}
|
|
1161
|
+
__name(intersection, "intersection");
|
|
1162
|
+
__name2(intersection, "intersection");
|
|
1163
|
+
function difference(array1, array2) {
|
|
1164
|
+
return array1.filter((item) => !array2.includes(item));
|
|
1165
|
+
}
|
|
1166
|
+
__name(difference, "difference");
|
|
1167
|
+
__name2(difference, "difference");
|
|
1168
|
+
function union(array1, array2) {
|
|
1169
|
+
return Array.from(/* @__PURE__ */ new Set([...array1, ...array2]));
|
|
1170
|
+
}
|
|
1171
|
+
__name(union, "union");
|
|
1172
|
+
__name2(union, "union");
|
|
1173
|
+
function deduplicate(array) {
|
|
1174
|
+
return [...new Set(array)];
|
|
1175
|
+
}
|
|
1176
|
+
__name(deduplicate, "deduplicate");
|
|
1177
|
+
__name2(deduplicate, "deduplicate");
|
|
1178
|
+
function remove(list, item) {
|
|
1179
|
+
const index = list?.indexOf(item);
|
|
1180
|
+
if (index >= 0) {
|
|
1181
|
+
list.splice(index, 1);
|
|
1182
|
+
return true;
|
|
1183
|
+
} else {
|
|
1184
|
+
return false;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
__name(remove, "remove");
|
|
1188
|
+
__name2(remove, "remove");
|
|
1189
|
+
function makeArray(source) {
|
|
1190
|
+
return Array.isArray(source) ? source : isNullable(source) ? [] : [source];
|
|
1191
|
+
}
|
|
1192
|
+
__name(makeArray, "makeArray");
|
|
1193
|
+
__name2(makeArray, "makeArray");
|
|
1194
|
+
function is(type, value) {
|
|
1195
|
+
if (arguments.length === 1) return (value2) => is(type, value2);
|
|
1196
|
+
return type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;
|
|
1197
|
+
}
|
|
1198
|
+
__name(is, "is");
|
|
1199
|
+
__name2(is, "is");
|
|
1200
|
+
function isArrayBufferLike(value) {
|
|
1201
|
+
return is("ArrayBuffer", value) || is("SharedArrayBuffer", value);
|
|
1202
|
+
}
|
|
1203
|
+
__name(isArrayBufferLike, "isArrayBufferLike");
|
|
1204
|
+
__name2(isArrayBufferLike, "isArrayBufferLike");
|
|
1205
|
+
function isArrayBufferSource(value) {
|
|
1206
|
+
return isArrayBufferLike(value) || ArrayBuffer.isView(value);
|
|
1207
|
+
}
|
|
1208
|
+
__name(isArrayBufferSource, "isArrayBufferSource");
|
|
1209
|
+
__name2(isArrayBufferSource, "isArrayBufferSource");
|
|
1210
|
+
var Binary;
|
|
1211
|
+
((Binary2) => {
|
|
1212
|
+
Binary2.is = isArrayBufferLike;
|
|
1213
|
+
Binary2.isSource = isArrayBufferSource;
|
|
1214
|
+
function fromSource(source) {
|
|
1215
|
+
if (ArrayBuffer.isView(source)) {
|
|
1216
|
+
return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
|
|
1217
|
+
} else {
|
|
1218
|
+
return source;
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
__name(fromSource, "fromSource");
|
|
1222
|
+
Binary2.fromSource = fromSource;
|
|
1223
|
+
__name2(fromSource, "fromSource");
|
|
1224
|
+
function toBase64(source) {
|
|
1225
|
+
if (typeof Buffer !== "undefined") {
|
|
1226
|
+
return Buffer.from(source).toString("base64");
|
|
1227
|
+
}
|
|
1228
|
+
let binary = "";
|
|
1229
|
+
const bytes = new Uint8Array(source);
|
|
1230
|
+
for (let i = 0; i < bytes.byteLength; i++) {
|
|
1231
|
+
binary += String.fromCharCode(bytes[i]);
|
|
1232
|
+
}
|
|
1233
|
+
return btoa(binary);
|
|
1234
|
+
}
|
|
1235
|
+
__name(toBase64, "toBase64");
|
|
1236
|
+
Binary2.toBase64 = toBase64;
|
|
1237
|
+
__name2(toBase64, "toBase64");
|
|
1238
|
+
function fromBase64(source) {
|
|
1239
|
+
if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "base64"));
|
|
1240
|
+
return Uint8Array.from(atob(source), (c) => c.charCodeAt(0));
|
|
1241
|
+
}
|
|
1242
|
+
__name(fromBase64, "fromBase64");
|
|
1243
|
+
Binary2.fromBase64 = fromBase64;
|
|
1244
|
+
__name2(fromBase64, "fromBase64");
|
|
1245
|
+
function toHex(source) {
|
|
1246
|
+
if (typeof Buffer !== "undefined") return Buffer.from(source).toString("hex");
|
|
1247
|
+
return Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
1248
|
+
}
|
|
1249
|
+
__name(toHex, "toHex");
|
|
1250
|
+
Binary2.toHex = toHex;
|
|
1251
|
+
__name2(toHex, "toHex");
|
|
1252
|
+
function fromHex(source) {
|
|
1253
|
+
if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "hex"));
|
|
1254
|
+
const hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);
|
|
1255
|
+
const buffer = [];
|
|
1256
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
1257
|
+
buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));
|
|
1258
|
+
}
|
|
1259
|
+
return Uint8Array.from(buffer).buffer;
|
|
1260
|
+
}
|
|
1261
|
+
__name(fromHex, "fromHex");
|
|
1262
|
+
Binary2.fromHex = fromHex;
|
|
1263
|
+
__name2(fromHex, "fromHex");
|
|
1264
|
+
})(Binary || (Binary = {}));
|
|
1265
|
+
var base64ToArrayBuffer = Binary.fromBase64;
|
|
1266
|
+
var arrayBufferToBase64 = Binary.toBase64;
|
|
1267
|
+
var hexToArrayBuffer = Binary.fromHex;
|
|
1268
|
+
var arrayBufferToHex = Binary.toHex;
|
|
1269
|
+
function clone(source, refs = /* @__PURE__ */ new Map()) {
|
|
1270
|
+
if (!source || typeof source !== "object") return source;
|
|
1271
|
+
if (is("Date", source)) return new Date(source.valueOf());
|
|
1272
|
+
if (is("RegExp", source)) return new RegExp(source.source, source.flags);
|
|
1273
|
+
if (isArrayBufferLike(source)) return source.slice(0);
|
|
1274
|
+
if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
|
|
1275
|
+
const cached = refs.get(source);
|
|
1276
|
+
if (cached) return cached;
|
|
1277
|
+
if (Array.isArray(source)) {
|
|
1278
|
+
const result2 = [];
|
|
1279
|
+
refs.set(source, result2);
|
|
1280
|
+
source.forEach((value, index) => {
|
|
1281
|
+
result2[index] = Reflect.apply(clone, null, [value, refs]);
|
|
1282
|
+
});
|
|
1283
|
+
return result2;
|
|
1284
|
+
}
|
|
1285
|
+
const result = Object.create(Object.getPrototypeOf(source));
|
|
1286
|
+
refs.set(source, result);
|
|
1287
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
1288
|
+
const descriptor = { ...Reflect.getOwnPropertyDescriptor(source, key) };
|
|
1289
|
+
if ("value" in descriptor) {
|
|
1290
|
+
descriptor.value = Reflect.apply(clone, null, [descriptor.value, refs]);
|
|
1291
|
+
}
|
|
1292
|
+
Reflect.defineProperty(result, key, descriptor);
|
|
1293
|
+
}
|
|
1294
|
+
return result;
|
|
1295
|
+
}
|
|
1296
|
+
__name(clone, "clone");
|
|
1297
|
+
__name2(clone, "clone");
|
|
1298
|
+
function deepEqual(a, b, strict) {
|
|
1299
|
+
if (a === b) return true;
|
|
1300
|
+
if (!strict && isNullable(a) && isNullable(b)) return true;
|
|
1301
|
+
if (typeof a !== typeof b) return false;
|
|
1302
|
+
if (typeof a !== "object") return false;
|
|
1303
|
+
if (!a || !b) return false;
|
|
1304
|
+
function check(test, then) {
|
|
1305
|
+
return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
|
|
1306
|
+
}
|
|
1307
|
+
__name(check, "check");
|
|
1308
|
+
__name2(check, "check");
|
|
1309
|
+
return check(Array.isArray, (a2, b2) => a2.length === b2.length && a2.every((item, index) => deepEqual(item, b2[index]))) ?? check(is("Date"), (a2, b2) => a2.valueOf() === b2.valueOf()) ?? check(is("RegExp"), (a2, b2) => a2.source === b2.source && a2.flags === b2.flags) ?? check(isArrayBufferLike, (a2, b2) => {
|
|
1310
|
+
if (a2.byteLength !== b2.byteLength) return false;
|
|
1311
|
+
const viewA = new Uint8Array(a2);
|
|
1312
|
+
const viewB = new Uint8Array(b2);
|
|
1313
|
+
for (let i = 0; i < viewA.length; i++) {
|
|
1314
|
+
if (viewA[i] !== viewB[i]) return false;
|
|
1315
|
+
}
|
|
1316
|
+
return true;
|
|
1317
|
+
}) ?? Object.keys({ ...a, ...b }).every((key) => deepEqual(a[key], b[key], strict));
|
|
1318
|
+
}
|
|
1319
|
+
__name(deepEqual, "deepEqual");
|
|
1320
|
+
__name2(deepEqual, "deepEqual");
|
|
1321
|
+
function capitalize(source) {
|
|
1322
|
+
return source.charAt(0).toUpperCase() + source.slice(1);
|
|
1323
|
+
}
|
|
1324
|
+
__name(capitalize, "capitalize");
|
|
1325
|
+
__name2(capitalize, "capitalize");
|
|
1326
|
+
function uncapitalize(source) {
|
|
1327
|
+
return source.charAt(0).toLowerCase() + source.slice(1);
|
|
1328
|
+
}
|
|
1329
|
+
__name(uncapitalize, "uncapitalize");
|
|
1330
|
+
__name2(uncapitalize, "uncapitalize");
|
|
1331
|
+
function camelCase(source) {
|
|
1332
|
+
return source.replace(/[_-][a-z]/g, (str) => str.slice(1).toUpperCase());
|
|
1333
|
+
}
|
|
1334
|
+
__name(camelCase, "camelCase");
|
|
1335
|
+
__name2(camelCase, "camelCase");
|
|
1336
|
+
function tokenize(source, delimiters, delimiter) {
|
|
1337
|
+
const output = [];
|
|
1338
|
+
let state = 0;
|
|
1339
|
+
for (let i = 0; i < source.length; i++) {
|
|
1340
|
+
const code = source.charCodeAt(i);
|
|
1341
|
+
if (code >= 65 && code <= 90) {
|
|
1342
|
+
if (state === 1) {
|
|
1343
|
+
const next = source.charCodeAt(i + 1);
|
|
1344
|
+
if (next >= 97 && next <= 122) {
|
|
1345
|
+
output.push(delimiter);
|
|
1346
|
+
}
|
|
1347
|
+
output.push(code + 32);
|
|
1348
|
+
} else {
|
|
1349
|
+
if (state !== 0) {
|
|
1350
|
+
output.push(delimiter);
|
|
1351
|
+
}
|
|
1352
|
+
output.push(code + 32);
|
|
1353
|
+
}
|
|
1354
|
+
state = 1;
|
|
1355
|
+
} else if (code >= 97 && code <= 122) {
|
|
1356
|
+
output.push(code);
|
|
1357
|
+
state = 2;
|
|
1358
|
+
} else if (delimiters.includes(code)) {
|
|
1359
|
+
if (state !== 0) {
|
|
1360
|
+
output.push(delimiter);
|
|
1361
|
+
}
|
|
1362
|
+
state = 0;
|
|
1363
|
+
} else {
|
|
1364
|
+
output.push(code);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
return String.fromCharCode(...output);
|
|
1368
|
+
}
|
|
1369
|
+
__name(tokenize, "tokenize");
|
|
1370
|
+
__name2(tokenize, "tokenize");
|
|
1371
|
+
function paramCase(source) {
|
|
1372
|
+
return tokenize(source, [45, 95], 45);
|
|
1373
|
+
}
|
|
1374
|
+
__name(paramCase, "paramCase");
|
|
1375
|
+
__name2(paramCase, "paramCase");
|
|
1376
|
+
function snakeCase(source) {
|
|
1377
|
+
return tokenize(source, [45, 95], 95);
|
|
1378
|
+
}
|
|
1379
|
+
__name(snakeCase, "snakeCase");
|
|
1380
|
+
__name2(snakeCase, "snakeCase");
|
|
1381
|
+
var camelize = camelCase;
|
|
1382
|
+
var hyphenate = paramCase;
|
|
1383
|
+
function formatProperty(key) {
|
|
1384
|
+
if (typeof key !== "string") return `[${key.toString()}]`;
|
|
1385
|
+
return /^[a-z_$][\w$]*$/i.test(key) ? `.${key}` : `[${JSON.stringify(key)}]`;
|
|
1386
|
+
}
|
|
1387
|
+
__name(formatProperty, "formatProperty");
|
|
1388
|
+
__name2(formatProperty, "formatProperty");
|
|
1389
|
+
function trimSlash(source) {
|
|
1390
|
+
return source.replace(/\/$/, "");
|
|
1391
|
+
}
|
|
1392
|
+
__name(trimSlash, "trimSlash");
|
|
1393
|
+
__name2(trimSlash, "trimSlash");
|
|
1394
|
+
function sanitize(source) {
|
|
1395
|
+
if (!source.startsWith("/")) source = "/" + source;
|
|
1396
|
+
return trimSlash(source);
|
|
1397
|
+
}
|
|
1398
|
+
__name(sanitize, "sanitize");
|
|
1399
|
+
__name2(sanitize, "sanitize");
|
|
1400
|
+
var Time;
|
|
1401
|
+
((Time2) => {
|
|
1402
|
+
Time2.millisecond = 1;
|
|
1403
|
+
Time2.second = 1e3;
|
|
1404
|
+
Time2.minute = Time2.second * 60;
|
|
1405
|
+
Time2.hour = Time2.minute * 60;
|
|
1406
|
+
Time2.day = Time2.hour * 24;
|
|
1407
|
+
Time2.week = Time2.day * 7;
|
|
1408
|
+
let timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
|
|
1409
|
+
function setTimezoneOffset(offset) {
|
|
1410
|
+
timezoneOffset = offset;
|
|
1411
|
+
}
|
|
1412
|
+
__name(setTimezoneOffset, "setTimezoneOffset");
|
|
1413
|
+
Time2.setTimezoneOffset = setTimezoneOffset;
|
|
1414
|
+
__name2(setTimezoneOffset, "setTimezoneOffset");
|
|
1415
|
+
function getTimezoneOffset() {
|
|
1416
|
+
return timezoneOffset;
|
|
1417
|
+
}
|
|
1418
|
+
__name(getTimezoneOffset, "getTimezoneOffset");
|
|
1419
|
+
Time2.getTimezoneOffset = getTimezoneOffset;
|
|
1420
|
+
__name2(getTimezoneOffset, "getTimezoneOffset");
|
|
1421
|
+
function getDateNumber(date = /* @__PURE__ */ new Date(), offset) {
|
|
1422
|
+
if (typeof date === "number") date = new Date(date);
|
|
1423
|
+
if (offset === void 0) offset = timezoneOffset;
|
|
1424
|
+
return Math.floor((date.valueOf() / Time2.minute - offset) / 1440);
|
|
1425
|
+
}
|
|
1426
|
+
__name(getDateNumber, "getDateNumber");
|
|
1427
|
+
Time2.getDateNumber = getDateNumber;
|
|
1428
|
+
__name2(getDateNumber, "getDateNumber");
|
|
1429
|
+
function fromDateNumber(value, offset) {
|
|
1430
|
+
const date = new Date(value * Time2.day);
|
|
1431
|
+
if (offset === void 0) offset = timezoneOffset;
|
|
1432
|
+
return new Date(+date + offset * Time2.minute);
|
|
1433
|
+
}
|
|
1434
|
+
__name(fromDateNumber, "fromDateNumber");
|
|
1435
|
+
Time2.fromDateNumber = fromDateNumber;
|
|
1436
|
+
__name2(fromDateNumber, "fromDateNumber");
|
|
1437
|
+
const numeric = /\d+(?:\.\d+)?/.source;
|
|
1438
|
+
const timeRegExp = new RegExp(`^${[
|
|
1439
|
+
"w(?:eek(?:s)?)?",
|
|
1440
|
+
"d(?:ay(?:s)?)?",
|
|
1441
|
+
"h(?:our(?:s)?)?",
|
|
1442
|
+
"m(?:in(?:ute)?(?:s)?)?",
|
|
1443
|
+
"s(?:ec(?:ond)?(?:s)?)?"
|
|
1444
|
+
].map((unit) => `(${numeric}${unit})?`).join("")}$`);
|
|
1445
|
+
function parseTime(source) {
|
|
1446
|
+
const capture = timeRegExp.exec(source);
|
|
1447
|
+
if (!capture) return 0;
|
|
1448
|
+
return (parseFloat(capture[1]) * Time2.week || 0) + (parseFloat(capture[2]) * Time2.day || 0) + (parseFloat(capture[3]) * Time2.hour || 0) + (parseFloat(capture[4]) * Time2.minute || 0) + (parseFloat(capture[5]) * Time2.second || 0);
|
|
1449
|
+
}
|
|
1450
|
+
__name(parseTime, "parseTime");
|
|
1451
|
+
Time2.parseTime = parseTime;
|
|
1452
|
+
__name2(parseTime, "parseTime");
|
|
1453
|
+
function parseDate(date) {
|
|
1454
|
+
const parsed = parseTime(date);
|
|
1455
|
+
if (parsed) {
|
|
1456
|
+
date = Date.now() + parsed;
|
|
1457
|
+
} else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) {
|
|
1458
|
+
date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;
|
|
1459
|
+
} else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) {
|
|
1460
|
+
date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;
|
|
1461
|
+
}
|
|
1462
|
+
return date ? new Date(date) : /* @__PURE__ */ new Date();
|
|
1463
|
+
}
|
|
1464
|
+
__name(parseDate, "parseDate");
|
|
1465
|
+
Time2.parseDate = parseDate;
|
|
1466
|
+
__name2(parseDate, "parseDate");
|
|
1467
|
+
function format(ms) {
|
|
1468
|
+
const abs = Math.abs(ms);
|
|
1469
|
+
if (abs >= Time2.day - Time2.hour / 2) {
|
|
1470
|
+
return Math.round(ms / Time2.day) + "d";
|
|
1471
|
+
} else if (abs >= Time2.hour - Time2.minute / 2) {
|
|
1472
|
+
return Math.round(ms / Time2.hour) + "h";
|
|
1473
|
+
} else if (abs >= Time2.minute - Time2.second / 2) {
|
|
1474
|
+
return Math.round(ms / Time2.minute) + "m";
|
|
1475
|
+
} else if (abs >= Time2.second) {
|
|
1476
|
+
return Math.round(ms / Time2.second) + "s";
|
|
1477
|
+
}
|
|
1478
|
+
return ms + "ms";
|
|
1479
|
+
}
|
|
1480
|
+
__name(format, "format");
|
|
1481
|
+
Time2.format = format;
|
|
1482
|
+
__name2(format, "format");
|
|
1483
|
+
function toDigits(source, length = 2) {
|
|
1484
|
+
return source.toString().padStart(length, "0");
|
|
1485
|
+
}
|
|
1486
|
+
__name(toDigits, "toDigits");
|
|
1487
|
+
Time2.toDigits = toDigits;
|
|
1488
|
+
__name2(toDigits, "toDigits");
|
|
1489
|
+
function template(template2, time = /* @__PURE__ */ new Date()) {
|
|
1490
|
+
return template2.replace("yyyy", time.getFullYear().toString()).replace("yy", time.getFullYear().toString().slice(2)).replace("MM", toDigits(time.getMonth() + 1)).replace("dd", toDigits(time.getDate())).replace("hh", toDigits(time.getHours())).replace("mm", toDigits(time.getMinutes())).replace("ss", toDigits(time.getSeconds())).replace("SSS", toDigits(time.getMilliseconds(), 3));
|
|
1491
|
+
}
|
|
1492
|
+
__name(template, "template");
|
|
1493
|
+
Time2.template = template;
|
|
1494
|
+
__name2(template, "template");
|
|
1495
|
+
})(Time || (Time = {}));
|
|
1496
|
+
|
|
1497
|
+
// ../../node_modules/@satorijs/element/lib/index.mjs
|
|
1498
|
+
var __defProp3 = Object.defineProperty;
|
|
1499
|
+
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
1500
|
+
var __name3 = /* @__PURE__ */ __name((target, value) => __defProp3(target, "name", { value, configurable: true }), "__name");
|
|
1501
|
+
var __commonJS = /* @__PURE__ */ __name((cb, mod) => /* @__PURE__ */ __name(function __require() {
|
|
1502
|
+
return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
1503
|
+
}, "__require"), "__commonJS");
|
|
1504
|
+
var require_index = __commonJS({
|
|
1505
|
+
"src/index.ts"(exports2, module2) {
|
|
1506
|
+
var _a;
|
|
1507
|
+
var kElement = Symbol.for("satori.element");
|
|
1508
|
+
var ElementConstructor = (_a = class {
|
|
1509
|
+
get data() {
|
|
1510
|
+
return this.attrs;
|
|
1511
|
+
}
|
|
1512
|
+
getTagName() {
|
|
1513
|
+
if (this.type === "component") {
|
|
1514
|
+
return this.attrs.is?.name ?? "component";
|
|
1515
|
+
} else {
|
|
1516
|
+
return this.type;
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
toAttrString() {
|
|
1520
|
+
return Object.entries(this.attrs).map(([key, value]) => {
|
|
1521
|
+
if (isNullable(value)) return "";
|
|
1522
|
+
key = hyphenate(key);
|
|
1523
|
+
if (value === true) return ` ${key}`;
|
|
1524
|
+
if (value === false) return ` no-${key}`;
|
|
1525
|
+
return ` ${key}="${Element.escape("" + value, true)}"`;
|
|
1526
|
+
}).join("");
|
|
1527
|
+
}
|
|
1528
|
+
toString(strip = false) {
|
|
1529
|
+
if (this.type === "text" && "content" in this.attrs) {
|
|
1530
|
+
return strip ? this.attrs.content : Element.escape(this.attrs.content);
|
|
1531
|
+
}
|
|
1532
|
+
const inner = this.children.map((child) => child.toString(strip)).join("");
|
|
1533
|
+
if (strip) return inner;
|
|
1534
|
+
const attrs = this.toAttrString();
|
|
1535
|
+
const tag = this.getTagName();
|
|
1536
|
+
if (!this.children.length) return `<${tag}${attrs}/>`;
|
|
1537
|
+
return `<${tag}${attrs}>${inner}</${tag}>`;
|
|
1538
|
+
}
|
|
1539
|
+
}, __name(_a, "ElementConstructor"), __name3(_a, "ElementConstructor"), _a);
|
|
1540
|
+
defineProperty(ElementConstructor, "name", "Element");
|
|
1541
|
+
defineProperty(ElementConstructor.prototype, kElement, true);
|
|
1542
|
+
function Element(type, ...args) {
|
|
1543
|
+
const el = Object.create(ElementConstructor.prototype);
|
|
1544
|
+
const attrs = {}, children = [];
|
|
1545
|
+
if (args[0] && typeof args[0] === "object" && !Element.isElement(args[0]) && !Array.isArray(args[0])) {
|
|
1546
|
+
const props = args.shift();
|
|
1547
|
+
for (const [key, value] of Object.entries(props)) {
|
|
1548
|
+
if (isNullable(value)) continue;
|
|
1549
|
+
if (key === "children") {
|
|
1550
|
+
args.push(...makeArray(value));
|
|
1551
|
+
} else {
|
|
1552
|
+
attrs[camelize(key)] = value;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
for (const child of args) {
|
|
1557
|
+
children.push(...Element.toElementArray(child));
|
|
1558
|
+
}
|
|
1559
|
+
if (typeof type === "function") {
|
|
1560
|
+
attrs.is = type;
|
|
1561
|
+
type = "component";
|
|
1562
|
+
}
|
|
1563
|
+
return Object.assign(el, { type, attrs, children });
|
|
1564
|
+
}
|
|
1565
|
+
__name(Element, "Element");
|
|
1566
|
+
__name3(Element, "Element");
|
|
1567
|
+
var evaluate = new Function("expr", "context", `
|
|
1568
|
+
try {
|
|
1569
|
+
with (context) {
|
|
1570
|
+
return eval(expr)
|
|
1571
|
+
}
|
|
1572
|
+
} catch {}
|
|
1573
|
+
`);
|
|
1574
|
+
((Element2) => {
|
|
1575
|
+
Element2.jsx = Element2;
|
|
1576
|
+
Element2.jsxs = Element2;
|
|
1577
|
+
Element2.jsxDEV = Element2;
|
|
1578
|
+
Element2.Fragment = "template";
|
|
1579
|
+
function isElement(source) {
|
|
1580
|
+
return source && typeof source === "object" && source[kElement];
|
|
1581
|
+
}
|
|
1582
|
+
__name(isElement, "isElement");
|
|
1583
|
+
Element2.isElement = isElement;
|
|
1584
|
+
__name3(isElement, "isElement");
|
|
1585
|
+
function toElement(content) {
|
|
1586
|
+
if (typeof content === "string" || typeof content === "number" || typeof content === "boolean") {
|
|
1587
|
+
content = "" + content;
|
|
1588
|
+
if (content) return Element2("text", { content });
|
|
1589
|
+
} else if (isElement(content)) {
|
|
1590
|
+
return content;
|
|
1591
|
+
} else if (!isNullable(content)) {
|
|
1592
|
+
throw new TypeError(`Invalid content: ${content}`);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
__name(toElement, "toElement");
|
|
1596
|
+
Element2.toElement = toElement;
|
|
1597
|
+
__name3(toElement, "toElement");
|
|
1598
|
+
function toElementArray(content) {
|
|
1599
|
+
if (Array.isArray(content)) {
|
|
1600
|
+
return content.map(toElement).filter(isNonNullable);
|
|
1601
|
+
} else {
|
|
1602
|
+
return [toElement(content)].filter(isNonNullable);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
__name(toElementArray, "toElementArray");
|
|
1606
|
+
Element2.toElementArray = toElementArray;
|
|
1607
|
+
__name3(toElementArray, "toElementArray");
|
|
1608
|
+
function normalize(source, context) {
|
|
1609
|
+
return typeof source === "string" ? parse(source, context) : toElementArray(source);
|
|
1610
|
+
}
|
|
1611
|
+
__name(normalize, "normalize");
|
|
1612
|
+
Element2.normalize = normalize;
|
|
1613
|
+
__name3(normalize, "normalize");
|
|
1614
|
+
function escape(source, inline = false) {
|
|
1615
|
+
const result = (source ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1616
|
+
return inline ? result.replace(/"/g, """) : result;
|
|
1617
|
+
}
|
|
1618
|
+
__name(escape, "escape");
|
|
1619
|
+
Element2.escape = escape;
|
|
1620
|
+
__name3(escape, "escape");
|
|
1621
|
+
function unescape(source) {
|
|
1622
|
+
return source.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/&#(\d+);/g, (_, code) => code === "38" ? _ : String.fromCharCode(+code)).replace(/&#x([0-9a-f]+);/gi, (_, code) => code === "26" ? _ : String.fromCharCode(parseInt(code, 16))).replace(/&(amp|#38|#x26);/g, "&");
|
|
1623
|
+
}
|
|
1624
|
+
__name(unescape, "unescape");
|
|
1625
|
+
Element2.unescape = unescape;
|
|
1626
|
+
__name3(unescape, "unescape");
|
|
1627
|
+
function from(source, options = {}) {
|
|
1628
|
+
const elements = parse(source);
|
|
1629
|
+
if (options.caret) {
|
|
1630
|
+
if (options.type && elements[0]?.type !== options.type) return;
|
|
1631
|
+
return elements[0];
|
|
1632
|
+
}
|
|
1633
|
+
return select(elements, options.type || "*")[0];
|
|
1634
|
+
}
|
|
1635
|
+
__name(from, "from");
|
|
1636
|
+
Element2.from = from;
|
|
1637
|
+
__name3(from, "from");
|
|
1638
|
+
const combRegExp = / *([ >+~]) */g;
|
|
1639
|
+
function parseSelector(input) {
|
|
1640
|
+
return input.split(",").map((query) => {
|
|
1641
|
+
const selectors = [];
|
|
1642
|
+
query = query.trim();
|
|
1643
|
+
let combCap, combinator = " ";
|
|
1644
|
+
while (combCap = combRegExp.exec(query)) {
|
|
1645
|
+
selectors.push({ type: query.slice(0, combCap.index), combinator });
|
|
1646
|
+
combinator = combCap[1];
|
|
1647
|
+
query = query.slice(combCap.index + combCap[0].length);
|
|
1648
|
+
}
|
|
1649
|
+
selectors.push({ type: query, combinator });
|
|
1650
|
+
return selectors;
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
__name(parseSelector, "parseSelector");
|
|
1654
|
+
Element2.parseSelector = parseSelector;
|
|
1655
|
+
__name3(parseSelector, "parseSelector");
|
|
1656
|
+
function select(source, query) {
|
|
1657
|
+
if (!source || !query) return [];
|
|
1658
|
+
if (typeof source === "string") source = parse(source);
|
|
1659
|
+
if (typeof query === "string") query = parseSelector(query);
|
|
1660
|
+
if (!query.length) return [];
|
|
1661
|
+
let adjacent = [];
|
|
1662
|
+
const results = [];
|
|
1663
|
+
for (const [index, element] of source.entries()) {
|
|
1664
|
+
const inner = [];
|
|
1665
|
+
const local = [...query, ...adjacent];
|
|
1666
|
+
adjacent = [];
|
|
1667
|
+
let matched = false;
|
|
1668
|
+
for (const group of local) {
|
|
1669
|
+
const { type, combinator } = group[0];
|
|
1670
|
+
if (type === element.type || type === "*") {
|
|
1671
|
+
if (group.length === 1) {
|
|
1672
|
+
matched = true;
|
|
1673
|
+
} else if ([" ", ">"].includes(group[1].combinator)) {
|
|
1674
|
+
inner.push(group.slice(1));
|
|
1675
|
+
} else if (group[1].combinator === "+") {
|
|
1676
|
+
adjacent.push(group.slice(1));
|
|
1677
|
+
} else {
|
|
1678
|
+
query.push(group.slice(1));
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
if (combinator === " ") {
|
|
1682
|
+
inner.push(group);
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
if (matched) results.push(source[index]);
|
|
1686
|
+
results.push(...select(element.children, inner));
|
|
1687
|
+
}
|
|
1688
|
+
return results;
|
|
1689
|
+
}
|
|
1690
|
+
__name(select, "select");
|
|
1691
|
+
Element2.select = select;
|
|
1692
|
+
__name3(select, "select");
|
|
1693
|
+
function interpolate(expr, context) {
|
|
1694
|
+
expr = expr.trim();
|
|
1695
|
+
if (!/^[\w.]+$/.test(expr)) {
|
|
1696
|
+
return evaluate(expr, context) ?? "";
|
|
1697
|
+
}
|
|
1698
|
+
let value = context;
|
|
1699
|
+
for (const part of expr.split(".")) {
|
|
1700
|
+
value = value[part];
|
|
1701
|
+
if (isNullable(value)) return "";
|
|
1702
|
+
}
|
|
1703
|
+
return value ?? "";
|
|
1704
|
+
}
|
|
1705
|
+
__name(interpolate, "interpolate");
|
|
1706
|
+
Element2.interpolate = interpolate;
|
|
1707
|
+
__name3(interpolate, "interpolate");
|
|
1708
|
+
const tagRegExp1 = /(?<comment><!--[\s\S]*?-->)|(?<tag><(\/?)([^!\s>/]*)([^>]*?)\s*(\/?)>)/;
|
|
1709
|
+
const tagRegExp2 = /(?<comment><!--[\s\S]*?-->)|(?<tag><(\/?)([^!\s>/]*)([^>]*?)\s*(\/?)>)|(?<curly>\{(?<derivative>[@:/#][^\s}]*)?[\s\S]*?\})/;
|
|
1710
|
+
const attrRegExp1 = /([^\s=]+)(?:="(?<value1>[^"]*)"|='(?<value2>[^']*)')?/g;
|
|
1711
|
+
const attrRegExp2 = /([^\s=]+)(?:="(?<value1>[^"]*)"|='(?<value2>[^']*)'|=\{(?<curly>[^}]+)\})?/g;
|
|
1712
|
+
let Position;
|
|
1713
|
+
((Position2) => {
|
|
1714
|
+
Position2[Position2["OPEN"] = 0] = "OPEN";
|
|
1715
|
+
Position2[Position2["CLOSE"] = 1] = "CLOSE";
|
|
1716
|
+
Position2[Position2["EMPTY"] = 2] = "EMPTY";
|
|
1717
|
+
Position2[Position2["CONTINUE"] = 3] = "CONTINUE";
|
|
1718
|
+
})(Position || (Position = {}));
|
|
1719
|
+
function parse(source, context) {
|
|
1720
|
+
const tokens = [];
|
|
1721
|
+
function pushText(content) {
|
|
1722
|
+
if (content) tokens.push(content);
|
|
1723
|
+
}
|
|
1724
|
+
__name(pushText, "pushText");
|
|
1725
|
+
__name3(pushText, "pushText");
|
|
1726
|
+
const tagRegExp = context ? tagRegExp2 : tagRegExp1;
|
|
1727
|
+
let tagCap;
|
|
1728
|
+
let trimStart = true;
|
|
1729
|
+
while (tagCap = tagRegExp.exec(source)) {
|
|
1730
|
+
const { curly, comment, derivative } = tagCap.groups;
|
|
1731
|
+
const trimEnd = !curly;
|
|
1732
|
+
parseContent(source.slice(0, tagCap.index), trimStart, trimEnd);
|
|
1733
|
+
trimStart = trimEnd;
|
|
1734
|
+
source = source.slice(tagCap.index + tagCap[0].length);
|
|
1735
|
+
const [_, , , close, type, extra, empty] = tagCap;
|
|
1736
|
+
if (comment) continue;
|
|
1737
|
+
if (curly) {
|
|
1738
|
+
let name2 = "", position = 2;
|
|
1739
|
+
if (derivative) {
|
|
1740
|
+
name2 = derivative.slice(1);
|
|
1741
|
+
position = {
|
|
1742
|
+
"@": 2,
|
|
1743
|
+
"#": 0,
|
|
1744
|
+
"/": 1,
|
|
1745
|
+
":": 3
|
|
1746
|
+
/* CONTINUE */
|
|
1747
|
+
}[derivative[0]];
|
|
1748
|
+
}
|
|
1749
|
+
tokens.push({
|
|
1750
|
+
type: "curly",
|
|
1751
|
+
name: name2,
|
|
1752
|
+
position,
|
|
1753
|
+
source: curly,
|
|
1754
|
+
extra: curly.slice(1 + (derivative ?? "").length, -1)
|
|
1755
|
+
});
|
|
1756
|
+
continue;
|
|
1757
|
+
}
|
|
1758
|
+
tokens.push({
|
|
1759
|
+
type: "angle",
|
|
1760
|
+
source: _,
|
|
1761
|
+
name: type || Element2.Fragment,
|
|
1762
|
+
position: close ? 1 : empty ? 2 : 0,
|
|
1763
|
+
extra
|
|
1764
|
+
});
|
|
1765
|
+
}
|
|
1766
|
+
parseContent(source, trimStart, true);
|
|
1767
|
+
function parseContent(source2, trimStart2, trimEnd) {
|
|
1768
|
+
source2 = unescape(source2);
|
|
1769
|
+
if (trimStart2) source2 = source2.replace(/^\s*\n\s*/, "");
|
|
1770
|
+
if (trimEnd) source2 = source2.replace(/\s*\n\s*$/, "");
|
|
1771
|
+
pushText(source2);
|
|
1772
|
+
}
|
|
1773
|
+
__name(parseContent, "parseContent");
|
|
1774
|
+
__name3(parseContent, "parseContent");
|
|
1775
|
+
return parseTokens(foldTokens(tokens), context);
|
|
1776
|
+
}
|
|
1777
|
+
__name(parse, "parse");
|
|
1778
|
+
Element2.parse = parse;
|
|
1779
|
+
__name3(parse, "parse");
|
|
1780
|
+
function foldTokens(tokens) {
|
|
1781
|
+
const stack = [[{
|
|
1782
|
+
type: "angle",
|
|
1783
|
+
name: Element2.Fragment,
|
|
1784
|
+
position: 0,
|
|
1785
|
+
source: "",
|
|
1786
|
+
extra: "",
|
|
1787
|
+
children: { default: [] }
|
|
1788
|
+
}, "default"]];
|
|
1789
|
+
function pushToken(...tokens2) {
|
|
1790
|
+
const [token, slot] = stack[0];
|
|
1791
|
+
token.children[slot].push(...tokens2);
|
|
1792
|
+
}
|
|
1793
|
+
__name(pushToken, "pushToken");
|
|
1794
|
+
__name3(pushToken, "pushToken");
|
|
1795
|
+
for (const token of tokens) {
|
|
1796
|
+
if (typeof token === "string") {
|
|
1797
|
+
pushToken(token);
|
|
1798
|
+
continue;
|
|
1799
|
+
}
|
|
1800
|
+
const { name: name2, position } = token;
|
|
1801
|
+
if (position === 1) {
|
|
1802
|
+
if (stack[0][0].name === name2) {
|
|
1803
|
+
stack.shift();
|
|
1804
|
+
}
|
|
1805
|
+
} else if (position === 3) {
|
|
1806
|
+
stack[0][0].children[name2] = [];
|
|
1807
|
+
stack[0][1] = name2;
|
|
1808
|
+
} else if (position === 0) {
|
|
1809
|
+
pushToken(token);
|
|
1810
|
+
token.children = { default: [] };
|
|
1811
|
+
stack.unshift([token, "default"]);
|
|
1812
|
+
} else {
|
|
1813
|
+
pushToken(token);
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
return stack[stack.length - 1][0].children.default;
|
|
1817
|
+
}
|
|
1818
|
+
__name(foldTokens, "foldTokens");
|
|
1819
|
+
__name3(foldTokens, "foldTokens");
|
|
1820
|
+
function parseTokens(tokens, context) {
|
|
1821
|
+
const result = [];
|
|
1822
|
+
for (const token of tokens) {
|
|
1823
|
+
if (typeof token === "string") {
|
|
1824
|
+
result.push(Element2("text", { content: token }));
|
|
1825
|
+
} else if (token.type === "angle") {
|
|
1826
|
+
const attrs = {};
|
|
1827
|
+
const attrRegExp = context ? attrRegExp2 : attrRegExp1;
|
|
1828
|
+
let attrCap;
|
|
1829
|
+
while (attrCap = attrRegExp.exec(token.extra)) {
|
|
1830
|
+
const [, key, v1, v2 = v1, v3] = attrCap;
|
|
1831
|
+
if (v3) {
|
|
1832
|
+
attrs[key] = interpolate(v3, context);
|
|
1833
|
+
} else if (!isNullable(v2)) {
|
|
1834
|
+
attrs[key] = unescape(v2);
|
|
1835
|
+
} else if (key.startsWith("no-")) {
|
|
1836
|
+
attrs[key.slice(3)] = false;
|
|
1837
|
+
} else {
|
|
1838
|
+
attrs[key] = true;
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
result.push(Element2(token.name, attrs, token.children && parseTokens(token.children.default, context)));
|
|
1842
|
+
} else if (!token.name) {
|
|
1843
|
+
result.push(...toElementArray(interpolate(token.extra, context)));
|
|
1844
|
+
} else if (token.name === "if") {
|
|
1845
|
+
if (evaluate(token.extra, context)) {
|
|
1846
|
+
result.push(...parseTokens(token.children.default, context));
|
|
1847
|
+
} else {
|
|
1848
|
+
result.push(...parseTokens(token.children.else || [], context));
|
|
1849
|
+
}
|
|
1850
|
+
} else if (token.name === "each") {
|
|
1851
|
+
const [expr, ident] = token.extra.split(/\s+as\s+/);
|
|
1852
|
+
const items = interpolate(expr, context);
|
|
1853
|
+
if (!items || !items[Symbol.iterator]) continue;
|
|
1854
|
+
for (const item of items) {
|
|
1855
|
+
result.push(...parseTokens(token.children.default, { ...context, [ident]: item }));
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
return result;
|
|
1860
|
+
}
|
|
1861
|
+
__name(parseTokens, "parseTokens");
|
|
1862
|
+
__name3(parseTokens, "parseTokens");
|
|
1863
|
+
function visit(element, rules, session) {
|
|
1864
|
+
const { type, attrs, children } = element;
|
|
1865
|
+
if (typeof rules === "function") {
|
|
1866
|
+
return rules(element, session);
|
|
1867
|
+
} else {
|
|
1868
|
+
let result = rules[typeof type === "string" ? type : ""] ?? rules.default ?? true;
|
|
1869
|
+
if (typeof result === "function") {
|
|
1870
|
+
result = result(attrs, children, session);
|
|
1871
|
+
}
|
|
1872
|
+
return result;
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
__name(visit, "visit");
|
|
1876
|
+
__name3(visit, "visit");
|
|
1877
|
+
function transform(source, rules, session) {
|
|
1878
|
+
const elements = typeof source === "string" ? parse(source) : source;
|
|
1879
|
+
const output = [];
|
|
1880
|
+
elements.forEach((element) => {
|
|
1881
|
+
const { type, attrs, children } = element;
|
|
1882
|
+
const result = visit(element, rules, session);
|
|
1883
|
+
if (result === true) {
|
|
1884
|
+
output.push(Element2(type, attrs, transform(children, rules, session)));
|
|
1885
|
+
} else if (result !== false) {
|
|
1886
|
+
output.push(...toElementArray(result));
|
|
1887
|
+
}
|
|
1888
|
+
});
|
|
1889
|
+
return typeof source === "string" ? output.join("") : output;
|
|
1890
|
+
}
|
|
1891
|
+
__name(transform, "transform");
|
|
1892
|
+
Element2.transform = transform;
|
|
1893
|
+
__name3(transform, "transform");
|
|
1894
|
+
async function transformAsync(source, rules, session) {
|
|
1895
|
+
const elements = typeof source === "string" ? parse(source) : source;
|
|
1896
|
+
const children = (await Promise.all(elements.map(async (element) => {
|
|
1897
|
+
const { type, attrs, children: children2 } = element;
|
|
1898
|
+
const result = await visit(element, rules, session);
|
|
1899
|
+
if (result === true) {
|
|
1900
|
+
return [Element2(type, attrs, await transformAsync(children2, rules, session))];
|
|
1901
|
+
} else if (result !== false) {
|
|
1902
|
+
return toElementArray(result);
|
|
1903
|
+
} else {
|
|
1904
|
+
return [];
|
|
1905
|
+
}
|
|
1906
|
+
}))).flat(1);
|
|
1907
|
+
return typeof source === "string" ? children.join("") : children;
|
|
1908
|
+
}
|
|
1909
|
+
__name(transformAsync, "transformAsync");
|
|
1910
|
+
Element2.transformAsync = transformAsync;
|
|
1911
|
+
__name3(transformAsync, "transformAsync");
|
|
1912
|
+
function createFactory(type, ...keys) {
|
|
1913
|
+
return (...args) => {
|
|
1914
|
+
const element = Element2(type);
|
|
1915
|
+
keys.forEach((key, index) => {
|
|
1916
|
+
if (!isNullable(args[index])) {
|
|
1917
|
+
element.attrs[key] = args[index];
|
|
1918
|
+
}
|
|
1919
|
+
});
|
|
1920
|
+
if (args[keys.length]) {
|
|
1921
|
+
Object.assign(element.attrs, args[keys.length]);
|
|
1922
|
+
}
|
|
1923
|
+
return element;
|
|
1924
|
+
};
|
|
1925
|
+
}
|
|
1926
|
+
__name(createFactory, "createFactory");
|
|
1927
|
+
__name3(createFactory, "createFactory");
|
|
1928
|
+
Element2.warn = /* @__PURE__ */ __name3(() => {
|
|
1929
|
+
}, "warn");
|
|
1930
|
+
function createAssetFactory(type) {
|
|
1931
|
+
return (src, ...args) => {
|
|
1932
|
+
let prefix = "base64://";
|
|
1933
|
+
if (typeof args[0] === "string") {
|
|
1934
|
+
prefix = `data:${args.shift()};base64,`;
|
|
1935
|
+
}
|
|
1936
|
+
if (is("Buffer", src)) {
|
|
1937
|
+
src = prefix + src.toString("base64");
|
|
1938
|
+
} else if (is("ArrayBuffer", src)) {
|
|
1939
|
+
src = prefix + Binary.toBase64(src);
|
|
1940
|
+
} else if (ArrayBuffer.isView(src)) {
|
|
1941
|
+
src = prefix + Binary.toBase64(src.buffer);
|
|
1942
|
+
}
|
|
1943
|
+
if (src.startsWith("base64://")) {
|
|
1944
|
+
(0, Element2.warn)(`protocol "base64:" is deprecated and will be removed in the future, please use "data:" instead`);
|
|
1945
|
+
}
|
|
1946
|
+
return Element2(type, { ...args[0], src });
|
|
1947
|
+
};
|
|
1948
|
+
}
|
|
1949
|
+
__name(createAssetFactory, "createAssetFactory");
|
|
1950
|
+
__name3(createAssetFactory, "createAssetFactory");
|
|
1951
|
+
Element2.text = createFactory("text", "content");
|
|
1952
|
+
Element2.at = createFactory("at", "id");
|
|
1953
|
+
Element2.sharp = createFactory("sharp", "id");
|
|
1954
|
+
Element2.quote = createFactory("quote", "id");
|
|
1955
|
+
Element2.image = createAssetFactory("img");
|
|
1956
|
+
Element2.img = createAssetFactory("img");
|
|
1957
|
+
Element2.video = createAssetFactory("video");
|
|
1958
|
+
Element2.audio = createAssetFactory("audio");
|
|
1959
|
+
Element2.file = createAssetFactory("file");
|
|
1960
|
+
function i18n(path5, children) {
|
|
1961
|
+
return Element2("i18n", typeof path5 === "string" ? { path: path5 } : path5, children);
|
|
1962
|
+
}
|
|
1963
|
+
__name(i18n, "i18n");
|
|
1964
|
+
Element2.i18n = i18n;
|
|
1965
|
+
__name3(i18n, "i18n");
|
|
1966
|
+
})(Element || (Element = {}));
|
|
1967
|
+
module2.exports = Element;
|
|
1968
|
+
}
|
|
1969
|
+
});
|
|
1970
|
+
var lib_default = require_index();
|
|
1971
|
+
|
|
1972
|
+
// ../../node_modules/@satorijs/protocol/lib/index.mjs
|
|
1973
|
+
var __defProp4 = Object.defineProperty;
|
|
1974
|
+
var __name4 = /* @__PURE__ */ __name((target, value) => __defProp4(target, "name", { value, configurable: true }), "__name");
|
|
1975
|
+
function Field(name2) {
|
|
1976
|
+
return { name: name2 };
|
|
1977
|
+
}
|
|
1978
|
+
__name(Field, "Field");
|
|
1979
|
+
__name4(Field, "Field");
|
|
1980
|
+
function Method(name2, fields, isForm = false) {
|
|
1981
|
+
return { name: name2, fields: fields.map(Field), isForm };
|
|
1982
|
+
}
|
|
1983
|
+
__name(Method, "Method");
|
|
1984
|
+
__name4(Method, "Method");
|
|
1985
|
+
var Methods = {
|
|
1986
|
+
"channel.get": Method("getChannel", ["channel_id", "guild_id"]),
|
|
1987
|
+
"channel.list": Method("getChannelList", ["guild_id", "next"]),
|
|
1988
|
+
"channel.create": Method("createChannel", ["guild_id", "data"]),
|
|
1989
|
+
"channel.update": Method("updateChannel", ["channel_id", "data"]),
|
|
1990
|
+
"channel.delete": Method("deleteChannel", ["channel_id"]),
|
|
1991
|
+
"channel.mute": Method("muteChannel", ["channel_id", "guild_id", "enable"]),
|
|
1992
|
+
"message.create": Method("createMessage", ["channel_id", "content", "referrer"]),
|
|
1993
|
+
"message.update": Method("editMessage", ["channel_id", "message_id", "content"]),
|
|
1994
|
+
"message.delete": Method("deleteMessage", ["channel_id", "message_id"]),
|
|
1995
|
+
"message.get": Method("getMessage", ["channel_id", "message_id"]),
|
|
1996
|
+
"message.list": Method("getMessageList", ["channel_id", "next", "direction", "limit", "order"]),
|
|
1997
|
+
"reaction.create": Method("createReaction", ["channel_id", "message_id", "emoji"]),
|
|
1998
|
+
"reaction.delete": Method("deleteReaction", ["channel_id", "message_id", "emoji", "user_id"]),
|
|
1999
|
+
"reaction.clear": Method("clearReaction", ["channel_id", "message_id", "emoji"]),
|
|
2000
|
+
"reaction.list": Method("getReactionList", ["channel_id", "message_id", "emoji", "next"]),
|
|
2001
|
+
"upload.create": Method("createUpload", [], true),
|
|
2002
|
+
"guild.get": Method("getGuild", ["guild_id"]),
|
|
2003
|
+
"guild.list": Method("getGuildList", ["next"]),
|
|
2004
|
+
"guild.member.get": Method("getGuildMember", ["guild_id", "user_id"]),
|
|
2005
|
+
"guild.member.list": Method("getGuildMemberList", ["guild_id", "next"]),
|
|
2006
|
+
"guild.member.kick": Method("kickGuildMember", ["guild_id", "user_id", "permanent"]),
|
|
2007
|
+
"guild.member.mute": Method("muteGuildMember", ["guild_id", "user_id", "duration", "reason"]),
|
|
2008
|
+
"guild.member.role.set": Method("setGuildMemberRole", ["guild_id", "user_id", "role_id"]),
|
|
2009
|
+
"guild.member.role.unset": Method("unsetGuildMemberRole", ["guild_id", "user_id", "role_id"]),
|
|
2010
|
+
"guild.member.role.list": Method("getGuildMemberRoleList", ["guild_id", "user_id", "next"]),
|
|
2011
|
+
"guild.role.list": Method("getGuildRoleList", ["guild_id", "next"]),
|
|
2012
|
+
"guild.role.create": Method("createGuildRole", ["guild_id", "data"]),
|
|
2013
|
+
"guild.role.update": Method("updateGuildRole", ["guild_id", "role_id", "data"]),
|
|
2014
|
+
"guild.role.delete": Method("deleteGuildRole", ["guild_id", "role_id"]),
|
|
2015
|
+
"login.get": Method("getLogin", []),
|
|
2016
|
+
"user.get": Method("getUser", ["user_id"]),
|
|
2017
|
+
"user.channel.create": Method("createDirectChannel", ["user_id", "guild_id"]),
|
|
2018
|
+
"friend.list": Method("getFriendList", ["next"]),
|
|
2019
|
+
"friend.delete": Method("deleteFriend", ["user_id"]),
|
|
2020
|
+
"friend.approve": Method("handleFriendRequest", ["message_id", "approve", "comment"]),
|
|
2021
|
+
"guild.approve": Method("handleGuildRequest", ["message_id", "approve", "comment"]),
|
|
2022
|
+
"guild.member.approve": Method("handleGuildMemberRequest", ["message_id", "approve", "comment"])
|
|
2023
|
+
};
|
|
2024
|
+
var Channel;
|
|
2025
|
+
((Channel2) => {
|
|
2026
|
+
let Type;
|
|
2027
|
+
((Type2) => {
|
|
2028
|
+
Type2[Type2["TEXT"] = 0] = "TEXT";
|
|
2029
|
+
Type2[Type2["DIRECT"] = 1] = "DIRECT";
|
|
2030
|
+
Type2[Type2["CATEGORY"] = 2] = "CATEGORY";
|
|
2031
|
+
Type2[Type2["VOICE"] = 3] = "VOICE";
|
|
2032
|
+
})(Type = Channel2.Type || (Channel2.Type = {}));
|
|
2033
|
+
})(Channel || (Channel = {}));
|
|
2034
|
+
function Resource(attrs = [], children = [], content) {
|
|
2035
|
+
return { attrs, children, content };
|
|
2036
|
+
}
|
|
2037
|
+
__name(Resource, "Resource");
|
|
2038
|
+
__name4(Resource, "Resource");
|
|
2039
|
+
((Resource2) => {
|
|
2040
|
+
const Definitions = {
|
|
2041
|
+
user: Resource2(["id", "name", "nick", "avatar", "isBot"]),
|
|
2042
|
+
member: Resource2(["name", "nick", "avatar"]),
|
|
2043
|
+
channel: Resource2(["id", "type", "name"]),
|
|
2044
|
+
guild: Resource2(["id", "name", "avatar"]),
|
|
2045
|
+
quote: Resource2(["id"], ["quote", "user", "member", "channel"], "content")
|
|
2046
|
+
};
|
|
2047
|
+
function encode(type, data) {
|
|
2048
|
+
const resource = Definitions[type];
|
|
2049
|
+
const element = lib_default(type, pick(data, resource.attrs));
|
|
2050
|
+
for (const key of resource.children) {
|
|
2051
|
+
if (isNullable(data[key])) continue;
|
|
2052
|
+
element.children.push(encode(key, data[key]));
|
|
2053
|
+
}
|
|
2054
|
+
if (resource.content && !isNullable(data[resource.content])) {
|
|
2055
|
+
element.children.push(...lib_default.parse(data[resource.content]));
|
|
2056
|
+
}
|
|
2057
|
+
return element;
|
|
2058
|
+
}
|
|
2059
|
+
__name(encode, "encode");
|
|
2060
|
+
Resource2.encode = encode;
|
|
2061
|
+
__name4(encode, "encode");
|
|
2062
|
+
function decode(element) {
|
|
2063
|
+
const data = element.attrs;
|
|
2064
|
+
const resource = Definitions[element.type];
|
|
2065
|
+
for (const key of resource.children) {
|
|
2066
|
+
const index = element.children.findIndex((el) => el.type === key);
|
|
2067
|
+
if (index === -1) continue;
|
|
2068
|
+
const [child] = element.children.splice(index, 1);
|
|
2069
|
+
data[key] = decode(child);
|
|
2070
|
+
}
|
|
2071
|
+
if (resource.content && element.children.length) {
|
|
2072
|
+
data[resource.content] = element.children.join("");
|
|
2073
|
+
}
|
|
2074
|
+
return data;
|
|
2075
|
+
}
|
|
2076
|
+
__name(decode, "decode");
|
|
2077
|
+
Resource2.decode = decode;
|
|
2078
|
+
__name4(decode, "decode");
|
|
2079
|
+
})(Resource || (Resource = {}));
|
|
2080
|
+
function transformKey(source, callback) {
|
|
2081
|
+
if (!source || typeof source !== "object") return source;
|
|
2082
|
+
if (Array.isArray(source)) return source.map((value) => transformKey(value, callback));
|
|
2083
|
+
return Object.fromEntries(Object.entries(source).map(([key, value]) => {
|
|
2084
|
+
if (key.startsWith("_") || key === "referrer") return [key, value];
|
|
2085
|
+
return [callback(key), transformKey(value, callback)];
|
|
2086
|
+
}));
|
|
2087
|
+
}
|
|
2088
|
+
__name(transformKey, "transformKey");
|
|
2089
|
+
__name4(transformKey, "transformKey");
|
|
2090
|
+
var Opcode = /* @__PURE__ */ ((Opcode2) => {
|
|
2091
|
+
Opcode2[Opcode2["EVENT"] = 0] = "EVENT";
|
|
2092
|
+
Opcode2[Opcode2["PING"] = 1] = "PING";
|
|
2093
|
+
Opcode2[Opcode2["PONG"] = 2] = "PONG";
|
|
2094
|
+
Opcode2[Opcode2["IDENTIFY"] = 3] = "IDENTIFY";
|
|
2095
|
+
Opcode2[Opcode2["READY"] = 4] = "READY";
|
|
2096
|
+
Opcode2[Opcode2["META"] = 5] = "META";
|
|
2097
|
+
return Opcode2;
|
|
2098
|
+
})(Opcode || {});
|
|
2099
|
+
var WebSocket;
|
|
2100
|
+
((WebSocket2) => {
|
|
2101
|
+
WebSocket2.CONNECTING = 0;
|
|
2102
|
+
WebSocket2.OPEN = 1;
|
|
2103
|
+
WebSocket2.CLOSING = 2;
|
|
2104
|
+
WebSocket2.CLOSED = 3;
|
|
2105
|
+
})(WebSocket || (WebSocket = {}));
|
|
2106
|
+
|
|
2107
|
+
// src/satori.ts
|
|
2108
|
+
function resolveSatoriEndpoint(ctx) {
|
|
2109
|
+
const url = ctx.satori?.server?.url ?? "/satori";
|
|
2110
|
+
const clean = url.startsWith("undefined") ? url.slice(9) : url;
|
|
2111
|
+
if (/^https?:\/\//i.test(clean)) return clean;
|
|
2112
|
+
const base = ctx.server?.selfUrl ?? ctx.server?.config?.selfUrl ?? "";
|
|
2113
|
+
return `${base}${clean.startsWith("/") ? clean : `/${clean}`}`;
|
|
2114
|
+
}
|
|
2115
|
+
__name(resolveSatoriEndpoint, "resolveSatoriEndpoint");
|
|
2116
|
+
function toSatoriEventUrl(endpoint) {
|
|
2117
|
+
const url = new URL(endpoint);
|
|
2118
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
2119
|
+
url.pathname = `${url.pathname.replace(/\/+$/, "")}/v1/events`;
|
|
2120
|
+
url.search = "";
|
|
2121
|
+
return url.href;
|
|
2122
|
+
}
|
|
2123
|
+
__name(toSatoriEventUrl, "toSatoriEventUrl");
|
|
2124
|
+
|
|
2125
|
+
// src/gateway.ts
|
|
2126
|
+
var WS_OPEN = 1;
|
|
2127
|
+
var RECONNECT_MAX_DELAY = 3e4;
|
|
2128
|
+
function getObject2(value) {
|
|
2129
|
+
return typeof value === "object" && value !== null ? value : {};
|
|
2130
|
+
}
|
|
2131
|
+
__name(getObject2, "getObject");
|
|
2132
|
+
function getString3(value) {
|
|
2133
|
+
return typeof value === "string" ? value : "";
|
|
2134
|
+
}
|
|
2135
|
+
__name(getString3, "getString");
|
|
2136
|
+
function getNumber2(value) {
|
|
2137
|
+
const num = Number(value);
|
|
2138
|
+
return Number.isFinite(num) ? num : 0;
|
|
2139
|
+
}
|
|
2140
|
+
__name(getNumber2, "getNumber");
|
|
2141
|
+
var _SatoriGateway = class _SatoriGateway {
|
|
2142
|
+
constructor(ctx, config, database, recorder, logger, onPayload) {
|
|
2143
|
+
this.ctx = ctx;
|
|
2144
|
+
this.config = config;
|
|
2145
|
+
this.database = database;
|
|
2146
|
+
this.recorder = recorder;
|
|
2147
|
+
this.logger = logger;
|
|
2148
|
+
this.onPayload = onPayload;
|
|
2149
|
+
this.stopped = true;
|
|
2150
|
+
this.retry = 0;
|
|
2151
|
+
this.sequence = 0;
|
|
2152
|
+
this.logins = [];
|
|
2153
|
+
this.online = false;
|
|
2154
|
+
}
|
|
2155
|
+
async start() {
|
|
2156
|
+
this.stopped = false;
|
|
2157
|
+
this.retry = 0;
|
|
2158
|
+
this.sequence = await this.loadSequence();
|
|
2159
|
+
this.connect();
|
|
2160
|
+
}
|
|
2161
|
+
dispose() {
|
|
2162
|
+
this.stopped = true;
|
|
2163
|
+
this.pingDispose?.();
|
|
2164
|
+
this.reconnectDispose?.();
|
|
2165
|
+
this.socket?.close();
|
|
2166
|
+
this.socket = void 0;
|
|
2167
|
+
this.setOnline(false);
|
|
2168
|
+
}
|
|
2169
|
+
getLogins() {
|
|
2170
|
+
return this.logins.map((item) => ({ ...item }));
|
|
2171
|
+
}
|
|
2172
|
+
async loadSequence() {
|
|
2173
|
+
const value = await this.database.getMeta("satori:sn");
|
|
2174
|
+
return getNumber2(value);
|
|
2175
|
+
}
|
|
2176
|
+
connect() {
|
|
2177
|
+
if (this.stopped) return;
|
|
2178
|
+
let socket;
|
|
2179
|
+
try {
|
|
2180
|
+
socket = this.ctx.http.ws(toSatoriEventUrl(resolveSatoriEndpoint(this.ctx)));
|
|
2181
|
+
} catch (error) {
|
|
2182
|
+
this.logger.warn("Satori 连接创建失败:", error);
|
|
2183
|
+
this.scheduleReconnect();
|
|
2184
|
+
return;
|
|
2185
|
+
}
|
|
2186
|
+
this.socket = socket;
|
|
2187
|
+
socket.addEventListener("open", () => {
|
|
2188
|
+
if (this.socket !== socket) {
|
|
2189
|
+
socket.close();
|
|
2190
|
+
return;
|
|
2191
|
+
}
|
|
2192
|
+
this.retry = 0;
|
|
2193
|
+
this.setOnline(true);
|
|
2194
|
+
socket.send(JSON.stringify({
|
|
2195
|
+
op: Opcode.IDENTIFY,
|
|
2196
|
+
body: {
|
|
2197
|
+
token: this.token,
|
|
2198
|
+
sn: this.sequence || void 0
|
|
2199
|
+
}
|
|
2200
|
+
}));
|
|
2201
|
+
if (!this.pingDispose) {
|
|
2202
|
+
this.pingDispose = this.ctx.setInterval(() => {
|
|
2203
|
+
if (this.socket?.readyState === WS_OPEN) {
|
|
2204
|
+
this.socket.send(JSON.stringify({ op: Opcode.PING, body: {} }));
|
|
2205
|
+
}
|
|
2206
|
+
}, 1e4);
|
|
2207
|
+
}
|
|
2208
|
+
});
|
|
2209
|
+
socket.addEventListener("message", (event) => {
|
|
2210
|
+
void this.handleMessage(event.data).catch((error) => {
|
|
2211
|
+
this.logger.warn("Satori 事件处理失败:", error);
|
|
2212
|
+
});
|
|
2213
|
+
});
|
|
2214
|
+
socket.addEventListener("close", () => {
|
|
2215
|
+
if (this.socket === socket) this.socket = void 0;
|
|
2216
|
+
this.pingDispose?.();
|
|
2217
|
+
this.pingDispose = void 0;
|
|
2218
|
+
this.setOnline(false);
|
|
2219
|
+
this.scheduleReconnect();
|
|
2220
|
+
});
|
|
2221
|
+
socket.addEventListener("error", () => {
|
|
2222
|
+
socket.close();
|
|
2223
|
+
});
|
|
2224
|
+
}
|
|
2225
|
+
get token() {
|
|
2226
|
+
return getString3(this.ctx.satori?.server?.config?.token);
|
|
2227
|
+
}
|
|
2228
|
+
scheduleReconnect() {
|
|
2229
|
+
if (this.stopped || this.reconnectDispose) return;
|
|
2230
|
+
const delay = Math.min(RECONNECT_MAX_DELAY, 1e3 * 2 ** this.retry);
|
|
2231
|
+
this.retry += 1;
|
|
2232
|
+
this.logger.logInfo("Satori 将在", delay, "ms 后重连");
|
|
2233
|
+
this.reconnectDispose = this.ctx.setTimeout(() => {
|
|
2234
|
+
this.reconnectDispose = void 0;
|
|
2235
|
+
this.connect();
|
|
2236
|
+
}, delay);
|
|
2237
|
+
}
|
|
2238
|
+
async handleMessage(data) {
|
|
2239
|
+
let payload;
|
|
2240
|
+
try {
|
|
2241
|
+
payload = JSON.parse(String(data));
|
|
2242
|
+
} catch {
|
|
2243
|
+
this.logger.warn("Satori 消息解析失败");
|
|
2244
|
+
return;
|
|
2245
|
+
}
|
|
2246
|
+
if (payload.op === Opcode.READY) {
|
|
2247
|
+
const body2 = getObject2(payload.body);
|
|
2248
|
+
this.logins = this.normalizeLogins(body2.logins);
|
|
2249
|
+
this.onPayload({ kind: "ready", logins: this.getLogins() });
|
|
2250
|
+
return;
|
|
2251
|
+
}
|
|
2252
|
+
if (payload.op !== Opcode.EVENT) return;
|
|
2253
|
+
const body = getObject2(payload.body);
|
|
2254
|
+
const sn = getNumber2(body.sn);
|
|
2255
|
+
if (sn) {
|
|
2256
|
+
this.sequence = sn;
|
|
2257
|
+
void this.database.setMeta("satori:sn", sn).catch((error) => {
|
|
2258
|
+
this.logger.warn("Satori sequence 保存失败:", error);
|
|
2259
|
+
});
|
|
2260
|
+
}
|
|
2261
|
+
const type = getString3(body.type);
|
|
2262
|
+
if (type === "login-added" || type === "login-updated") {
|
|
2263
|
+
const next = this.normalizeLogins([body.login]);
|
|
2264
|
+
if (next.length) {
|
|
2265
|
+
this.logins = this.logins.filter((item) => {
|
|
2266
|
+
return !(item.platform === next[0].platform && item.selfId === next[0].selfId);
|
|
2267
|
+
});
|
|
2268
|
+
this.logins.push(next[0]);
|
|
2269
|
+
this.onPayload({ kind: "ready", logins: this.getLogins() });
|
|
2270
|
+
}
|
|
2271
|
+
return;
|
|
2272
|
+
}
|
|
2273
|
+
if (type === "login-removed") {
|
|
2274
|
+
const login2 = getObject2(body.login);
|
|
2275
|
+
const loginUser2 = getObject2(login2.user);
|
|
2276
|
+
const platform2 = getString3(body.platform) || getString3(login2.platform);
|
|
2277
|
+
const selfId2 = getString3(body.self_id) || getString3(body.selfId) || getString3(loginUser2.id);
|
|
2278
|
+
this.logins = this.logins.filter((item) => {
|
|
2279
|
+
return !(item.platform === platform2 && item.selfId === selfId2);
|
|
2280
|
+
});
|
|
2281
|
+
this.onPayload({ kind: "ready", logins: this.getLogins() });
|
|
2282
|
+
return;
|
|
2283
|
+
}
|
|
2284
|
+
const login = getObject2(body.login);
|
|
2285
|
+
const loginUser = getObject2(login.user);
|
|
2286
|
+
const platform = getString3(body.platform) || getString3(login.platform);
|
|
2287
|
+
const selfId = getString3(body.self_id) || getString3(body.selfId) || getString3(loginUser.id);
|
|
2288
|
+
const event = {
|
|
2289
|
+
type: getString3(body.type),
|
|
2290
|
+
platform,
|
|
2291
|
+
selfId,
|
|
2292
|
+
timestamp: getNumber2(body.timestamp) || Date.now(),
|
|
2293
|
+
sn,
|
|
2294
|
+
body
|
|
2295
|
+
};
|
|
2296
|
+
if (this.isBlocked(platform)) return;
|
|
2297
|
+
try {
|
|
2298
|
+
await this.recorder.handleEvent(body);
|
|
2299
|
+
} catch (error) {
|
|
2300
|
+
this.logger.warn("Satori 消息写入失败:", error);
|
|
2301
|
+
}
|
|
2302
|
+
this.onPayload({ kind: "event", event });
|
|
2303
|
+
}
|
|
2304
|
+
normalizeLogins(value) {
|
|
2305
|
+
if (!Array.isArray(value)) return [];
|
|
2306
|
+
const result = [];
|
|
2307
|
+
for (const item of value) {
|
|
2308
|
+
const login = getObject2(item);
|
|
2309
|
+
const user = getObject2(login.user);
|
|
2310
|
+
const platform = getString3(login.platform) || getString3(user.platform);
|
|
2311
|
+
const selfId = getString3(login.self_id) || getString3(login.selfId) || getString3(user.id);
|
|
2312
|
+
if (!platform || !selfId || this.isBlocked(platform)) continue;
|
|
2313
|
+
result.push({
|
|
2314
|
+
platform,
|
|
2315
|
+
selfId,
|
|
2316
|
+
name: getString3(user.name) || getString3(user.nick) || getString3(user.nickname) || selfId,
|
|
2317
|
+
avatar: getString3(user.avatar) || void 0,
|
|
2318
|
+
status: getNumber2(login.status),
|
|
2319
|
+
features: Array.isArray(login.features) ? login.features.map(String) : []
|
|
2320
|
+
});
|
|
2321
|
+
}
|
|
2322
|
+
return result;
|
|
2323
|
+
}
|
|
2324
|
+
isBlocked(platform) {
|
|
2325
|
+
return (this.config.blockedPlatforms ?? []).some((item) => {
|
|
2326
|
+
return item.exactMatch ? platform === item.platformName : platform.includes(item.platformName);
|
|
2327
|
+
});
|
|
2328
|
+
}
|
|
2329
|
+
setOnline(online) {
|
|
2330
|
+
if (this.online === online) return;
|
|
2331
|
+
this.online = online;
|
|
2332
|
+
this.onPayload({ kind: "status", online });
|
|
2333
|
+
}
|
|
2334
|
+
};
|
|
2335
|
+
__name(_SatoriGateway, "SatoriGateway");
|
|
2336
|
+
var SatoriGateway = _SatoriGateway;
|
|
2337
|
+
|
|
1002
2338
|
// src/media.ts
|
|
1003
2339
|
var import_node_crypto2 = require("node:crypto");
|
|
1004
2340
|
var import_node_fs = require("node:fs");
|
|
@@ -1357,26 +2693,26 @@ var KOISHI_STATUS_I18N_FALLBACK = {
|
|
|
1357
2693
|
"commands.status.messages.status.2": "连接中",
|
|
1358
2694
|
"commands.status.messages.status.3": "异常"
|
|
1359
2695
|
};
|
|
1360
|
-
function
|
|
2696
|
+
function getString4(value) {
|
|
1361
2697
|
return typeof value === "string" ? value : "";
|
|
1362
2698
|
}
|
|
1363
|
-
__name(
|
|
2699
|
+
__name(getString4, "getString");
|
|
1364
2700
|
function getMessageId(value) {
|
|
1365
|
-
const raw =
|
|
2701
|
+
const raw = getObject3(value).id ?? getObject3(value).message_id;
|
|
1366
2702
|
return raw == null ? "" : String(raw);
|
|
1367
2703
|
}
|
|
1368
2704
|
__name(getMessageId, "getMessageId");
|
|
1369
|
-
function
|
|
2705
|
+
function getNumber3(value) {
|
|
1370
2706
|
const num = Number(value);
|
|
1371
2707
|
return Number.isFinite(num) ? num : 0;
|
|
1372
2708
|
}
|
|
1373
|
-
__name(
|
|
1374
|
-
function
|
|
2709
|
+
__name(getNumber3, "getNumber");
|
|
2710
|
+
function getObject3(value) {
|
|
1375
2711
|
return typeof value === "object" && value !== null ? value : {};
|
|
1376
2712
|
}
|
|
1377
|
-
__name(
|
|
2713
|
+
__name(getObject3, "getObject");
|
|
1378
2714
|
function toSatoriElement(value) {
|
|
1379
|
-
const raw =
|
|
2715
|
+
const raw = getObject3(value);
|
|
1380
2716
|
const rawAttrs = raw.attrs ?? raw.data;
|
|
1381
2717
|
const attrs = typeof rawAttrs === "object" && rawAttrs !== null ? rawAttrs : {};
|
|
1382
2718
|
const children = Array.isArray(raw.children) ? raw.children.map(toSatoriElement) : [];
|
|
@@ -1396,37 +2732,37 @@ function toSegments(elements, resolveI18n) {
|
|
|
1396
2732
|
for (const raw of elements) {
|
|
1397
2733
|
const element = toSatoriElement(raw);
|
|
1398
2734
|
const attrs = element.attrs ?? {};
|
|
1399
|
-
const type =
|
|
2735
|
+
const type = getString4(element.type);
|
|
1400
2736
|
if (type === "text") {
|
|
1401
|
-
result.push({ type: "text", text:
|
|
2737
|
+
result.push({ type: "text", text: getString4(attrs.content) || getString4(attrs.text) });
|
|
1402
2738
|
} else if (type === "at") {
|
|
1403
|
-
const id =
|
|
1404
|
-
const name2 =
|
|
2739
|
+
const id = getString4(attrs.id) || getString4(attrs.qq);
|
|
2740
|
+
const name2 = getString4(attrs.name) || (attrs.type === "all" ? "所有人" : id);
|
|
1405
2741
|
result.push({ type: "at", qq: id, text: name2.startsWith("@") ? name2 : `@${name2}` });
|
|
1406
2742
|
} else if (type === "img" || type === "image") {
|
|
1407
|
-
const src =
|
|
1408
|
-
result.push({ type: "image", file: src, url: src, summary:
|
|
2743
|
+
const src = getString4(attrs.src) || getString4(attrs.url) || getString4(attrs.file);
|
|
2744
|
+
result.push({ type: "image", file: src, url: src, summary: getString4(attrs.title) });
|
|
1409
2745
|
} else if (type === "audio" || type === "record") {
|
|
1410
|
-
const src =
|
|
2746
|
+
const src = getString4(attrs.src) || getString4(attrs.url) || getString4(attrs.file);
|
|
1411
2747
|
result.push({ type: "record", file: src, url: src });
|
|
1412
2748
|
} else if (type === "video") {
|
|
1413
|
-
const src =
|
|
2749
|
+
const src = getString4(attrs.src) || getString4(attrs.url) || getString4(attrs.file);
|
|
1414
2750
|
result.push({ type: "video", file: src, url: src });
|
|
1415
2751
|
} else if (type === "file") {
|
|
1416
|
-
const src =
|
|
1417
|
-
result.push({ type: "file", file: src, url: src, name:
|
|
2752
|
+
const src = getString4(attrs.src) || getString4(attrs.url) || getString4(attrs.file);
|
|
2753
|
+
result.push({ type: "file", file: src, url: src, name: getString4(attrs.name) });
|
|
1418
2754
|
} else if (type === "quote") {
|
|
1419
|
-
result.push({ type: "reply", id:
|
|
2755
|
+
result.push({ type: "reply", id: getString4(attrs.id) });
|
|
1420
2756
|
} else if (type === "json") {
|
|
1421
|
-
result.push({ type: "json", data:
|
|
2757
|
+
result.push({ type: "json", data: getString4(attrs.data) || getString4(attrs.content) });
|
|
1422
2758
|
} else if (type === "xml") {
|
|
1423
|
-
result.push({ type: "xml", data:
|
|
2759
|
+
result.push({ type: "xml", data: getString4(attrs.data) || getString4(attrs.content) });
|
|
1424
2760
|
} else if (type === "markdown") {
|
|
1425
|
-
result.push({ type: "markdown", content:
|
|
2761
|
+
result.push({ type: "markdown", content: getString4(attrs.content) });
|
|
1426
2762
|
} else if (isForwardContainer(element)) {
|
|
1427
2763
|
result.push({
|
|
1428
2764
|
type: "forward",
|
|
1429
|
-
id:
|
|
2765
|
+
id: getString4(attrs.id),
|
|
1430
2766
|
content: toForwardNodes(element.children ?? [], resolveI18n) ?? []
|
|
1431
2767
|
});
|
|
1432
2768
|
} else if (type === "p") {
|
|
@@ -1435,7 +2771,7 @@ function toSegments(elements, resolveI18n) {
|
|
|
1435
2771
|
} else if (type === "br") {
|
|
1436
2772
|
result.push({ type: "text", text: "\n" });
|
|
1437
2773
|
} else if (type === "i18n") {
|
|
1438
|
-
const path5 =
|
|
2774
|
+
const path5 = getString4(attrs.path);
|
|
1439
2775
|
const resolved = resolveI18n ? resolveI18n(attrs) : "";
|
|
1440
2776
|
result.push({ type: "text", text: resolved || `[${path5 || "i18n"}]` });
|
|
1441
2777
|
} else if (element.children?.length) {
|
|
@@ -1466,12 +2802,12 @@ function toForwardNodes(elements, resolveI18n) {
|
|
|
1466
2802
|
const authorAttrs = author?.attrs ?? {};
|
|
1467
2803
|
const content = children.filter((item) => item.type !== "author");
|
|
1468
2804
|
nodes.push({
|
|
1469
|
-
message_id:
|
|
1470
|
-
time:
|
|
2805
|
+
message_id: getString4(attrs.id),
|
|
2806
|
+
time: getNumber3(authorAttrs.time) || getNumber3(attrs.time),
|
|
1471
2807
|
sender: {
|
|
1472
|
-
user_id:
|
|
1473
|
-
nickname:
|
|
1474
|
-
avatar:
|
|
2808
|
+
user_id: getString4(authorAttrs.id),
|
|
2809
|
+
nickname: getString4(authorAttrs.name),
|
|
2810
|
+
avatar: getString4(authorAttrs.avatar)
|
|
1475
2811
|
},
|
|
1476
2812
|
message: toSegments(content, resolveI18n)
|
|
1477
2813
|
});
|
|
@@ -1486,7 +2822,7 @@ function detectKind(elements) {
|
|
|
1486
2822
|
while (stack.length) {
|
|
1487
2823
|
const element = stack.pop();
|
|
1488
2824
|
if (!element) continue;
|
|
1489
|
-
const type =
|
|
2825
|
+
const type = getString4(element.type);
|
|
1490
2826
|
if (isForwardContainer(element)) return "forward";
|
|
1491
2827
|
if (type === "img" || type === "image" || type === "mface") return "image";
|
|
1492
2828
|
if (type === "audio" || type === "record") return "voice";
|
|
@@ -1503,7 +2839,7 @@ function forwardId(elements) {
|
|
|
1503
2839
|
const element = stack.pop();
|
|
1504
2840
|
if (!element) continue;
|
|
1505
2841
|
if (isForwardContainer(element)) {
|
|
1506
|
-
const id =
|
|
2842
|
+
const id = getString4(element.attrs?.id);
|
|
1507
2843
|
if (id) return id;
|
|
1508
2844
|
}
|
|
1509
2845
|
stack.push(...element.children ?? []);
|
|
@@ -1656,10 +2992,10 @@ var _SelfMessageRecorder = class _SelfMessageRecorder {
|
|
|
1656
2992
|
if (session.type !== "send") return;
|
|
1657
2993
|
const platform = session.platform || "";
|
|
1658
2994
|
const selfId = session.selfId || "";
|
|
1659
|
-
const event =
|
|
1660
|
-
const eventChannel =
|
|
1661
|
-
const eventMessage =
|
|
1662
|
-
const channelId = session.channelId ||
|
|
2995
|
+
const event = getObject3(session.event);
|
|
2996
|
+
const eventChannel = getObject3(event.channel);
|
|
2997
|
+
const eventMessage = getObject3(event.message);
|
|
2998
|
+
const channelId = session.channelId || getString4(eventChannel.id);
|
|
1663
2999
|
if (this.isBlocked(platform) || !platform || !selfId || !channelId) return;
|
|
1664
3000
|
const messageId = session.messageId || getMessageId(eventMessage);
|
|
1665
3001
|
if (messageId) {
|
|
@@ -1691,7 +3027,7 @@ var _SelfMessageRecorder = class _SelfMessageRecorder {
|
|
|
1691
3027
|
});
|
|
1692
3028
|
}
|
|
1693
3029
|
resolveI18nElement(attrs) {
|
|
1694
|
-
const path5 =
|
|
3030
|
+
const path5 = getString4(attrs.path);
|
|
1695
3031
|
if (!path5 || !this.ctx.i18n) return `[${path5 || "i18n"}]`;
|
|
1696
3032
|
try {
|
|
1697
3033
|
const locales = this.ctx.i18n.fallback([]);
|
|
@@ -1737,9 +3073,9 @@ var _SelfMessageRecorder = class _SelfMessageRecorder {
|
|
|
1737
3073
|
normalizeElements(content) {
|
|
1738
3074
|
try {
|
|
1739
3075
|
const normalized = typeof content === "string" ? content : Array.isArray(content) ? content.map((raw) => {
|
|
1740
|
-
const item =
|
|
3076
|
+
const item = getObject3(raw);
|
|
1741
3077
|
if (typeof item.data === "object" && item.data !== null && item.attrs === void 0) {
|
|
1742
|
-
return (0, import_koishi.h)(
|
|
3078
|
+
return (0, import_koishi.h)(getString4(item.type), item.data);
|
|
1743
3079
|
}
|
|
1744
3080
|
return raw;
|
|
1745
3081
|
}) : content;
|
|
@@ -1754,24 +3090,17 @@ __name(_SelfMessageRecorder, "SelfMessageRecorder");
|
|
|
1754
3090
|
var SelfMessageRecorder = _SelfMessageRecorder;
|
|
1755
3091
|
|
|
1756
3092
|
// src/bootstrap.ts
|
|
1757
|
-
function
|
|
1758
|
-
const url = ctx.satori?.server?.url ?? "/satori";
|
|
1759
|
-
const clean = url.startsWith("undefined") ? url.slice(9) : url;
|
|
1760
|
-
if (/^https?:\/\//i.test(clean)) return clean;
|
|
1761
|
-
const base = ctx.server?.selfUrl ?? ctx.server?.config?.selfUrl ?? "";
|
|
1762
|
-
return `${base}${clean.startsWith("/") ? clean : `/${clean}`}`;
|
|
1763
|
-
}
|
|
1764
|
-
__name(resolveEndpoint, "resolveEndpoint");
|
|
1765
|
-
function registerBootstrap(ctx, config, database, logger) {
|
|
3093
|
+
function registerBootstrap(ctx, config, database, logger, getLogins) {
|
|
1766
3094
|
ctx.console.addListener("chat-patch/bootstrap", () => {
|
|
1767
3095
|
logger.logInfo("返回 Satori bootstrap:", {
|
|
1768
|
-
endpoint:
|
|
3096
|
+
endpoint: resolveSatoriEndpoint(ctx),
|
|
1769
3097
|
basePath: config.basePath
|
|
1770
3098
|
});
|
|
1771
3099
|
return {
|
|
1772
|
-
endpoint:
|
|
3100
|
+
endpoint: resolveSatoriEndpoint(ctx),
|
|
1773
3101
|
token: ctx.satori?.server?.config?.token ?? "",
|
|
1774
3102
|
basePath: config.basePath,
|
|
3103
|
+
logins: getLogins(),
|
|
1775
3104
|
blockedPlatforms: config.blockedPlatforms ?? []
|
|
1776
3105
|
};
|
|
1777
3106
|
}, { authority: 4 });
|
|
@@ -2449,7 +3778,7 @@ var name = "chat-patch";
|
|
|
2449
3778
|
var reusable = false;
|
|
2450
3779
|
var filter = false;
|
|
2451
3780
|
var inject = {
|
|
2452
|
-
required: ["console", "server", "satori.server"]
|
|
3781
|
+
required: ["console", "server", "http", "satori.server"]
|
|
2453
3782
|
};
|
|
2454
3783
|
var usage = `
|
|
2455
3784
|
---
|
|
@@ -2466,17 +3795,25 @@ async function apply(ctx, config) {
|
|
|
2466
3795
|
const contactCache = new ContactCacheService(ctx, database, pluginLogger);
|
|
2467
3796
|
const media = new MediaManager(ctx, config, database, pluginLogger);
|
|
2468
3797
|
media.start();
|
|
2469
|
-
const recorder = new Recorder(
|
|
2470
|
-
recorder
|
|
3798
|
+
const recorder = new Recorder(config, database, media, contactCache, pluginLogger);
|
|
3799
|
+
const gateway = new SatoriGateway(ctx, config, database, recorder, pluginLogger, (payload) => {
|
|
3800
|
+
void ctx.console.broadcast("chat-patch/event", payload).catch((error) => {
|
|
3801
|
+
pluginLogger.warn("推送前端事件失败:", error);
|
|
3802
|
+
});
|
|
3803
|
+
});
|
|
2471
3804
|
const selfMessages = new SelfMessageRecorder(ctx, config, database, media, pluginLogger);
|
|
2472
3805
|
selfMessages.start();
|
|
2473
|
-
|
|
3806
|
+
void gateway.start().catch((error) => {
|
|
3807
|
+
pluginLogger.warn("Satori 网关启动失败:", error);
|
|
3808
|
+
});
|
|
3809
|
+
registerBootstrap(ctx, config, database, pluginLogger, () => gateway.getLogins());
|
|
2474
3810
|
registerWeb(ctx, config, database, contactCache, media, pluginLogger);
|
|
2475
3811
|
ctx.console.addEntry({
|
|
2476
3812
|
dev: import_node_path4.default.resolve(__dirname, "../client/index.ts"),
|
|
2477
3813
|
prod: import_node_path4.default.resolve(__dirname, "../dist")
|
|
2478
3814
|
});
|
|
2479
3815
|
ctx.on("dispose", async () => {
|
|
3816
|
+
gateway.dispose();
|
|
2480
3817
|
selfMessages.dispose();
|
|
2481
3818
|
media.dispose();
|
|
2482
3819
|
await database.dispose();
|