koishi-plugin-chat-analyse 0.4.6 → 0.4.8

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.
@@ -91,6 +91,17 @@ export declare class Collector {
91
91
  * @returns {Promise<UserCache | null>} 返回用户的缓存对象,如果操作失败则返回 `null`。
92
92
  */
93
93
  private getOrCreateCachedUser;
94
+ /**
95
+ * @private
96
+ * @async
97
+ * @method fetchApiNames
98
+ * @description 并发调用机器人API以获取用户和频道名称,作为备用数据源。
99
+ * @param bot - The bot instance.
100
+ * @param guildId - The guild ID.
101
+ * @param userId - The user ID.
102
+ * @returns {Promise<{userName: string, channelName: string}>} - 包含名称的对象。
103
+ */
104
+ private fetchApiNames;
94
105
  /**
95
106
  * @private
96
107
  * @method sanitizeContent
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.js CHANGED
@@ -202,46 +202,42 @@ var Collector = class _Collector {
202
202
  * @returns {Promise<UserCache | null>} 返回用户的缓存对象,如果操作失败则返回 `null`。
203
203
  */
204
204
  async getOrCreateCachedUser(session, channelId) {
205
- const { userId, bot, guildId } = session;
205
+ const { userId, bot } = session;
206
206
  const cacheKey = `${channelId}:${userId}`;
207
207
  if (this.userCache.has(cacheKey)) return this.userCache.get(cacheKey);
208
208
  if (this.pendingUserRequests.has(cacheKey)) return this.pendingUserRequests.get(cacheKey);
209
209
  const promise = (async () => {
210
210
  try {
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;
215
- }
216
- const [guild, member] = await Promise.all([
217
- guildId ? bot.getGuild(guildId).catch(() => null) : Promise.resolve(null),
218
- guildId ? bot.getGuildMember(guildId, userId).catch(() => null) : Promise.resolve(null)
219
- ]);
220
- const user = !member ? await bot.getUser(userId).catch(() => null) : null;
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
- });
211
+ const sessionUserName = session.username || "";
212
+ const sessionChannelName = session.event._data.raw.peerName || session.guild.name || "";
213
+ const dbUser = await this.ctx.database.get("analyse_user", { channelId, userId });
214
+ if (dbUser[0]) {
215
+ const user = dbUser[0];
216
+ const nameChanged = sessionUserName && user.userName !== sessionUserName;
217
+ const channelNameChanged = sessionChannelName && user.channelName !== sessionChannelName;
218
+ if (nameChanged || channelNameChanged) {
219
+ user.userName = nameChanged ? sessionUserName : user.userName;
220
+ user.channelName = channelNameChanged ? sessionChannelName : user.channelName;
221
+ await this.ctx.database.set("analyse_user", { uid: user.uid }, { userName: user.userName, channelName: user.channelName });
232
222
  }
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;
223
+ this.userCache.set(cacheKey, user);
224
+ return user;
244
225
  }
226
+ let finalUserName = sessionUserName;
227
+ let finalChannelName = sessionChannelName;
228
+ if (!finalUserName || !finalChannelName) {
229
+ const apiData = await this.fetchApiNames(bot, session.guildId || channelId, userId);
230
+ finalUserName = finalUserName || apiData.userName;
231
+ finalChannelName = finalChannelName || apiData.channelName;
232
+ }
233
+ const createdUser = await this.ctx.database.create("analyse_user", {
234
+ channelId,
235
+ userId,
236
+ userName: finalUserName,
237
+ channelName: finalChannelName
238
+ });
239
+ this.userCache.set(cacheKey, createdUser);
240
+ return createdUser;
245
241
  } catch (error) {
246
242
  this.ctx.logger.error(`创建或获取用户(${cacheKey})失败:`, error);
247
243
  return null;
@@ -252,6 +248,30 @@ var Collector = class _Collector {
252
248
  this.pendingUserRequests.set(cacheKey, promise);
253
249
  return promise;
254
250
  }
251
+ /**
252
+ * @private
253
+ * @async
254
+ * @method fetchApiNames
255
+ * @description 并发调用机器人API以获取用户和频道名称,作为备用数据源。
256
+ * @param bot - The bot instance.
257
+ * @param guildId - The guild ID.
258
+ * @param userId - The user ID.
259
+ * @returns {Promise<{userName: string, channelName: string}>} - 包含名称的对象。
260
+ */
261
+ async fetchApiNames(bot, guildId, userId) {
262
+ const results = await Promise.allSettled([
263
+ guildId && bot.getGuildMember ? bot.getGuildMember(guildId, userId) : Promise.resolve(null),
264
+ bot.getUser ? bot.getUser(userId) : Promise.resolve(null),
265
+ guildId && bot.getGuild ? bot.getGuild(guildId) : Promise.resolve(null)
266
+ ]);
267
+ const member = results[0].status === "fulfilled" ? results[0].value : null;
268
+ const user = results[1].status === "fulfilled" ? results[1].value : null;
269
+ const guild = results[2].status === "fulfilled" ? results[2].value : null;
270
+ return {
271
+ userName: member?.username || member?.nick || member?.name || user?.name || "",
272
+ channelName: guild?.name || ""
273
+ };
274
+ }
255
275
  /**
256
276
  * @private
257
277
  * @method sanitizeContent
@@ -1078,6 +1098,15 @@ var Data = class {
1078
1098
  return "数据清理失败";
1079
1099
  }
1080
1100
  });
1101
+ analyse.subcommand(".list", "列出频道及命令", { authority: 4 }).action(async () => {
1102
+ const allChannelInfo = await this.ctx.database.get("analyse_user", {}, ["channelId", "channelName"]);
1103
+ const uniqueChannels = [...new Map(allChannelInfo.map((item) => [item.channelId, item])).values()];
1104
+ const channelOutput = uniqueChannels.length > 0 ? "频道列表:\n" + uniqueChannels.map((c) => `[${c.channelId}] ${c.channelName}`).join("\n") : "暂无频道记录";
1105
+ const commands = await this.ctx.database.select("analyse_cmd").distinct("command").execute();
1106
+ const commandOutput = commands.length > 0 ? "命令列表:\n" + commands.map((c) => c.command).join(", ") : "暂无命令记录";
1107
+ return `${channelOutput}
1108
+ ${commandOutput}`;
1109
+ });
1081
1110
  }
1082
1111
  };
1083
1112
 
@@ -1099,12 +1128,12 @@ var using = ["database", "puppeteer", "cron"];
1099
1128
  var Config = import_koishi6.Schema.intersect([
1100
1129
  import_koishi6.Schema.object({
1101
1130
  enableListener: import_koishi6.Schema.boolean().default(true).description("启用消息监听"),
1102
- enableOriRecord: import_koishi6.Schema.boolean().default(true).description("启用原始记录")
1131
+ enableData: import_koishi6.Schema.boolean().default(false).description("启用数据管理")
1103
1132
  }).description("监听配置"),
1104
1133
  import_koishi6.Schema.object({
1105
1134
  enableCmdStat: import_koishi6.Schema.boolean().default(true).description("启用命令统计"),
1106
1135
  enableMsgStat: import_koishi6.Schema.boolean().default(true).description("启用消息统计"),
1107
- enableData: import_koishi6.Schema.boolean().default(false).description("启用数据管理")
1136
+ enableOriRecord: import_koishi6.Schema.boolean().default(true).description("启用原始记录")
1108
1137
  }).description("功能配置"),
1109
1138
  import_koishi6.Schema.object({
1110
1139
  enableRankStat: import_koishi6.Schema.boolean().default(true).description("启用发言排行"),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-chat-analyse",
3
3
  "description": "聊天记录分析",
4
- "version": "0.4.6",
4
+ "version": "0.4.8",
5
5
  "contributors": [
6
6
  "Yis_Rime <yis_rime@outlook.com>"
7
7
  ],