koishi-plugin-chatluna-affinity 0.3.0 → 0.3.2
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/AffinityDashboardPage.vue +30 -0
- package/client/components/ui/alert.tsx +50 -0
- package/client/components/ui/avatar.tsx +47 -0
- package/client/components/ui/badge.tsx +35 -0
- package/client/components/ui/button.tsx +53 -0
- package/client/components/ui/card.tsx +57 -0
- package/client/components/ui/chart.tsx +136 -0
- package/client/components/ui/sonner.tsx +23 -0
- package/client/components/ui/table.tsx +77 -0
- package/client/components/ui/tabs.tsx +82 -0
- package/client/dashboard/AffinityDashboard.tsx +1123 -0
- package/client/dashboard/mount.tsx +9 -0
- package/client/dashboard/types.ts +85 -0
- package/client/index.ts +13 -0
- package/client/lib/utils.ts +6 -0
- package/client/style.css +125 -0
- package/dist/index.js +38400 -159
- package/dist/style.css +1 -1
- package/lib/index.d.ts +68 -15
- package/lib/index.js +673 -8
- package/package.json +57 -16
- package/readme.md +4 -2
package/lib/index.js
CHANGED
|
@@ -417,6 +417,7 @@ __export(index_exports, {
|
|
|
417
417
|
COMMON_STYLE: () => COMMON_STYLE,
|
|
418
418
|
Config: () => ConfigSchema,
|
|
419
419
|
ConfigSchema: () => ConfigSchema,
|
|
420
|
+
DASHBOARD_SNAPSHOT_MODEL_NAME: () => DASHBOARD_SNAPSHOT_MODEL_NAME,
|
|
420
421
|
DEFAULT_MEMBER_INFO_ITEMS: () => DEFAULT_MEMBER_INFO_ITEMS,
|
|
421
422
|
FETCH_CONSTANTS: () => FETCH_CONSTANTS,
|
|
422
423
|
MIGRATION_MODEL_NAME: () => MIGRATION_MODEL_NAME,
|
|
@@ -430,6 +431,7 @@ __export(index_exports, {
|
|
|
430
431
|
THRESHOLDS: () => THRESHOLDS,
|
|
431
432
|
TIME_CONSTANTS: () => TIME_CONSTANTS,
|
|
432
433
|
TIMING_CONSTANTS: () => TIMING_CONSTANTS,
|
|
434
|
+
USER_AFFINITY_SNAPSHOT_MODEL_NAME: () => USER_AFFINITY_SNAPSHOT_MODEL_NAME,
|
|
433
435
|
USER_ALIAS_MODEL_NAME: () => USER_ALIAS_MODEL_NAME,
|
|
434
436
|
USER_ALIAS_MODEL_NAME_V2: () => USER_ALIAS_MODEL_NAME_V2,
|
|
435
437
|
appendActionEntry: () => appendActionEntry,
|
|
@@ -474,6 +476,7 @@ __export(index_exports, {
|
|
|
474
476
|
escapeHtmlForRender: () => escapeHtmlForRender,
|
|
475
477
|
extendAffinityModel: () => extendAffinityModel,
|
|
476
478
|
extendBlacklistModel: () => extendBlacklistModel,
|
|
479
|
+
extendDashboardSnapshotModel: () => extendDashboardSnapshotModel,
|
|
477
480
|
extendMigrationModel: () => extendMigrationModel,
|
|
478
481
|
extendUserAliasModel: () => extendUserAliasModel,
|
|
479
482
|
fetchGroupMemberIds: () => fetchGroupMemberIds,
|
|
@@ -844,7 +847,7 @@ var XmlToolSettingsSchema = import_koishi4.Schema.object({
|
|
|
844
847
|
<userAlias scopeId="{scopeId}" userId="123456" name="\u5C0F\u7965"/>
|
|
845
848
|
</actions>
|
|
846
849
|
\`\`\``
|
|
847
|
-
).description("\u6A21\u578B\u56DE\u590D XML \u53C2\u8003\u63D0\u793A\u8BCD\
|
|
850
|
+
).description("\u6A21\u578B\u56DE\u590D XML \u53C2\u8003\u63D0\u793A\u8BCD\u3002\u6B64\u5185\u5BB9\u4E0D\u4F1A\u81EA\u52A8\u6CE8\u5165\u5230\u89D2\u8272\u63D0\u793A\u8BCD\u4E2D\uFF1B\u8BF7\u5148\u5C06 {scopeId} \u66FF\u6362\u4E3A\u5B9E\u9645 scopeId\uFF0C\u518D\u624B\u52A8\u590D\u5236\u5230 ChatLuna Character \u7684\u89D2\u8272\u63D0\u793A\u8BCD\u91CC\u3002\u82E5\u5F00\u542F\u201C\u5C06 XML \u5DE5\u5177\u6539\u4E3A\u6CE8\u5165\u5B9E\u9A8C\u6027\u5DE5\u5177\u8C03\u7528\u56DE\u590D\u201D\uFF0C\u5219\u53EA\u9700\u5728\u63D0\u793A\u8BCD\u4E2D\u544A\u77E5 AI \u4F60\u7684 scopeId").collapse()
|
|
848
851
|
}).description("XML \u5DE5\u5177\u8BBE\u7F6E");
|
|
849
852
|
var VariableSettingsSchema = import_koishi4.Schema.object({
|
|
850
853
|
affinityVariableName: import_koishi4.Schema.string().default("affinity").description(
|
|
@@ -860,6 +863,7 @@ var VariableSettingsSchema = import_koishi4.Schema.object({
|
|
|
860
863
|
)
|
|
861
864
|
}).description("\u53D8\u91CF\u8BBE\u7F6E");
|
|
862
865
|
var OtherSettingsSchema = import_koishi4.Schema.object({
|
|
866
|
+
enableDashboard: import_koishi4.Schema.boolean().default(true).description("\u5728 Koishi \u63A7\u5236\u53F0\u4FA7\u680F\u663E\u793A\u597D\u611F\u5EA6\u4EEA\u8868\u76D8"),
|
|
863
867
|
rankRenderAsImage: import_koishi4.Schema.boolean().default(false).description("\u5C06\u597D\u611F\u5EA6\u6392\u884C\u6E32\u67D3\u4E3A\u56FE\u7247"),
|
|
864
868
|
blacklistRenderAsImage: import_koishi4.Schema.boolean().default(false).description("\u5C06\u9ED1\u540D\u5355\u6E32\u67D3\u4E3A\u56FE\u7247"),
|
|
865
869
|
shortTermBlacklistRenderAsImage: import_koishi4.Schema.boolean().default(false).description("\u5C06\u4E34\u65F6\u9ED1\u540D\u5355\u6E32\u67D3\u4E3A\u56FE\u7247"),
|
|
@@ -1012,12 +1016,57 @@ function extendMigrationModel(ctx) {
|
|
|
1012
1016
|
);
|
|
1013
1017
|
}
|
|
1014
1018
|
|
|
1019
|
+
// src/models/dashboard-snapshot.ts
|
|
1020
|
+
var DASHBOARD_SNAPSHOT_MODEL_NAME = "chatluna_affinity_dashboard_snapshot";
|
|
1021
|
+
var USER_AFFINITY_SNAPSHOT_MODEL_NAME = "chatluna_affinity_user_snapshot";
|
|
1022
|
+
function extendDashboardSnapshotModel(ctx) {
|
|
1023
|
+
ctx.model.extend(
|
|
1024
|
+
DASHBOARD_SNAPSHOT_MODEL_NAME,
|
|
1025
|
+
{
|
|
1026
|
+
scopeId: { type: "string", length: 32 },
|
|
1027
|
+
date: { type: "string", length: 10 },
|
|
1028
|
+
recordedAt: { type: "timestamp" },
|
|
1029
|
+
generatedBy: { type: "string", length: 32, nullable: true },
|
|
1030
|
+
users: { type: "integer", initial: 0 },
|
|
1031
|
+
affinityTotal: { type: "integer", initial: 0 },
|
|
1032
|
+
longTermAffinityTotal: { type: "integer", initial: 0 },
|
|
1033
|
+
shortTermAffinityTotal: { type: "integer", initial: 0 },
|
|
1034
|
+
chatCount: { type: "integer", initial: 0 },
|
|
1035
|
+
blacklisted: { type: "integer", initial: 0 },
|
|
1036
|
+
permanentBlacklisted: { type: "integer", initial: 0 },
|
|
1037
|
+
temporaryBlacklisted: { type: "integer", initial: 0 },
|
|
1038
|
+
aliases: { type: "integer", initial: 0 },
|
|
1039
|
+
latestInteractionAt: { type: "timestamp", nullable: true }
|
|
1040
|
+
},
|
|
1041
|
+
{ primary: ["scopeId", "date"] }
|
|
1042
|
+
);
|
|
1043
|
+
ctx.model.extend(
|
|
1044
|
+
USER_AFFINITY_SNAPSHOT_MODEL_NAME,
|
|
1045
|
+
{
|
|
1046
|
+
scopeId: { type: "string", length: 32 },
|
|
1047
|
+
userId: { type: "string", length: 64 },
|
|
1048
|
+
date: { type: "string", length: 10 },
|
|
1049
|
+
recordedAt: { type: "timestamp" },
|
|
1050
|
+
nickname: { type: "string", length: 255, nullable: true },
|
|
1051
|
+
affinity: { type: "integer", initial: 0 },
|
|
1052
|
+
longTermAffinity: { type: "integer", initial: 0 },
|
|
1053
|
+
shortTermAffinity: { type: "integer", initial: 0 },
|
|
1054
|
+
chatCount: { type: "integer", initial: 0 },
|
|
1055
|
+
relation: { type: "string", length: 64, nullable: true },
|
|
1056
|
+
specialRelation: { type: "string", length: 64, nullable: true },
|
|
1057
|
+
lastInteractionAt: { type: "timestamp", nullable: true }
|
|
1058
|
+
},
|
|
1059
|
+
{ primary: ["scopeId", "userId", "date"] }
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1015
1063
|
// src/models/index.ts
|
|
1016
1064
|
function registerModels(ctx) {
|
|
1017
1065
|
extendAffinityModel(ctx);
|
|
1018
1066
|
extendBlacklistModel(ctx);
|
|
1019
1067
|
extendUserAliasModel(ctx);
|
|
1020
1068
|
extendMigrationModel(ctx);
|
|
1069
|
+
extendDashboardSnapshotModel(ctx);
|
|
1021
1070
|
}
|
|
1022
1071
|
|
|
1023
1072
|
// src/helpers/logger.ts
|
|
@@ -3834,6 +3883,600 @@ function createMigrationService(options) {
|
|
|
3834
3883
|
return { run };
|
|
3835
3884
|
}
|
|
3836
3885
|
|
|
3886
|
+
// src/services/dashboard/snapshot.ts
|
|
3887
|
+
async function readRecordedDashboardSnapshots(ctx, scopeId) {
|
|
3888
|
+
const dashboardSnapshots = await ctx.database.get(
|
|
3889
|
+
DASHBOARD_SNAPSHOT_MODEL_NAME,
|
|
3890
|
+
{ scopeId }
|
|
3891
|
+
);
|
|
3892
|
+
const userAffinitySnapshots = await ctx.database.get(
|
|
3893
|
+
USER_AFFINITY_SNAPSHOT_MODEL_NAME,
|
|
3894
|
+
{ scopeId }
|
|
3895
|
+
);
|
|
3896
|
+
return { dashboardSnapshots, userAffinitySnapshots };
|
|
3897
|
+
}
|
|
3898
|
+
function formatSnapshotDate(value) {
|
|
3899
|
+
const year = value.getFullYear();
|
|
3900
|
+
const month = String(value.getMonth() + 1).padStart(2, "0");
|
|
3901
|
+
const day = String(value.getDate()).padStart(2, "0");
|
|
3902
|
+
return `${year}-${month}-${day}`;
|
|
3903
|
+
}
|
|
3904
|
+
function parseSnapshotDate(value) {
|
|
3905
|
+
const matched = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
3906
|
+
if (!matched) return null;
|
|
3907
|
+
const year = Number(matched[1]);
|
|
3908
|
+
const month = Number(matched[2]);
|
|
3909
|
+
const day = Number(matched[3]);
|
|
3910
|
+
const date = new Date(year, month - 1, day);
|
|
3911
|
+
if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) {
|
|
3912
|
+
return null;
|
|
3913
|
+
}
|
|
3914
|
+
return date;
|
|
3915
|
+
}
|
|
3916
|
+
async function readDashboardSnapshotSource(ctx, scopeId) {
|
|
3917
|
+
const affinityRows = await ctx.database.get(MODEL_NAME_V2, { scopeId });
|
|
3918
|
+
const blacklistRows = await ctx.database.get(BLACKLIST_MODEL_NAME_V2, {
|
|
3919
|
+
scopeId
|
|
3920
|
+
});
|
|
3921
|
+
const aliasRows = await ctx.database.get(USER_ALIAS_MODEL_NAME_V2, {
|
|
3922
|
+
scopeId
|
|
3923
|
+
});
|
|
3924
|
+
return { affinityRows, blacklistRows, aliasRows };
|
|
3925
|
+
}
|
|
3926
|
+
function createDashboardSnapshot(scopeId, now, source, trigger = "backend") {
|
|
3927
|
+
const permanentBlacklisted = source.blacklistRows.filter(
|
|
3928
|
+
(row) => row.mode === "permanent"
|
|
3929
|
+
).length;
|
|
3930
|
+
const temporaryBlacklisted = source.blacklistRows.filter(
|
|
3931
|
+
(row) => row.mode === "temporary"
|
|
3932
|
+
).length;
|
|
3933
|
+
const latestInteractionAt = source.affinityRows.reduce(
|
|
3934
|
+
(latest, row) => {
|
|
3935
|
+
const value = row.lastInteractionAt;
|
|
3936
|
+
if (!value) return latest;
|
|
3937
|
+
if (!latest || value.getTime() > latest.getTime()) return value;
|
|
3938
|
+
return latest;
|
|
3939
|
+
},
|
|
3940
|
+
null
|
|
3941
|
+
);
|
|
3942
|
+
return {
|
|
3943
|
+
scopeId,
|
|
3944
|
+
date: formatSnapshotDate(now),
|
|
3945
|
+
recordedAt: now,
|
|
3946
|
+
generatedBy: trigger,
|
|
3947
|
+
users: source.affinityRows.length,
|
|
3948
|
+
affinityTotal: source.affinityRows.reduce(
|
|
3949
|
+
(total, row) => total + Number(row.affinity || 0),
|
|
3950
|
+
0
|
|
3951
|
+
),
|
|
3952
|
+
longTermAffinityTotal: source.affinityRows.reduce(
|
|
3953
|
+
(total, row) => total + Number(row.longTermAffinity ?? row.affinity ?? 0),
|
|
3954
|
+
0
|
|
3955
|
+
),
|
|
3956
|
+
shortTermAffinityTotal: source.affinityRows.reduce(
|
|
3957
|
+
(total, row) => total + Number(row.shortTermAffinity || 0),
|
|
3958
|
+
0
|
|
3959
|
+
),
|
|
3960
|
+
chatCount: source.affinityRows.reduce(
|
|
3961
|
+
(total, row) => total + Number(row.chatCount || 0),
|
|
3962
|
+
0
|
|
3963
|
+
),
|
|
3964
|
+
blacklisted: source.blacklistRows.length,
|
|
3965
|
+
permanentBlacklisted,
|
|
3966
|
+
temporaryBlacklisted,
|
|
3967
|
+
aliases: source.aliasRows.length,
|
|
3968
|
+
latestInteractionAt
|
|
3969
|
+
};
|
|
3970
|
+
}
|
|
3971
|
+
function createUserAffinitySnapshots(scopeId, now, source, existingSnapshots = []) {
|
|
3972
|
+
const date = formatSnapshotDate(now);
|
|
3973
|
+
const latestSnapshotsByUserId = /* @__PURE__ */ new Map();
|
|
3974
|
+
for (const snapshot of existingSnapshots) {
|
|
3975
|
+
if (snapshot.scopeId !== scopeId || !parseSnapshotDate(snapshot.date)) {
|
|
3976
|
+
continue;
|
|
3977
|
+
}
|
|
3978
|
+
const latest = latestSnapshotsByUserId.get(snapshot.userId);
|
|
3979
|
+
if (!latest || snapshot.date >= latest.date) {
|
|
3980
|
+
latestSnapshotsByUserId.set(snapshot.userId, snapshot);
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
return source.affinityRows.filter((row) => {
|
|
3984
|
+
const latest = latestSnapshotsByUserId.get(row.userId);
|
|
3985
|
+
return !latest || Number(latest.affinity || 0) !== Number(row.affinity || 0) || Number(latest.longTermAffinity || 0) !== Number(row.longTermAffinity ?? row.affinity ?? 0) || Number(latest.chatCount || 0) !== Number(row.chatCount || 0);
|
|
3986
|
+
}).map((row) => ({
|
|
3987
|
+
scopeId,
|
|
3988
|
+
userId: row.userId,
|
|
3989
|
+
date,
|
|
3990
|
+
recordedAt: now,
|
|
3991
|
+
nickname: row.nickname || null,
|
|
3992
|
+
affinity: Number(row.affinity || 0),
|
|
3993
|
+
longTermAffinity: Number(row.longTermAffinity ?? row.affinity ?? 0),
|
|
3994
|
+
shortTermAffinity: Number(row.shortTermAffinity || 0),
|
|
3995
|
+
chatCount: Number(row.chatCount || 0),
|
|
3996
|
+
relation: row.relation || null,
|
|
3997
|
+
specialRelation: row.specialRelation || null,
|
|
3998
|
+
lastInteractionAt: row.lastInteractionAt || null
|
|
3999
|
+
}));
|
|
4000
|
+
}
|
|
4001
|
+
function hasSnapshotSourceData(source) {
|
|
4002
|
+
return source.affinityRows.length > 0 || source.blacklistRows.length > 0 || source.aliasRows.length > 0;
|
|
4003
|
+
}
|
|
4004
|
+
function mergeDashboardSnapshot(rows, snapshot) {
|
|
4005
|
+
return [
|
|
4006
|
+
...rows.filter(
|
|
4007
|
+
(row) => row.scopeId !== snapshot.scopeId || row.date !== snapshot.date
|
|
4008
|
+
),
|
|
4009
|
+
snapshot
|
|
4010
|
+
];
|
|
4011
|
+
}
|
|
4012
|
+
function mergeUserAffinitySnapshots(rows, snapshots) {
|
|
4013
|
+
const snapshotKeys = new Set(
|
|
4014
|
+
snapshots.map(
|
|
4015
|
+
(snapshot) => `${snapshot.scopeId}:${snapshot.userId}:${snapshot.date}`
|
|
4016
|
+
)
|
|
4017
|
+
);
|
|
4018
|
+
return [
|
|
4019
|
+
...rows.filter(
|
|
4020
|
+
(row) => !snapshotKeys.has(`${row.scopeId}:${row.userId}:${row.date}`)
|
|
4021
|
+
),
|
|
4022
|
+
...snapshots
|
|
4023
|
+
];
|
|
4024
|
+
}
|
|
4025
|
+
async function recordDashboardSnapshot(ctx, options) {
|
|
4026
|
+
const scopeId = options.scopeId.trim();
|
|
4027
|
+
if (!scopeId) {
|
|
4028
|
+
return { dashboardSnapshots: [], userAffinitySnapshots: [] };
|
|
4029
|
+
}
|
|
4030
|
+
const now = options.now || /* @__PURE__ */ new Date();
|
|
4031
|
+
const source = options.source || await readDashboardSnapshotSource(ctx, scopeId);
|
|
4032
|
+
const existingSnapshots = options.existingSnapshots || await ctx.database.get(DASHBOARD_SNAPSHOT_MODEL_NAME, { scopeId });
|
|
4033
|
+
const existingUserAffinitySnapshots = options.existingUserAffinitySnapshots || await ctx.database.get(USER_AFFINITY_SNAPSHOT_MODEL_NAME, { scopeId });
|
|
4034
|
+
if (!hasSnapshotSourceData(source) && existingSnapshots.length === 0) {
|
|
4035
|
+
return {
|
|
4036
|
+
dashboardSnapshots: existingSnapshots,
|
|
4037
|
+
userAffinitySnapshots: existingUserAffinitySnapshots
|
|
4038
|
+
};
|
|
4039
|
+
}
|
|
4040
|
+
const snapshot = createDashboardSnapshot(
|
|
4041
|
+
scopeId,
|
|
4042
|
+
now,
|
|
4043
|
+
source,
|
|
4044
|
+
options.trigger
|
|
4045
|
+
);
|
|
4046
|
+
const userSnapshots = createUserAffinitySnapshots(
|
|
4047
|
+
scopeId,
|
|
4048
|
+
now,
|
|
4049
|
+
source,
|
|
4050
|
+
existingUserAffinitySnapshots
|
|
4051
|
+
);
|
|
4052
|
+
await ctx.database.upsert(DASHBOARD_SNAPSHOT_MODEL_NAME, [snapshot]);
|
|
4053
|
+
if (userSnapshots.length > 0) {
|
|
4054
|
+
await ctx.database.upsert(USER_AFFINITY_SNAPSHOT_MODEL_NAME, userSnapshots);
|
|
4055
|
+
}
|
|
4056
|
+
return {
|
|
4057
|
+
dashboardSnapshots: mergeDashboardSnapshot(existingSnapshots, snapshot),
|
|
4058
|
+
userAffinitySnapshots: mergeUserAffinitySnapshots(
|
|
4059
|
+
existingUserAffinitySnapshots,
|
|
4060
|
+
userSnapshots
|
|
4061
|
+
)
|
|
4062
|
+
};
|
|
4063
|
+
}
|
|
4064
|
+
|
|
4065
|
+
// src/services/dashboard/backend.ts
|
|
4066
|
+
var DEFAULT_SNAPSHOT_INTERVAL_MS = 60 * 60 * 1e3;
|
|
4067
|
+
function registerDashboardBackend(options) {
|
|
4068
|
+
const { config, ctx, log } = options;
|
|
4069
|
+
if (config.enableDashboard === false) return;
|
|
4070
|
+
const getNow = options.now || (() => /* @__PURE__ */ new Date());
|
|
4071
|
+
const intervalMs = options.sampleIntervalMs || DEFAULT_SNAPSHOT_INTERVAL_MS;
|
|
4072
|
+
const schedule = options.setInterval || setInterval;
|
|
4073
|
+
const clear = options.clearInterval || clearInterval;
|
|
4074
|
+
let timer = null;
|
|
4075
|
+
let running = false;
|
|
4076
|
+
const record = async () => {
|
|
4077
|
+
if (running) return;
|
|
4078
|
+
running = true;
|
|
4079
|
+
try {
|
|
4080
|
+
await recordDashboardSnapshot(ctx, {
|
|
4081
|
+
scopeId: config.scopeId,
|
|
4082
|
+
now: getNow()
|
|
4083
|
+
});
|
|
4084
|
+
} catch (error) {
|
|
4085
|
+
log("warn", "\u8BB0\u5F55\u4EEA\u8868\u76D8\u540E\u53F0\u5FEB\u7167\u5931\u8D25", error);
|
|
4086
|
+
} finally {
|
|
4087
|
+
running = false;
|
|
4088
|
+
}
|
|
4089
|
+
};
|
|
4090
|
+
ctx.on("ready", () => {
|
|
4091
|
+
if (timer !== null) return;
|
|
4092
|
+
void record();
|
|
4093
|
+
timer = schedule(() => {
|
|
4094
|
+
void record();
|
|
4095
|
+
}, intervalMs);
|
|
4096
|
+
});
|
|
4097
|
+
ctx.on("dispose", () => {
|
|
4098
|
+
if (timer === null) return;
|
|
4099
|
+
clear(timer);
|
|
4100
|
+
timer = null;
|
|
4101
|
+
});
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
// src/services/dashboard/index.ts
|
|
4105
|
+
var DASHBOARD_EVENT = "chatluna-affinity/dashboard";
|
|
4106
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
4107
|
+
var WEEK_DAYS = 7;
|
|
4108
|
+
var MONTH_DAYS = 30;
|
|
4109
|
+
var HISTORY_POINT_LIMIT = 12;
|
|
4110
|
+
function toIsoString(value) {
|
|
4111
|
+
if (!value) return null;
|
|
4112
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
4113
|
+
if (Number.isNaN(date.getTime())) return null;
|
|
4114
|
+
return date.toISOString();
|
|
4115
|
+
}
|
|
4116
|
+
function toCount(value) {
|
|
4117
|
+
return Number.isFinite(value) ? Number(value) : 0;
|
|
4118
|
+
}
|
|
4119
|
+
function roundAverage(total, count) {
|
|
4120
|
+
if (!count) return 0;
|
|
4121
|
+
return Math.round(total / count * 100) / 100;
|
|
4122
|
+
}
|
|
4123
|
+
function roundPercent(value) {
|
|
4124
|
+
return Math.round(value * 100) / 100;
|
|
4125
|
+
}
|
|
4126
|
+
function snapshotAffinityTotal(snapshot) {
|
|
4127
|
+
return toCount(snapshot.affinityTotal);
|
|
4128
|
+
}
|
|
4129
|
+
function snapshotUsers(snapshot) {
|
|
4130
|
+
return toCount(snapshot.users);
|
|
4131
|
+
}
|
|
4132
|
+
function snapshotChatCount(snapshot) {
|
|
4133
|
+
return toCount(snapshot.chatCount);
|
|
4134
|
+
}
|
|
4135
|
+
function snapshotBlacklisted(snapshot) {
|
|
4136
|
+
return toCount(snapshot.blacklisted);
|
|
4137
|
+
}
|
|
4138
|
+
function snapshotAliases(snapshot) {
|
|
4139
|
+
return toCount(snapshot.aliases);
|
|
4140
|
+
}
|
|
4141
|
+
function createMetricChange(current, previous) {
|
|
4142
|
+
return {
|
|
4143
|
+
current,
|
|
4144
|
+
previous,
|
|
4145
|
+
percent: previous === 0 ? current === 0 ? 0 : null : roundPercent((current - previous) / previous * 100)
|
|
4146
|
+
};
|
|
4147
|
+
}
|
|
4148
|
+
function getDisplayRelation(record) {
|
|
4149
|
+
return record.specialRelation || record.relation || "\u672A\u5206\u7EC4";
|
|
4150
|
+
}
|
|
4151
|
+
function getRelationKind(record) {
|
|
4152
|
+
return record.specialRelation ? "custom" : "preset";
|
|
4153
|
+
}
|
|
4154
|
+
function getRelationTone(record, levels) {
|
|
4155
|
+
if (record.specialRelation) return "custom";
|
|
4156
|
+
const relation = record.relation || "";
|
|
4157
|
+
const orderedLevels = [...levels || []].filter((level) => level.relation).sort((left, right) => left.min - right.min);
|
|
4158
|
+
const index = orderedLevels.findIndex((level) => level.relation === relation);
|
|
4159
|
+
if (index < 0) return "unknown";
|
|
4160
|
+
const ratio = orderedLevels.length > 1 ? index / (orderedLevels.length - 1) : 1;
|
|
4161
|
+
if (ratio <= 0.25) return "low";
|
|
4162
|
+
if (ratio < 0.75) return "medium";
|
|
4163
|
+
return "high";
|
|
4164
|
+
}
|
|
4165
|
+
function getDisplayName(record) {
|
|
4166
|
+
return record.nickname || record.userId;
|
|
4167
|
+
}
|
|
4168
|
+
function getOneBotAvatarUrl(userId) {
|
|
4169
|
+
const numericId = userId.match(/^\d+$/)?.[0];
|
|
4170
|
+
return numericId ? `https://q1.qlogo.cn/g?b=qq&nk=${numericId}&s=640` : null;
|
|
4171
|
+
}
|
|
4172
|
+
function getBlacklistDisplayName(record) {
|
|
4173
|
+
return record.nickname || record.userId;
|
|
4174
|
+
}
|
|
4175
|
+
function formatTrendLabel(date) {
|
|
4176
|
+
return `${date.getMonth() + 1}/${date.getDate()}`;
|
|
4177
|
+
}
|
|
4178
|
+
function startOfLocalDay(value) {
|
|
4179
|
+
return new Date(value.getFullYear(), value.getMonth(), value.getDate());
|
|
4180
|
+
}
|
|
4181
|
+
function createEmptyTrendPoint(date) {
|
|
4182
|
+
return {
|
|
4183
|
+
label: formatTrendLabel(date),
|
|
4184
|
+
users: 0,
|
|
4185
|
+
averageAffinity: 0,
|
|
4186
|
+
chatCount: 0,
|
|
4187
|
+
blacklisted: 0
|
|
4188
|
+
};
|
|
4189
|
+
}
|
|
4190
|
+
function createSnapshotTrendPoint(snapshot) {
|
|
4191
|
+
const date = parseSnapshotDate(snapshot.date);
|
|
4192
|
+
if (!date) return null;
|
|
4193
|
+
return {
|
|
4194
|
+
label: formatTrendLabel(date),
|
|
4195
|
+
users: snapshotUsers(snapshot),
|
|
4196
|
+
averageAffinity: roundAverage(
|
|
4197
|
+
snapshotAffinityTotal(snapshot),
|
|
4198
|
+
snapshotUsers(snapshot)
|
|
4199
|
+
),
|
|
4200
|
+
chatCount: snapshotChatCount(snapshot),
|
|
4201
|
+
blacklisted: snapshotBlacklisted(snapshot)
|
|
4202
|
+
};
|
|
4203
|
+
}
|
|
4204
|
+
function createDailyTrend(snapshots, anchor, days) {
|
|
4205
|
+
const snapshotsByDate = new Map(
|
|
4206
|
+
snapshots.map((snapshot) => [snapshot.date, snapshot])
|
|
4207
|
+
);
|
|
4208
|
+
const end = startOfLocalDay(anchor).getTime() + DAY_MS;
|
|
4209
|
+
const start = new Date(end - days * DAY_MS);
|
|
4210
|
+
return Array.from({ length: days }, (_, index) => {
|
|
4211
|
+
const date = new Date(start.getTime() + index * DAY_MS);
|
|
4212
|
+
const snapshot = snapshotsByDate.get(formatSnapshotDate(date));
|
|
4213
|
+
const point = snapshot ? createSnapshotTrendPoint(snapshot) : null;
|
|
4214
|
+
return point || createEmptyTrendPoint(date);
|
|
4215
|
+
});
|
|
4216
|
+
}
|
|
4217
|
+
function createAllTrend(snapshots) {
|
|
4218
|
+
const latestByMonth = /* @__PURE__ */ new Map();
|
|
4219
|
+
for (const snapshot of snapshots) {
|
|
4220
|
+
const date = parseSnapshotDate(snapshot.date);
|
|
4221
|
+
if (!date) continue;
|
|
4222
|
+
const key = `${date.getFullYear()}-${date.getMonth()}`;
|
|
4223
|
+
const current = latestByMonth.get(key);
|
|
4224
|
+
if (!current || snapshot.date > current.date) {
|
|
4225
|
+
latestByMonth.set(key, snapshot);
|
|
4226
|
+
}
|
|
4227
|
+
}
|
|
4228
|
+
return [...latestByMonth.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([, snapshot]) => {
|
|
4229
|
+
const point = createSnapshotTrendPoint(snapshot);
|
|
4230
|
+
const date = parseSnapshotDate(snapshot.date);
|
|
4231
|
+
return {
|
|
4232
|
+
...point || createEmptyTrendPoint(date || /* @__PURE__ */ new Date()),
|
|
4233
|
+
label: date ? `${date.getFullYear()}/${date.getMonth() + 1}` : snapshot.date
|
|
4234
|
+
};
|
|
4235
|
+
});
|
|
4236
|
+
}
|
|
4237
|
+
function getSnapshotTime(snapshot) {
|
|
4238
|
+
return parseSnapshotDate(snapshot.date)?.getTime() ?? null;
|
|
4239
|
+
}
|
|
4240
|
+
function getLatestSnapshotDate(snapshots) {
|
|
4241
|
+
const times = snapshots.map(getSnapshotTime).filter((value) => value !== null);
|
|
4242
|
+
if (!times.length) return null;
|
|
4243
|
+
return new Date(Math.max(...times));
|
|
4244
|
+
}
|
|
4245
|
+
function findLatestSnapshotInWindow(snapshots, start, end) {
|
|
4246
|
+
let latest = null;
|
|
4247
|
+
let latestTime = -Infinity;
|
|
4248
|
+
for (const snapshot of snapshots) {
|
|
4249
|
+
const time = getSnapshotTime(snapshot);
|
|
4250
|
+
if (time === null || time < start || time >= end || time < latestTime) {
|
|
4251
|
+
continue;
|
|
4252
|
+
}
|
|
4253
|
+
latest = snapshot;
|
|
4254
|
+
latestTime = time;
|
|
4255
|
+
}
|
|
4256
|
+
return latest;
|
|
4257
|
+
}
|
|
4258
|
+
function snapshotAverage(snapshot) {
|
|
4259
|
+
if (!snapshot) return 0;
|
|
4260
|
+
return roundAverage(snapshotAffinityTotal(snapshot), snapshotUsers(snapshot));
|
|
4261
|
+
}
|
|
4262
|
+
function createUserHistoryPoints(row, snapshots, trendAnchor) {
|
|
4263
|
+
const points = snapshots.map((snapshot) => {
|
|
4264
|
+
const date = parseSnapshotDate(snapshot.date);
|
|
4265
|
+
if (!date) return null;
|
|
4266
|
+
return {
|
|
4267
|
+
date,
|
|
4268
|
+
point: {
|
|
4269
|
+
label: formatTrendLabel(date),
|
|
4270
|
+
timestamp: toIsoString(snapshot.recordedAt) || toIsoString(date),
|
|
4271
|
+
affinity: toCount(snapshot.affinity),
|
|
4272
|
+
longTermAffinity: toCount(snapshot.longTermAffinity),
|
|
4273
|
+
chatCount: toCount(snapshot.chatCount)
|
|
4274
|
+
}
|
|
4275
|
+
};
|
|
4276
|
+
}).filter(
|
|
4277
|
+
(point) => point !== null
|
|
4278
|
+
).sort((left, right) => left.date.getTime() - right.date.getTime());
|
|
4279
|
+
if (points.length) {
|
|
4280
|
+
const anchorDate = startOfLocalDay(trendAnchor);
|
|
4281
|
+
const latest = points.at(-1);
|
|
4282
|
+
if (latest && latest.date.getTime() < anchorDate.getTime()) {
|
|
4283
|
+
points.push({
|
|
4284
|
+
date: anchorDate,
|
|
4285
|
+
point: {
|
|
4286
|
+
label: formatTrendLabel(anchorDate),
|
|
4287
|
+
timestamp: toIsoString(anchorDate),
|
|
4288
|
+
affinity: latest.point.affinity,
|
|
4289
|
+
longTermAffinity: toCount(row.longTermAffinity ?? row.affinity),
|
|
4290
|
+
chatCount: toCount(row.chatCount)
|
|
4291
|
+
}
|
|
4292
|
+
});
|
|
4293
|
+
}
|
|
4294
|
+
return points.slice(-HISTORY_POINT_LIMIT).map(({ point }) => point);
|
|
4295
|
+
}
|
|
4296
|
+
return [
|
|
4297
|
+
{
|
|
4298
|
+
label: "\u5F53\u524D",
|
|
4299
|
+
timestamp: toIsoString(row.lastInteractionAt),
|
|
4300
|
+
affinity: toCount(row.affinity),
|
|
4301
|
+
longTermAffinity: toCount(row.longTermAffinity ?? row.affinity),
|
|
4302
|
+
chatCount: toCount(row.chatCount)
|
|
4303
|
+
}
|
|
4304
|
+
];
|
|
4305
|
+
}
|
|
4306
|
+
function groupUserSnapshots(snapshots) {
|
|
4307
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
4308
|
+
for (const snapshot of snapshots) {
|
|
4309
|
+
const rows = grouped.get(snapshot.userId) || [];
|
|
4310
|
+
rows.push(snapshot);
|
|
4311
|
+
grouped.set(snapshot.userId, rows);
|
|
4312
|
+
}
|
|
4313
|
+
return grouped;
|
|
4314
|
+
}
|
|
4315
|
+
async function getDashboardData(ctx, options) {
|
|
4316
|
+
const scopeId = options.scopeId;
|
|
4317
|
+
const now = options.now || /* @__PURE__ */ new Date();
|
|
4318
|
+
const relationshipAffinityLevels = options.relationshipAffinityLevels || [];
|
|
4319
|
+
const affinityRows = await ctx.database.get(MODEL_NAME_V2, {
|
|
4320
|
+
scopeId
|
|
4321
|
+
});
|
|
4322
|
+
const blacklistRows = await ctx.database.get(BLACKLIST_MODEL_NAME_V2, {
|
|
4323
|
+
scopeId
|
|
4324
|
+
});
|
|
4325
|
+
const aliasRows = await ctx.database.get(USER_ALIAS_MODEL_NAME_V2, {
|
|
4326
|
+
scopeId
|
|
4327
|
+
});
|
|
4328
|
+
const recordedSnapshots = await readRecordedDashboardSnapshots(ctx, scopeId);
|
|
4329
|
+
const snapshotRows = recordedSnapshots.dashboardSnapshots;
|
|
4330
|
+
const userSnapshotRows = recordedSnapshots.userAffinitySnapshots;
|
|
4331
|
+
const trendAnchor = getLatestSnapshotDate(snapshotRows) || now;
|
|
4332
|
+
let chatCount = 0;
|
|
4333
|
+
let affinityTotal = 0;
|
|
4334
|
+
let longTermTotal = 0;
|
|
4335
|
+
let shortTermTotal = 0;
|
|
4336
|
+
let latestInteractionAt = null;
|
|
4337
|
+
const relationCounts = /* @__PURE__ */ new Map();
|
|
4338
|
+
const affinityByUserId = /* @__PURE__ */ new Map();
|
|
4339
|
+
const userSnapshotsByUserId = groupUserSnapshots(userSnapshotRows);
|
|
4340
|
+
for (const row of affinityRows) {
|
|
4341
|
+
chatCount += toCount(row.chatCount);
|
|
4342
|
+
affinityTotal += toCount(row.affinity);
|
|
4343
|
+
longTermTotal += toCount(row.longTermAffinity ?? row.affinity);
|
|
4344
|
+
shortTermTotal += toCount(row.shortTermAffinity);
|
|
4345
|
+
const relation = getDisplayRelation(row);
|
|
4346
|
+
const kind = getRelationKind(row);
|
|
4347
|
+
const relationKey = `${kind}:${relation}`;
|
|
4348
|
+
const currentRelation = relationCounts.get(relationKey) || {
|
|
4349
|
+
relation,
|
|
4350
|
+
kind,
|
|
4351
|
+
count: 0
|
|
4352
|
+
};
|
|
4353
|
+
currentRelation.count += 1;
|
|
4354
|
+
relationCounts.set(relationKey, currentRelation);
|
|
4355
|
+
affinityByUserId.set(row.userId, toCount(row.affinity));
|
|
4356
|
+
const currentInteractionAt = toIsoString(row.lastInteractionAt);
|
|
4357
|
+
if (currentInteractionAt && (!latestInteractionAt || currentInteractionAt > latestInteractionAt)) {
|
|
4358
|
+
latestInteractionAt = currentInteractionAt;
|
|
4359
|
+
}
|
|
4360
|
+
}
|
|
4361
|
+
const topUsers = [...affinityRows].sort((left, right) => right.affinity - left.affinity).map((row) => ({
|
|
4362
|
+
userId: row.userId,
|
|
4363
|
+
name: getDisplayName(row),
|
|
4364
|
+
avatarUrl: getOneBotAvatarUrl(row.userId),
|
|
4365
|
+
affinity: toCount(row.affinity),
|
|
4366
|
+
longTermAffinity: toCount(row.longTermAffinity ?? row.affinity),
|
|
4367
|
+
relation: getDisplayRelation(row),
|
|
4368
|
+
relationTone: getRelationTone(row, relationshipAffinityLevels),
|
|
4369
|
+
chatCount: toCount(row.chatCount),
|
|
4370
|
+
lastInteractionAt: toIsoString(row.lastInteractionAt),
|
|
4371
|
+
historyPoints: createUserHistoryPoints(
|
|
4372
|
+
row,
|
|
4373
|
+
userSnapshotsByUserId.get(row.userId) || [],
|
|
4374
|
+
trendAnchor
|
|
4375
|
+
)
|
|
4376
|
+
}));
|
|
4377
|
+
const relationStats = [...relationCounts.values()].sort((left, right) => right.count - left.count);
|
|
4378
|
+
const currentWeekEnd = startOfLocalDay(trendAnchor).getTime() + DAY_MS;
|
|
4379
|
+
const currentWeekStart = currentWeekEnd - WEEK_DAYS * DAY_MS;
|
|
4380
|
+
const previousWeekStart = currentWeekStart - WEEK_DAYS * DAY_MS;
|
|
4381
|
+
const currentWeekSnapshot = findLatestSnapshotInWindow(
|
|
4382
|
+
snapshotRows,
|
|
4383
|
+
currentWeekStart,
|
|
4384
|
+
currentWeekEnd
|
|
4385
|
+
);
|
|
4386
|
+
const previousWeekSnapshot = findLatestSnapshotInWindow(
|
|
4387
|
+
snapshotRows,
|
|
4388
|
+
previousWeekStart,
|
|
4389
|
+
currentWeekStart
|
|
4390
|
+
);
|
|
4391
|
+
const blacklistItems = [...blacklistRows].sort((left, right) => {
|
|
4392
|
+
const leftTime = toIsoString(left.blockedAt) || "";
|
|
4393
|
+
const rightTime = toIsoString(right.blockedAt) || "";
|
|
4394
|
+
return rightTime.localeCompare(leftTime);
|
|
4395
|
+
}).map((row) => ({
|
|
4396
|
+
platform: row.platform,
|
|
4397
|
+
userId: row.userId,
|
|
4398
|
+
name: getBlacklistDisplayName(row),
|
|
4399
|
+
avatarUrl: getOneBotAvatarUrl(row.userId),
|
|
4400
|
+
affinity: affinityByUserId.get(row.userId) ?? null,
|
|
4401
|
+
mode: row.mode,
|
|
4402
|
+
blockedAt: toIsoString(row.blockedAt),
|
|
4403
|
+
expiresAt: toIsoString(row.expiresAt),
|
|
4404
|
+
note: row.note || ""
|
|
4405
|
+
}));
|
|
4406
|
+
const permanentBlacklisted = blacklistRows.filter(
|
|
4407
|
+
(row) => row.mode === "permanent"
|
|
4408
|
+
).length;
|
|
4409
|
+
const temporaryBlacklisted = blacklistRows.filter(
|
|
4410
|
+
(row) => row.mode === "temporary"
|
|
4411
|
+
).length;
|
|
4412
|
+
return {
|
|
4413
|
+
scopeId,
|
|
4414
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4415
|
+
totals: {
|
|
4416
|
+
users: affinityRows.length,
|
|
4417
|
+
blacklisted: blacklistRows.length,
|
|
4418
|
+
permanentBlacklisted,
|
|
4419
|
+
temporaryBlacklisted,
|
|
4420
|
+
aliases: aliasRows.length,
|
|
4421
|
+
chatCount
|
|
4422
|
+
},
|
|
4423
|
+
averages: {
|
|
4424
|
+
affinity: roundAverage(affinityTotal, affinityRows.length),
|
|
4425
|
+
longTermAffinity: roundAverage(longTermTotal, affinityRows.length),
|
|
4426
|
+
shortTermAffinity: roundAverage(shortTermTotal, affinityRows.length)
|
|
4427
|
+
},
|
|
4428
|
+
latestInteractionAt,
|
|
4429
|
+
weeklyChanges: {
|
|
4430
|
+
users: createMetricChange(
|
|
4431
|
+
currentWeekSnapshot ? snapshotUsers(currentWeekSnapshot) : 0,
|
|
4432
|
+
previousWeekSnapshot ? snapshotUsers(previousWeekSnapshot) : 0
|
|
4433
|
+
),
|
|
4434
|
+
averageAffinity: createMetricChange(
|
|
4435
|
+
snapshotAverage(currentWeekSnapshot),
|
|
4436
|
+
snapshotAverage(previousWeekSnapshot)
|
|
4437
|
+
),
|
|
4438
|
+
chatCount: createMetricChange(
|
|
4439
|
+
currentWeekSnapshot ? snapshotChatCount(currentWeekSnapshot) : 0,
|
|
4440
|
+
previousWeekSnapshot ? snapshotChatCount(previousWeekSnapshot) : 0
|
|
4441
|
+
),
|
|
4442
|
+
aliases: createMetricChange(
|
|
4443
|
+
currentWeekSnapshot ? snapshotAliases(currentWeekSnapshot) : 0,
|
|
4444
|
+
previousWeekSnapshot ? snapshotAliases(previousWeekSnapshot) : 0
|
|
4445
|
+
)
|
|
4446
|
+
},
|
|
4447
|
+
trends: {
|
|
4448
|
+
week: createDailyTrend(snapshotRows, trendAnchor, WEEK_DAYS),
|
|
4449
|
+
month: createDailyTrend(snapshotRows, trendAnchor, MONTH_DAYS),
|
|
4450
|
+
all: createAllTrend(snapshotRows)
|
|
4451
|
+
},
|
|
4452
|
+
relationStats,
|
|
4453
|
+
blacklistItems,
|
|
4454
|
+
topUsers
|
|
4455
|
+
};
|
|
4456
|
+
}
|
|
4457
|
+
function registerDashboardWebui(options) {
|
|
4458
|
+
const { config, ctx, entry, log } = options;
|
|
4459
|
+
if (config.enableDashboard === false) return;
|
|
4460
|
+
ctx.inject(["console"], (innerCtx) => {
|
|
4461
|
+
const consoleService = innerCtx.console;
|
|
4462
|
+
consoleService.addEntry(entry);
|
|
4463
|
+
consoleService.addListener(
|
|
4464
|
+
DASHBOARD_EVENT,
|
|
4465
|
+
async () => getDashboardData(ctx, {
|
|
4466
|
+
scopeId: config.scopeId,
|
|
4467
|
+
relationshipAffinityLevels: config.relationshipAffinityLevels
|
|
4468
|
+
}),
|
|
4469
|
+
{ authority: 1 }
|
|
4470
|
+
);
|
|
4471
|
+
if (config.debugLogging) {
|
|
4472
|
+
log("debug", "\u5DF2\u6CE8\u518C\u63A7\u5236\u53F0\u4EEA\u8868\u76D8\u9875\u9762\u4E0E\u6570\u636E\u63A5\u53E3", {
|
|
4473
|
+
event: DASHBOARD_EVENT,
|
|
4474
|
+
scopeId: config.scopeId
|
|
4475
|
+
});
|
|
4476
|
+
}
|
|
4477
|
+
});
|
|
4478
|
+
}
|
|
4479
|
+
|
|
3837
4480
|
// src/renders/base.ts
|
|
3838
4481
|
function getPuppeteer(ctx) {
|
|
3839
4482
|
return ctx.puppeteer || null;
|
|
@@ -5211,20 +5854,26 @@ function registerClearAllCommand(deps) {
|
|
|
5211
5854
|
await ctx.database.remove(USER_ALIAS_MODEL_NAME_V2, {
|
|
5212
5855
|
scopeId: config.scopeId
|
|
5213
5856
|
});
|
|
5857
|
+
await ctx.database.remove(DASHBOARD_SNAPSHOT_MODEL_NAME, {
|
|
5858
|
+
scopeId: config.scopeId
|
|
5859
|
+
});
|
|
5860
|
+
await ctx.database.remove(USER_AFFINITY_SNAPSHOT_MODEL_NAME, {
|
|
5861
|
+
scopeId: config.scopeId
|
|
5862
|
+
});
|
|
5214
5863
|
cache.clearAll?.();
|
|
5215
5864
|
log("info", "\u5F53\u524D\u4F5C\u7528\u57DF\u6570\u636E\u5E93\u5DF2\u6E05\u7A7A", {
|
|
5216
5865
|
scopeId: config.scopeId,
|
|
5217
5866
|
operator: session.userId,
|
|
5218
5867
|
platform: session.platform
|
|
5219
5868
|
});
|
|
5220
|
-
return `\u2705 \u5DF2\u6210\u529F\u6E05\u7A7A\u4F5C\u7528\u57DF ${config.scopeId} \u4E0B\u7684\u597D\u611F\u5EA6\u3001\u9ED1\u540D\u5355\
|
|
5869
|
+
return `\u2705 \u5DF2\u6210\u529F\u6E05\u7A7A\u4F5C\u7528\u57DF ${config.scopeId} \u4E0B\u7684\u597D\u611F\u5EA6\u3001\u9ED1\u540D\u5355\u3001\u6635\u79F0\u4E0E\u8D8B\u52BF\u5FEB\u7167\u6570\u636E\u3002`;
|
|
5221
5870
|
} catch (error) {
|
|
5222
5871
|
log("warn", "\u6E05\u7A7A\u6570\u636E\u5E93\u5931\u8D25", error);
|
|
5223
5872
|
return "\u274C \u6E05\u7A7A\u6570\u636E\u5E93\u65F6\u53D1\u751F\u9519\u8BEF\uFF0C\u8BF7\u67E5\u770B\u65E5\u5FD7\u3002";
|
|
5224
5873
|
}
|
|
5225
5874
|
}
|
|
5226
5875
|
pendingClearConfirmations.set(sessionKey, { expiresAt: now + 60 * 1e3 });
|
|
5227
|
-
return `\u26A0\uFE0F \u8B66\u544A\uFF1A\u6B64\u64CD\u4F5C\u5C06\u6C38\u4E45\u5220\u9664\u4F5C\u7528\u57DF ${config.scopeId} \u4E0B\u7684\u597D\u611F\u5EA6\u3001\u9ED1\u540D\u5355\
|
|
5876
|
+
return `\u26A0\uFE0F \u8B66\u544A\uFF1A\u6B64\u64CD\u4F5C\u5C06\u6C38\u4E45\u5220\u9664\u4F5C\u7528\u57DF ${config.scopeId} \u4E0B\u7684\u597D\u611F\u5EA6\u3001\u9ED1\u540D\u5355\u3001\u6635\u79F0\u4E0E\u8D8B\u52BF\u5FEB\u7167\u6570\u636E\uFF0C\u4E14\u65E0\u6CD5\u6062\u590D\uFF01
|
|
5228
5877
|
\u8BF7\u5728 60 \u79D2\u5185\u4F7F\u7528 \`${buildScopedCommandName(config.scopeId, "clearAll")} -y\` \u6216 \`\u6E05\u7A7A\u597D\u611F\u5EA6 -y\` \u786E\u8BA4\u6267\u884C\u3002`;
|
|
5229
5878
|
});
|
|
5230
5879
|
}
|
|
@@ -5302,14 +5951,21 @@ function apply(ctx, config) {
|
|
|
5302
5951
|
config.initialAffinity = Number.isFinite(config.initialAffinity) ? Number(config.initialAffinity) : BASE_AFFINITY_DEFAULTS.initialAffinity;
|
|
5303
5952
|
normalizeToolSettings(config);
|
|
5304
5953
|
registerModels(ctx);
|
|
5305
|
-
ctx
|
|
5306
|
-
|
|
5307
|
-
|
|
5954
|
+
const log = createLogger(ctx, config);
|
|
5955
|
+
registerDashboardBackend({
|
|
5956
|
+
ctx,
|
|
5957
|
+
config,
|
|
5958
|
+
log
|
|
5959
|
+
});
|
|
5960
|
+
registerDashboardWebui({
|
|
5961
|
+
ctx,
|
|
5962
|
+
config,
|
|
5963
|
+
log,
|
|
5964
|
+
entry: {
|
|
5308
5965
|
dev: path.resolve(__dirname, "../client/index.ts"),
|
|
5309
5966
|
prod: path.resolve(__dirname, "../dist")
|
|
5310
|
-
}
|
|
5967
|
+
}
|
|
5311
5968
|
});
|
|
5312
|
-
const log = createLogger(ctx, config);
|
|
5313
5969
|
log("info", runtimeFingerprint);
|
|
5314
5970
|
log(
|
|
5315
5971
|
"warn",
|
|
@@ -5714,6 +6370,12 @@ async function callOneBotAPI(internal, action, params, fallbacks = []) {
|
|
|
5714
6370
|
|
|
5715
6371
|
// src/index.ts
|
|
5716
6372
|
var usage = `
|
|
6373
|
+
## \u4F7F\u7528\u8BF4\u660E
|
|
6374
|
+
|
|
6375
|
+
\u9996\u6B21\u4F7F\u7528\u524D\u8BF7\u5148\u9605\u8BFB [readme.md](https://github.com/Sor85/AAAAACAT-chatluna-plugins/blob/main/plugins/chatluna-affinity/readme.md)\uFF0C\u6309\u6587\u6863\u5B8C\u6210\u4F9D\u8D56\u5B89\u88C5\u3001\`scopeId\` \u914D\u7F6E\u3001\u53D8\u91CF\u6CE8\u5165\u548C XML \u5DE5\u5177\u63A5\u5165\u3002
|
|
6376
|
+
|
|
6377
|
+
\u5982\u679C\u4F60\u4E3B\u8981\u5728 ChatLuna Character \u4E2D\u4F7F\u7528\u672C\u63D2\u4EF6\uFF0C\u8BF7\u4F18\u5148\u67E5\u770B readme.md \u4E2D\u7684\u201C\u5FEB\u901F\u4E0A\u624B\u201D\u548C\u201C\u53D8\u91CF\u201D\u7AE0\u8282\u3002
|
|
6378
|
+
|
|
5717
6379
|
## \u66F4\u65B0\u65E5\u5FD7
|
|
5718
6380
|
|
|
5719
6381
|
0.3.0
|
|
@@ -5789,6 +6451,7 @@ var usage = `
|
|
|
5789
6451
|
COMMON_STYLE,
|
|
5790
6452
|
Config,
|
|
5791
6453
|
ConfigSchema,
|
|
6454
|
+
DASHBOARD_SNAPSHOT_MODEL_NAME,
|
|
5792
6455
|
DEFAULT_MEMBER_INFO_ITEMS,
|
|
5793
6456
|
FETCH_CONSTANTS,
|
|
5794
6457
|
MIGRATION_MODEL_NAME,
|
|
@@ -5802,6 +6465,7 @@ var usage = `
|
|
|
5802
6465
|
THRESHOLDS,
|
|
5803
6466
|
TIME_CONSTANTS,
|
|
5804
6467
|
TIMING_CONSTANTS,
|
|
6468
|
+
USER_AFFINITY_SNAPSHOT_MODEL_NAME,
|
|
5805
6469
|
USER_ALIAS_MODEL_NAME,
|
|
5806
6470
|
USER_ALIAS_MODEL_NAME_V2,
|
|
5807
6471
|
appendActionEntry,
|
|
@@ -5846,6 +6510,7 @@ var usage = `
|
|
|
5846
6510
|
escapeHtmlForRender,
|
|
5847
6511
|
extendAffinityModel,
|
|
5848
6512
|
extendBlacklistModel,
|
|
6513
|
+
extendDashboardSnapshotModel,
|
|
5849
6514
|
extendMigrationModel,
|
|
5850
6515
|
extendUserAliasModel,
|
|
5851
6516
|
fetchGroupMemberIds,
|