koishi-plugin-chat-analyse 0.4.5 → 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/Debug.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { Context, Command } from 'koishi';
2
+ /**
3
+ * @class Debug
4
+ * @description
5
+ * 提供一系列调试工具,用于数据维护和状态检查。
6
+ * 包括手动补全用户信息、列出数据库中的频道和命令等功能。
7
+ */
8
+ export declare class Debug {
9
+ private ctx;
10
+ /**
11
+ * @constructor
12
+ * @param {Context} ctx - Koishi 的插件上下文。
13
+ */
14
+ constructor(ctx: Context);
15
+ /**
16
+ * @public
17
+ * @method registerCommands
18
+ * @description 在 'analyse' 命令下注册所有调试相关的子命令。
19
+ * @param {Command} analyse - 主 'analyse' 命令实例。
20
+ */
21
+ registerCommands(analyse: Command): void;
22
+ }
package/lib/index.d.ts CHANGED
@@ -18,6 +18,7 @@ export interface Config {
18
18
  enableOriRecord: boolean;
19
19
  enableWhoAt: boolean;
20
20
  enableData: boolean;
21
+ enableDebug: boolean;
21
22
  atRetentionDays: number;
22
23
  rankRetentionDays: number;
23
24
  }
package/lib/index.js CHANGED
@@ -208,29 +208,40 @@ var Collector = class _Collector {
208
208
  if (this.pendingUserRequests.has(cacheKey)) return this.pendingUserRequests.get(cacheKey);
209
209
  const promise = (async () => {
210
210
  try {
211
- const existing = await this.ctx.database.get("analyse_user", { channelId, userId });
212
- if (existing.length > 0) {
213
- const { uid: uid2, userName: userName2, channelName: channelName2 } = existing[0];
214
- const cachedUser2 = { uid: uid2, userName: userName2, channelName: channelName2 };
215
- this.userCache.set(cacheKey, cachedUser2);
216
- return cachedUser2;
211
+ const [dbUser] = await this.ctx.database.get("analyse_user", { channelId, userId });
212
+ if (dbUser && dbUser.userName && dbUser.channelName) {
213
+ this.userCache.set(cacheKey, dbUser);
214
+ return dbUser;
217
215
  }
218
216
  const [guild, member] = await Promise.all([
219
217
  guildId ? bot.getGuild(guildId).catch(() => null) : Promise.resolve(null),
220
218
  guildId ? bot.getGuildMember(guildId, userId).catch(() => null) : Promise.resolve(null)
221
219
  ]);
222
220
  const user = !member ? await bot.getUser(userId).catch(() => null) : null;
223
- const newUserRecord = {
224
- channelId,
225
- userId,
226
- channelName: guild?.name || channelId,
227
- userName: member?.nick || member?.name || user?.name || userId
228
- };
229
- const createdUser = await this.ctx.database.create("analyse_user", newUserRecord);
230
- const { uid, userName, channelName } = createdUser;
231
- const cachedUser = { uid, userName, channelName };
232
- this.userCache.set(cacheKey, cachedUser);
233
- return cachedUser;
221
+ const fetchedUserName = member?.nick || member?.name || user?.name || "";
222
+ const fetchedChannelName = guild?.name || "";
223
+ if (dbUser) {
224
+ const needsUpdate = !dbUser.userName && fetchedUserName || !dbUser.channelName && fetchedChannelName;
225
+ if (needsUpdate) {
226
+ dbUser.userName = dbUser.userName || fetchedUserName;
227
+ dbUser.channelName = dbUser.channelName || fetchedChannelName;
228
+ await this.ctx.database.set("analyse_user", { uid: dbUser.uid }, {
229
+ userName: dbUser.userName,
230
+ channelName: dbUser.channelName
231
+ });
232
+ }
233
+ if (dbUser.userName && dbUser.channelName) this.userCache.set(cacheKey, dbUser);
234
+ return dbUser;
235
+ } else {
236
+ const createdUser = await this.ctx.database.create("analyse_user", {
237
+ channelId,
238
+ userId,
239
+ userName: fetchedUserName,
240
+ channelName: fetchedChannelName
241
+ });
242
+ if (createdUser.userName && createdUser.channelName) this.userCache.set(cacheKey, createdUser);
243
+ return createdUser;
244
+ }
234
245
  } catch (error) {
235
246
  this.ctx.logger.error(`创建或获取用户(${cacheKey})失败:`, error);
236
247
  return null;
@@ -894,8 +905,9 @@ var WhoAt = class {
894
905
  const userInfoMap = new Map(users.map((u) => [u.uid, { name: u.userName, id: u.userId }]));
895
906
  const messageElements = records.map((record) => {
896
907
  const senderInfo = userInfoMap.get(record.uid);
897
- const userId = senderInfo?.id;
898
- const authorElement = (0, import_koishi4.h)("author", { userId, name: userId });
908
+ const userId = senderInfo.id;
909
+ const userName = senderInfo.name || userId;
910
+ const authorElement = (0, import_koishi4.h)("author", { userId, name: userName });
899
911
  const contentElement = import_koishi4.h.text(record.content);
900
912
  return (0, import_koishi4.h)("message", {}, [authorElement, contentElement]);
901
913
  });
@@ -1069,6 +1081,81 @@ var Data = class {
1069
1081
  }
1070
1082
  };
1071
1083
 
1084
+ // src/Debug.ts
1085
+ var Debug = class {
1086
+ /**
1087
+ * @constructor
1088
+ * @param {Context} ctx - Koishi 的插件上下文。
1089
+ */
1090
+ constructor(ctx) {
1091
+ this.ctx = ctx;
1092
+ }
1093
+ static {
1094
+ __name(this, "Debug");
1095
+ }
1096
+ /**
1097
+ * @public
1098
+ * @method registerCommands
1099
+ * @description 在 'analyse' 命令下注册所有调试相关的子命令。
1100
+ * @param {Command} analyse - 主 'analyse' 命令实例。
1101
+ */
1102
+ registerCommands(analyse) {
1103
+ analyse.subcommand(".fill", "手动补全用户信息", { authority: 4 }).action(async ({ session }) => {
1104
+ const bots = this.ctx.bots;
1105
+ if (bots.length === 0) return "暂无可用机器人";
1106
+ const usersToUpdate = await this.ctx.database.get("analyse_user", {
1107
+ $or: [{ userName: "" }, { channelName: "" }]
1108
+ });
1109
+ if (usersToUpdate.length === 0) return "暂无用户信息需要补全";
1110
+ const usersByChannel = usersToUpdate.reduce((acc, user) => {
1111
+ (acc[user.channelId] = acc[user.channelId] || []).push(user);
1112
+ return acc;
1113
+ }, {});
1114
+ let updatedCount = 0;
1115
+ const bot = bots.find((b) => b.platform === session.platform) || bots[0];
1116
+ for (const channelId in usersByChannel) {
1117
+ const usersInChannel = usersByChannel[channelId];
1118
+ let channelName = usersInChannel.find((u) => u.channelName)?.channelName || "";
1119
+ if (!channelName && channelId) {
1120
+ try {
1121
+ channelName = (await bot.getGuild(channelId))?.name || "";
1122
+ } catch (e) {
1123
+ this.ctx.logger.warn(`获取频道 ${channelId} 信息失败:`, e);
1124
+ }
1125
+ }
1126
+ for (const user of usersInChannel) {
1127
+ if (user.userName && user.channelName) continue;
1128
+ let userName = user.userName;
1129
+ if (!userName && user.userId && channelId) {
1130
+ try {
1131
+ const member = await bot.getGuildMember(channelId, user.userId);
1132
+ userName = member?.nick || member?.name || "";
1133
+ if (!userName) userName = (await bot.getUser(user.userId))?.name || "";
1134
+ } catch (e) {
1135
+ this.ctx.logger.warn(`获取频道 ${channelId} 的用户 ${user.userId} 信息失败:`, e);
1136
+ }
1137
+ }
1138
+ await this.ctx.database.set("analyse_user", { uid: user.uid }, {
1139
+ userName: userName || user.userName,
1140
+ channelName: channelName || user.channelName
1141
+ });
1142
+ updatedCount++;
1143
+ }
1144
+ }
1145
+ return `已补全 ${updatedCount} 条用户信息`;
1146
+ });
1147
+ analyse.subcommand(".list", "列出频道及命令", { authority: 4 }).action(async () => {
1148
+ const allChannelInfo = await this.ctx.database.get("analyse_user", {}, ["channelId", "channelName"]);
1149
+ const uniqueChannels = [...new Map(allChannelInfo.map((item) => [item.channelId, item])).values()];
1150
+ const channelOutput = uniqueChannels.length > 0 ? "频道列表:\n" + uniqueChannels.map((c) => `[${c.channelId}] ${c.channelName}`).join("\n") : "暂无频道记录";
1151
+ const commands = await this.ctx.database.select("analyse_cmd").distinct("command").execute();
1152
+ const commandOutput = commands.length > 0 ? "命令列表:\n" + commands.map((c) => c.command).join(", ") : "暂无命令记录";
1153
+ return `${channelOutput}
1154
+ ${commandOutput}`;
1155
+ });
1156
+ }
1157
+ };
1158
+
1072
1159
  // src/index.ts
1073
1160
  var usage = `
1074
1161
  <div style="border-radius: 10px; border: 1px solid #ddd; padding: 16px; margin-bottom: 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1);">
@@ -1091,8 +1178,7 @@ var Config = import_koishi6.Schema.intersect([
1091
1178
  }).description("监听配置"),
1092
1179
  import_koishi6.Schema.object({
1093
1180
  enableCmdStat: import_koishi6.Schema.boolean().default(true).description("启用命令统计"),
1094
- enableMsgStat: import_koishi6.Schema.boolean().default(true).description("启用消息统计"),
1095
- enableData: import_koishi6.Schema.boolean().default(false).description("启用数据管理")
1181
+ enableMsgStat: import_koishi6.Schema.boolean().default(true).description("启用消息统计")
1096
1182
  }).description("功能配置"),
1097
1183
  import_koishi6.Schema.object({
1098
1184
  enableRankStat: import_koishi6.Schema.boolean().default(true).description("启用发言排行"),
@@ -1101,7 +1187,11 @@ var Config = import_koishi6.Schema.intersect([
1101
1187
  import_koishi6.Schema.object({
1102
1188
  enableWhoAt: import_koishi6.Schema.boolean().default(true).description("启用 @ 记录"),
1103
1189
  atRetentionDays: import_koishi6.Schema.number().min(0).default(7).description("记录保留天数")
1104
- }).description("@ 记录配置")
1190
+ }).description("@ 记录配置"),
1191
+ import_koishi6.Schema.object({
1192
+ enableData: import_koishi6.Schema.boolean().default(false).description("启用数据管理"),
1193
+ enableDebug: import_koishi6.Schema.boolean().default(false).description("启用调试工具")
1194
+ }).description("高级功能")
1105
1195
  ]);
1106
1196
  function apply(ctx, config) {
1107
1197
  if (config.enableListener) new Collector(ctx, config);
@@ -1109,6 +1199,7 @@ function apply(ctx, config) {
1109
1199
  new Stat(ctx, config).registerCommands(analyse);
1110
1200
  if (config.enableWhoAt) new WhoAt(ctx, config).registerCommand(analyse);
1111
1201
  if (config.enableData) new Data(ctx).registerCommands(analyse);
1202
+ if (config.enableDebug) new Debug(ctx).registerCommands(analyse);
1112
1203
  }
1113
1204
  __name(apply, "apply");
1114
1205
  // Annotate the CommonJS export names for ESM import in node:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-chat-analyse",
3
3
  "description": "聊天记录分析",
4
- "version": "0.4.5",
4
+ "version": "0.4.7",
5
5
  "contributors": [
6
6
  "Yis_Rime <yis_rime@outlook.com>"
7
7
  ],