koishi-plugin-chat-patch 2.4.5 → 3.0.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/src/index.ts CHANGED
@@ -7,6 +7,7 @@ import { MessageHandler } from './message-handler'
7
7
  import { FileManager } from './file-manager'
8
8
  import { ApiHandlers } from './api-handlers'
9
9
  import { Config } from './config'
10
+ import { createPluginLogger } from './logger'
10
11
  import { Utils } from './utils'
11
12
 
12
13
  export const name = 'chat-patch'
@@ -36,127 +37,50 @@ export const usage = `
36
37
  export { Config } from './config'
37
38
 
38
39
  export async function apply(ctx: Context, config: Config) {
39
- const logger = ctx.logger('chat-patch')
40
-
41
- const mediaDir = path.join(ctx.baseDir, 'data', 'chat-patch', 'persist-media', 'media')
42
- if (require('node:fs').existsSync(mediaDir)) {
43
- try {
44
- const files = require('node:fs').readdirSync(mediaDir)
45
- let deletedCount = 0
46
- for (const file of files) {
47
- const filePath = path.join(mediaDir, file)
48
- try {
49
- require('node:fs').unlinkSync(filePath)
50
- deletedCount++
51
- } catch (e) {
52
- logger.warn('删除媒体文件失败:', filePath, e)
53
- }
54
- }
55
- if (deletedCount > 0) {
56
- logger.info(`启动时清理了 ${deletedCount} 个旧版本的媒体缓存文件`)
57
- }
58
- } catch (e) {
59
- logger.warn('清理媒体文件夹失败:', e)
60
- }
61
- }
62
-
63
- const fileManager = new FileManager(ctx, config)
64
- const messageHandler = new MessageHandler(ctx, config, fileManager)
65
- const apiHandlers = new ApiHandlers(ctx, config, fileManager, messageHandler)
66
- const utils = new Utils(config, ctx)
40
+ const pluginLogger = createPluginLogger(ctx.logger('chat-patch'), config)
67
41
 
68
- const initialData = fileManager.readChatDataFromFile()
69
- const cleanedData = fileManager.cleanExcessMessages(initialData)
42
+ const fileManager = new FileManager(ctx, config, pluginLogger)
43
+ await fileManager.initialize()
70
44
 
71
- const originalCount = Object.values(initialData.messages).reduce((total, msgs) => total + msgs.length, 0)
72
- const cleanedCount = Object.values(cleanedData.messages).reduce((total, msgs) => total + msgs.length, 0)
73
-
74
- if (originalCount !== cleanedCount) {
75
- fileManager.writeChatDataToFile(cleanedData)
76
- }
45
+ const messageHandler = new MessageHandler(ctx, config, fileManager, pluginLogger)
46
+ const apiHandlers = new ApiHandlers(ctx, config, fileManager, messageHandler, pluginLogger)
47
+ const utils = new Utils(config, ctx)
77
48
 
78
- function logInfo(...args: any[]) {
79
- if (config.loggerinfo) {
80
- (logger.info as (...args: any[]) => void)(...args)
81
- }
82
- }
49
+ const metadata = await fileManager.readMetadataOnly()
83
50
 
84
- logInfo('插件加载完成,数据统计:', {
85
- 机器人数量: Object.keys(cleanedData.bots).length,
86
- 频道数量: Object.keys(cleanedData.channels).reduce((total, botId) =>
87
- total + Object.keys(cleanedData.channels[botId] || {}).length, 0),
88
- 消息频道数: Object.keys(cleanedData.messages).length,
89
- 总消息数: Object.values(cleanedData.messages).reduce((total, msgs) => total + msgs.length, 0)
51
+ pluginLogger.logInfo('插件加载完成,元数据统计:', {
52
+ 机器人数量: Object.keys(metadata.bots).length,
53
+ 频道数量: Object.keys(metadata.channels).reduce((total, botId) =>
54
+ total + Object.keys(metadata.channels[botId] || {}).length, 0),
55
+ 置顶机器人数量: metadata.pinnedBots.length,
56
+ 置顶频道数量: metadata.pinnedChannels.length
90
57
  })
91
58
 
92
59
  ctx.on('message', (session) => {
93
60
  if (utils.isPlatformBlocked(session.platform || 'unknown')) return
94
61
 
95
- const timestamp = Date.now()
96
-
97
- ctx.console.broadcast('chat-message-event', {
98
- type: 'message',
99
- selfId: session.selfId,
100
- platform: session.platform || 'unknown',
101
- channelId: session.channelId,
102
- messageId: session.event?.message?.id || `msg-${timestamp}`,
103
- content: session.content || '',
104
- userId: session.userId || 'unknown',
105
- username: session.username || session.userId || 'unknown',
106
- avatar: session.event?.user?.avatar,
107
- timestamp: timestamp,
108
- isDirect: session.isDirect,
109
- elements: utils.cleanBase64Content(session.elements, false),
110
- bot: {
111
- avatar: session.bot.user?.avatar,
112
- name: session.bot.user?.name,
113
- }
114
- })
115
-
116
- messageHandler.recordUserMessage(session, timestamp)
62
+ messageHandler.recordUserMessage(session, Date.now())
117
63
  })
118
64
 
119
65
  ctx.on('before-send', (session) => {
120
66
  if (utils.isPlatformBlocked(session.platform || 'unknown')) return
121
67
 
122
- const timestamp = Date.now()
123
-
124
- ctx.console.broadcast('chat-bot-message-event', {
125
- type: 'bot-message',
126
- selfId: session.selfId,
127
- platform: session.platform || 'unknown',
128
- channelId: session.channelId,
129
- messageId: `bot-msg-${timestamp}`,
130
- content: session.content || '',
131
- userId: session.selfId,
132
- username: session.bot.user?.name || `Bot-${session.selfId}`,
133
- avatar: session.bot.user?.avatar,
134
- timestamp: timestamp,
135
- sending: true,
136
- elements: utils.cleanBase64Content(session.event?.message?.elements, true),
137
- bot: {
138
- avatar: session.bot.user?.avatar,
139
- name: session.bot.user?.name,
140
- }
141
- })
142
-
143
- messageHandler.recordBotMessage(session, timestamp)
68
+ messageHandler.recordBotMessage(session, Date.now())
144
69
  })
145
70
 
146
- ctx.on('ready', async () => {
147
- logInfo('插件启动完成,开始监听消息')
71
+ let cleanupDelayTimer: (() => void) | undefined
72
+ let cleanupInterval: (() => void) | undefined
148
73
 
149
- ctx.setInterval(() => {
150
- const data = fileManager.readChatDataFromFile()
151
- const cleanedData = fileManager.cleanExcessMessages(data)
74
+ ctx.on('ready', async () => {
75
+ pluginLogger.logInfo('插件启动完成,开始监听消息')
152
76
 
153
- const originalCount = Object.values(data.messages).reduce((total, msgs) => total + msgs.length, 0)
154
- const cleanedCount = Object.values(cleanedData.messages).reduce((total, msgs) => total + msgs.length, 0)
77
+ // 延后清理,避免和 Koishi ready 时的资源竞争。
78
+ cleanupDelayTimer = ctx.setTimeout(() => {
79
+ void fileManager.cleanupExcessMessagesInStorage()
80
+ }, 15000)
155
81
 
156
- if (originalCount !== cleanedCount) {
157
- fileManager.writeChatDataToFile(cleanedData)
158
- logInfo('定期清理完成,清理了', originalCount - cleanedCount, '条超量消息')
159
- }
82
+ cleanupInterval = ctx.setInterval(() => {
83
+ void fileManager.cleanupExcessMessagesInStorage()
160
84
  }, 300000)
161
85
  })
162
86
 
@@ -168,8 +92,10 @@ export async function apply(ctx: Context, config: Config) {
168
92
  })
169
93
 
170
94
  ctx.on('dispose', () => {
171
-
172
- fileManager.dispose()
173
- logInfo('插件已卸载,所有待处理的消息已写入')
95
+ cleanupDelayTimer?.()
96
+ cleanupInterval?.()
97
+ messageHandler.dispose()
98
+ void fileManager.dispose()
99
+ pluginLogger.logInfo('插件已卸载,所有待处理的消息已写入')
174
100
  })
175
101
  }
package/src/logger.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { Logger } from 'koishi'
2
+
3
+ import { Config } from './config'
4
+
5
+ export interface PluginLogger {
6
+ logInfo(...args: unknown[]): void
7
+ info(...args: unknown[]): void
8
+ warn(...args: unknown[]): void
9
+ error(...args: unknown[]): void
10
+ }
11
+
12
+ export function createPluginLogger(logger: Logger, config: Pick<Config, 'loggerinfo'>): PluginLogger {
13
+ return {
14
+ logInfo(...args: unknown[]) {
15
+ if (config.loggerinfo) {
16
+ Reflect.apply(logger.info, logger, args)
17
+ }
18
+ },
19
+ info(...args: unknown[]) {
20
+ Reflect.apply(logger.info, logger, args)
21
+ },
22
+ warn(...args: unknown[]) {
23
+ Reflect.apply(logger.warn, logger, args)
24
+ },
25
+ error(...args: unknown[]) {
26
+ Reflect.apply(logger.error, logger, args)
27
+ }
28
+ }
29
+ }