koishi-plugin-chat-analyse 0.5.0 → 0.5.1

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.
@@ -0,0 +1,88 @@
1
+ import { Context } from 'koishi';
2
+ import { Config } from './index';
3
+ declare module 'koishi' {
4
+ interface Tables {
5
+ analyse_user: {
6
+ uid: number;
7
+ channelId: string;
8
+ userId: string;
9
+ channelName: string;
10
+ userName: string;
11
+ };
12
+ analyse_cmd: {
13
+ uid: number;
14
+ command: string;
15
+ count: number;
16
+ timestamp: Date;
17
+ };
18
+ analyse_msg: {
19
+ uid: number;
20
+ type: string;
21
+ count: number;
22
+ timestamp: Date;
23
+ };
24
+ analyse_rank: {
25
+ uid: number;
26
+ type: string;
27
+ count: number;
28
+ timestamp: Date;
29
+ };
30
+ analyse_cache: {
31
+ id: number;
32
+ uid: number;
33
+ content: string;
34
+ timestamp: Date;
35
+ };
36
+ analyse_at: {
37
+ id: number;
38
+ uid: number;
39
+ target: string;
40
+ content: string;
41
+ timestamp: Date;
42
+ };
43
+ }
44
+ }
45
+ /**
46
+ * @class Collector
47
+ * @description 核心数据收集器。根据配置,高效地监听、收集、缓冲并持久化聊天数据。
48
+ */
49
+ export declare class Collector {
50
+ private ctx;
51
+ private config;
52
+ /** @property FLUSH_INTERVAL - 内存缓存区定时刷入数据库的间隔(毫秒)。 */
53
+ private static readonly FLUSH_INTERVAL;
54
+ /** @property BUFFER_THRESHOLD - 内存缓存区触发刷新的消息数量阈值。 */
55
+ private static readonly BUFFER_THRESHOLD;
56
+ private msgStatBuffer;
57
+ private rankStatBuffer;
58
+ private cmdStatBuffer;
59
+ private oriCacheBuffer;
60
+ private whoAtBuffer;
61
+ private userCache;
62
+ private channelCache;
63
+ private pendingRequests;
64
+ private flushInterval;
65
+ /**
66
+ * @param ctx - Koishi 的插件上下文。
67
+ * @param config - 插件的配置对象。
68
+ */
69
+ constructor(ctx: Context, config: Config);
70
+ /**
71
+ * @private @method onMessage
72
+ * @description 统一的消息事件处理器,解析消息并更新各类统计数据的缓冲区。
73
+ * @param session - Koishi 的会话对象。
74
+ */
75
+ private onMessage;
76
+ /**
77
+ * @private @method sanitizeContent
78
+ * @description 将 Koishi 消息元素数组净化为纯文本字符串。
79
+ * @param elements - 消息元素数组。
80
+ * @returns 净化后的纯文本。
81
+ */
82
+ private sanitizeContent;
83
+ /**
84
+ * @private @method flushBuffers
85
+ * @description 将所有内存中的数据缓冲区批量写入数据库,并清空缓冲区。
86
+ */
87
+ private flushBuffers;
88
+ }
package/lib/index.js CHANGED
@@ -68,7 +68,7 @@ var Collector = class _Collector {
68
68
  /** @property FLUSH_INTERVAL - 内存缓存区定时刷入数据库的间隔(毫秒)。 */
69
69
  static FLUSH_INTERVAL = import_koishi.Time.minute;
70
70
  /** @property BUFFER_THRESHOLD - 内存缓存区触发刷新的消息数量阈值。 */
71
- static BUFFER_THRESHOLD = 100;
71
+ static BUFFER_THRESHOLD = 60;
72
72
  // 统一的数据缓冲区
73
73
  msgStatBuffer = /* @__PURE__ */ new Map();
74
74
  rankStatBuffer = /* @__PURE__ */ new Map();
@@ -76,7 +76,8 @@ var Collector = class _Collector {
76
76
  oriCacheBuffer = [];
77
77
  whoAtBuffer = [];
78
78
  userCache = /* @__PURE__ */ new Map();
79
- pendingUserRequests = /* @__PURE__ */ new Map();
79
+ channelCache = /* @__PURE__ */ new Map();
80
+ pendingRequests = /* @__PURE__ */ new Map();
80
81
  flushInterval;
81
82
  /**
82
83
  * @private @method onMessage
@@ -90,35 +91,41 @@ var Collector = class _Collector {
90
91
  let user;
91
92
  if (this.userCache.has(cacheKey)) {
92
93
  user = this.userCache.get(cacheKey);
93
- } else if (this.pendingUserRequests.has(cacheKey)) {
94
- user = await this.pendingUserRequests.get(cacheKey);
94
+ } else if (this.pendingRequests.has(cacheKey)) {
95
+ user = await this.pendingRequests.get(cacheKey);
95
96
  } else {
96
97
  const promise = (async () => {
97
98
  try {
98
99
  const [dbUser] = await this.ctx.database.get("analyse_user", { channelId, userId });
99
100
  const currentUserName = session.username ?? "";
100
- const guild = await bot.getGuild(channelId).catch(() => null);
101
- const currentChannelName = guild?.name ?? "";
101
+ let currentChannelName = this.channelCache.get(channelId);
102
+ if (currentChannelName === void 0) {
103
+ const guild = await bot.getGuild(channelId).catch(() => null);
104
+ currentChannelName = guild?.name ?? "";
105
+ if (currentChannelName) this.channelCache.set(channelId, currentChannelName);
106
+ }
102
107
  if (dbUser) {
103
108
  if (currentUserName && dbUser.userName !== currentUserName || currentChannelName && dbUser.channelName !== currentChannelName) {
104
109
  await this.ctx.database.set("analyse_user", { uid: dbUser.uid }, { userName: currentUserName, channelName: currentChannelName });
105
110
  dbUser.userName = currentUserName;
106
111
  dbUser.channelName = currentChannelName;
107
112
  }
108
- this.userCache.set(cacheKey, dbUser);
109
- return dbUser;
113
+ const cacheData2 = { uid: dbUser.uid, userName: dbUser.userName };
114
+ this.userCache.set(cacheKey, cacheData2);
115
+ return cacheData2;
110
116
  }
111
117
  const createdUser = await this.ctx.database.create("analyse_user", { channelId, userId, userName: currentUserName, channelName: currentChannelName });
112
- this.userCache.set(cacheKey, createdUser);
113
- return createdUser;
118
+ const cacheData = { uid: createdUser.uid, userName: createdUser.userName };
119
+ this.userCache.set(cacheKey, cacheData);
120
+ return cacheData;
114
121
  } catch (error) {
115
122
  this.ctx.logger.error(`创建或获取用户(${cacheKey})失败:`, error);
116
123
  return null;
117
124
  } finally {
118
- this.pendingUserRequests.delete(cacheKey);
125
+ this.pendingRequests.delete(cacheKey);
119
126
  }
120
127
  })();
121
- this.pendingUserRequests.set(cacheKey, promise);
128
+ this.pendingRequests.set(cacheKey, promise);
122
129
  user = await promise;
123
130
  }
124
131
  if (!user) return;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-chat-analyse",
3
3
  "description": "聊天记录分析",
4
- "version": "0.5.0",
4
+ "version": "0.5.1",
5
5
  "contributors": [
6
6
  "Yis_Rime <yis_rime@outlook.com>"
7
7
  ],