koishi-plugin-chat-patch 2.2.0 → 2.4.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/client/icons/activity.vue +9 -9
- package/client/icons/index.ts +4 -4
- package/client/index.scss +90 -90
- package/client/index.ts +25 -25
- package/client/vue/composables/useChatActions.ts +1 -1
- package/client/vue/composables/useChatData.ts +1 -1
- package/client/vue/composables/useImageCache.ts +1 -1
- package/client/vue/types.ts +1 -1
- package/dist/index.js +2 -2
- package/lib/file-manager.d.ts +32 -0
- package/lib/index.js +417 -197
- package/lib/message-handler.d.ts +7 -5
- package/package.json +1 -1
- package/readme.md +25 -25
- package/src/api-handlers.ts +19 -65
- package/src/config.ts +45 -46
- package/src/file-manager.ts +367 -169
- package/src/index.ts +58 -31
- package/src/message-handler.ts +161 -134
- package/src/types.ts +62 -62
- package/src/utils.ts +4 -16
package/src/file-manager.ts
CHANGED
|
@@ -1,169 +1,367 @@
|
|
|
1
|
-
import { ChatData, MessageInfo } from './types'
|
|
2
|
-
import { Context, Logger } from 'koishi'
|
|
3
|
-
import { Config } from './config'
|
|
4
|
-
import { Utils } from './utils'
|
|
5
|
-
|
|
6
|
-
import path from 'node:path'
|
|
7
|
-
import fs from 'node:fs'
|
|
8
|
-
|
|
9
|
-
export class FileManager {
|
|
10
|
-
private
|
|
11
|
-
private
|
|
12
|
-
private logger: Logger
|
|
13
|
-
private utils: Utils
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
1
|
+
import { ChatData, MessageInfo } from './types'
|
|
2
|
+
import { Context, Logger } from 'koishi'
|
|
3
|
+
import { Config } from './config'
|
|
4
|
+
import { Utils } from './utils'
|
|
5
|
+
|
|
6
|
+
import path from 'node:path'
|
|
7
|
+
import fs from 'node:fs'
|
|
8
|
+
|
|
9
|
+
export class FileManager {
|
|
10
|
+
private chatHistoryDir: string // 聊天记录根目录
|
|
11
|
+
private metadataFilePath: string // 元数据文件路径(存储bots、channels、pinned等信息)
|
|
12
|
+
private logger: Logger
|
|
13
|
+
private utils: Utils
|
|
14
|
+
|
|
15
|
+
private memoryCache: ChatData | null = null
|
|
16
|
+
|
|
17
|
+
private pendingMessages: Map<string, MessageInfo[]> = new Map() // 按channelKey分组的待写入消息
|
|
18
|
+
|
|
19
|
+
private writeTimers: Map<string, (() => void)> = new Map() // 每个频道独立的写入定时器
|
|
20
|
+
|
|
21
|
+
private readonly WRITE_DEBOUNCE_MS = 1000
|
|
22
|
+
|
|
23
|
+
constructor(
|
|
24
|
+
private ctx: Context,
|
|
25
|
+
private config: Config
|
|
26
|
+
) {
|
|
27
|
+
const baseDir = path.resolve(ctx.baseDir, 'data', 'chat-patch')
|
|
28
|
+
this.chatHistoryDir = path.join(baseDir, 'chat-history')
|
|
29
|
+
this.metadataFilePath = path.join(baseDir, 'metadata.json')
|
|
30
|
+
this.logger = ctx.logger('chat-patch')
|
|
31
|
+
this.utils = new Utils(config)
|
|
32
|
+
|
|
33
|
+
// 清理旧版本的单文件存储
|
|
34
|
+
this.cleanupOldDataFiles(baseDir)
|
|
35
|
+
|
|
36
|
+
this.memoryCache = this.readChatDataFromFile()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 清理旧版本的JSON文件
|
|
40
|
+
private cleanupOldDataFiles(baseDir: string) {
|
|
41
|
+
const oldFiles = ['chat-data.json', 'data.json', 'messages.json']
|
|
42
|
+
for (const fileName of oldFiles) {
|
|
43
|
+
const filePath = path.join(baseDir, fileName)
|
|
44
|
+
if (fs.existsSync(filePath)) {
|
|
45
|
+
try {
|
|
46
|
+
fs.unlinkSync(filePath)
|
|
47
|
+
this.logger.info(`已删除旧版本数据文件: ${fileName}`)
|
|
48
|
+
} catch (error) {
|
|
49
|
+
this.logger.warn(`删除旧版本数据文件失败: ${fileName}`, error)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 确保目录存在
|
|
56
|
+
private ensureDir(dirPath: string) {
|
|
57
|
+
if (!fs.existsSync(dirPath)) {
|
|
58
|
+
fs.mkdirSync(dirPath, { recursive: true })
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 获取频道消息文件路径
|
|
63
|
+
private getChannelFilePath(selfId: string, channelId: string): string {
|
|
64
|
+
const botDir = path.join(this.chatHistoryDir, selfId)
|
|
65
|
+
this.ensureDir(botDir)
|
|
66
|
+
return path.join(botDir, `${channelId}.json`)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 读取单个频道的消息
|
|
70
|
+
private readChannelMessages(selfId: string, channelId: string): MessageInfo[] {
|
|
71
|
+
const filePath = this.getChannelFilePath(selfId, channelId)
|
|
72
|
+
if (!fs.existsSync(filePath)) {
|
|
73
|
+
return []
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const jsonData = fs.readFileSync(filePath, 'utf8')
|
|
78
|
+
const messages = JSON.parse(jsonData)
|
|
79
|
+
return Array.isArray(messages) ? messages : []
|
|
80
|
+
} catch (error) {
|
|
81
|
+
this.logger.error(`读取频道消息失败 [${selfId}:${channelId}]:`, error)
|
|
82
|
+
return []
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 写入单个频道的消息
|
|
87
|
+
private writeChannelMessages(selfId: string, channelId: string, messages: MessageInfo[]) {
|
|
88
|
+
const filePath = this.getChannelFilePath(selfId, channelId)
|
|
89
|
+
try {
|
|
90
|
+
const jsonData = JSON.stringify(messages, null, 2)
|
|
91
|
+
fs.writeFileSync(filePath, jsonData, 'utf8')
|
|
92
|
+
} catch (error) {
|
|
93
|
+
this.logger.error(`写入频道消息失败 [${selfId}:${channelId}]:`, error)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 读取元数据(bots、channels、pinned等)
|
|
98
|
+
private readMetadata(): Omit<ChatData, 'messages'> {
|
|
99
|
+
if (!fs.existsSync(this.metadataFilePath)) {
|
|
100
|
+
return {
|
|
101
|
+
bots: {},
|
|
102
|
+
channels: {},
|
|
103
|
+
pinnedBots: [],
|
|
104
|
+
pinnedChannels: []
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const jsonData = fs.readFileSync(this.metadataFilePath, 'utf8')
|
|
110
|
+
const data = JSON.parse(jsonData)
|
|
111
|
+
return {
|
|
112
|
+
bots: data.bots || {},
|
|
113
|
+
channels: data.channels || {},
|
|
114
|
+
pinnedBots: data.pinnedBots || [],
|
|
115
|
+
pinnedChannels: data.pinnedChannels || [],
|
|
116
|
+
lastSaveTime: data.lastSaveTime
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
this.logger.error('读取元数据失败:', error)
|
|
120
|
+
return {
|
|
121
|
+
bots: {},
|
|
122
|
+
channels: {},
|
|
123
|
+
pinnedBots: [],
|
|
124
|
+
pinnedChannels: []
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 写入元数据
|
|
130
|
+
private writeMetadata(metadata: Omit<ChatData, 'messages'>) {
|
|
131
|
+
try {
|
|
132
|
+
this.ensureDir(path.dirname(this.metadataFilePath))
|
|
133
|
+
const dataToWrite = {
|
|
134
|
+
...metadata,
|
|
135
|
+
lastSaveTime: Date.now()
|
|
136
|
+
}
|
|
137
|
+
const jsonData = JSON.stringify(dataToWrite, null, 2)
|
|
138
|
+
fs.writeFileSync(this.metadataFilePath, jsonData, 'utf8')
|
|
139
|
+
} catch (error) {
|
|
140
|
+
this.logger.error('写入元数据失败:', error)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 扫描所有频道消息文件并加载到内存
|
|
145
|
+
private loadAllChannelMessages(): Record<string, MessageInfo[]> {
|
|
146
|
+
const messages: Record<string, MessageInfo[]> = {}
|
|
147
|
+
|
|
148
|
+
if (!fs.existsSync(this.chatHistoryDir)) {
|
|
149
|
+
return messages
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
const botDirs = fs.readdirSync(this.chatHistoryDir)
|
|
154
|
+
for (const botId of botDirs) {
|
|
155
|
+
const botDir = path.join(this.chatHistoryDir, botId)
|
|
156
|
+
const stat = fs.statSync(botDir)
|
|
157
|
+
if (!stat.isDirectory()) continue
|
|
158
|
+
|
|
159
|
+
const channelFiles = fs.readdirSync(botDir)
|
|
160
|
+
for (const fileName of channelFiles) {
|
|
161
|
+
if (!fileName.endsWith('.json')) continue
|
|
162
|
+
|
|
163
|
+
const channelId = fileName.replace('.json', '')
|
|
164
|
+
const channelKey = `${botId}:${channelId}`
|
|
165
|
+
messages[channelKey] = this.readChannelMessages(botId, channelId)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} catch (error) {
|
|
169
|
+
this.logger.error('加载频道消息失败:', error)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return messages
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
readChatDataFromFile(): ChatData {
|
|
176
|
+
// 如果已有缓存,直接返回
|
|
177
|
+
if (this.memoryCache) {
|
|
178
|
+
return this.memoryCache
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 异步加载数据
|
|
182
|
+
process.nextTick(() => {
|
|
183
|
+
try {
|
|
184
|
+
const metadata = this.readMetadata()
|
|
185
|
+
const messages = this.loadAllChannelMessages()
|
|
186
|
+
this.memoryCache = {
|
|
187
|
+
...metadata,
|
|
188
|
+
messages
|
|
189
|
+
}
|
|
190
|
+
} catch (error) {
|
|
191
|
+
this.logger.error('读取聊天数据失败:', error)
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
// 先返回空数据
|
|
196
|
+
this.memoryCache = {
|
|
197
|
+
bots: {},
|
|
198
|
+
channels: {},
|
|
199
|
+
messages: {},
|
|
200
|
+
pinnedBots: [],
|
|
201
|
+
pinnedChannels: []
|
|
202
|
+
}
|
|
203
|
+
return this.memoryCache
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
writeChatDataToFile(data: ChatData) {
|
|
207
|
+
data.lastSaveTime = Date.now()
|
|
208
|
+
this.memoryCache = data
|
|
209
|
+
|
|
210
|
+
process.nextTick(() => {
|
|
211
|
+
try {
|
|
212
|
+
// 写入元数据
|
|
213
|
+
const { messages, ...metadata } = data
|
|
214
|
+
this.writeMetadata(metadata)
|
|
215
|
+
|
|
216
|
+
// 写入各个频道的消息
|
|
217
|
+
for (const [channelKey, channelMessages] of Object.entries(messages)) {
|
|
218
|
+
const [selfId, channelId] = channelKey.split(':')
|
|
219
|
+
if (selfId && channelId) {
|
|
220
|
+
this.writeChannelMessages(selfId, channelId, channelMessages)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
} catch (error) {
|
|
224
|
+
this.logger.error('写入聊天数据失败:', error)
|
|
225
|
+
}
|
|
226
|
+
})
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// 为特定频道安排写入
|
|
230
|
+
private scheduleWrite(channelKey: string) {
|
|
231
|
+
// 取消之前的定时器
|
|
232
|
+
const existingTimer = this.writeTimers.get(channelKey)
|
|
233
|
+
if (existingTimer) {
|
|
234
|
+
existingTimer()
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// 创建新的定时器
|
|
238
|
+
const timer = this.ctx.setTimeout(() => {
|
|
239
|
+
process.nextTick(() => {
|
|
240
|
+
this.flushPendingMessages(channelKey)
|
|
241
|
+
})
|
|
242
|
+
this.writeTimers.delete(channelKey)
|
|
243
|
+
}, this.WRITE_DEBOUNCE_MS)
|
|
244
|
+
|
|
245
|
+
this.writeTimers.set(channelKey, timer)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// 刷新特定频道的待写入消息
|
|
249
|
+
private flushPendingMessages(channelKey: string) {
|
|
250
|
+
const messagesToWrite = this.pendingMessages.get(channelKey)
|
|
251
|
+
if (!messagesToWrite || messagesToWrite.length === 0) return
|
|
252
|
+
|
|
253
|
+
this.pendingMessages.delete(channelKey)
|
|
254
|
+
|
|
255
|
+
const data = this.memoryCache || this.readChatDataFromFile()
|
|
256
|
+
const [selfId, channelId] = channelKey.split(':')
|
|
257
|
+
|
|
258
|
+
if (!selfId || !channelId) return
|
|
259
|
+
|
|
260
|
+
if (!data.messages[channelKey]) {
|
|
261
|
+
data.messages[channelKey] = []
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
for (const messageInfo of messagesToWrite) {
|
|
265
|
+
const existingMessage = data.messages[channelKey].find(m => m.id === messageInfo.id)
|
|
266
|
+
if (existingMessage) {
|
|
267
|
+
continue
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (!messageInfo.timestamp) {
|
|
271
|
+
messageInfo.timestamp = Date.now()
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const cleanedMessageInfo = this.utils.cleanBase64Content(messageInfo) as MessageInfo
|
|
275
|
+
data.messages[channelKey].push(cleanedMessageInfo)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// 限制消息数量
|
|
279
|
+
if (data.messages[channelKey].length > this.config.maxMessagesPerChannel) {
|
|
280
|
+
data.messages[channelKey].sort((a, b) => a.timestamp - b.timestamp)
|
|
281
|
+
data.messages[channelKey] = data.messages[channelKey].slice(-this.config.maxMessagesPerChannel)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// 只写入这个频道的消息文件
|
|
285
|
+
this.writeChannelMessages(selfId, channelId, data.messages[channelKey])
|
|
286
|
+
this.memoryCache = data
|
|
287
|
+
|
|
288
|
+
this.logInfo(`批量写入 ${messagesToWrite.length} 条消息到频道 ${channelKey}`)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
cleanExcessMessages(data: ChatData): ChatData {
|
|
292
|
+
let cleanedCount = 0
|
|
293
|
+
const cleanedMessages: Record<string, MessageInfo[]> = {}
|
|
294
|
+
|
|
295
|
+
for (const [channelKey, messages] of Object.entries(data.messages)) {
|
|
296
|
+
if (messages.length > this.config.maxMessagesPerChannel) {
|
|
297
|
+
const sortedMessages = [...messages].sort((a, b) => a.timestamp - b.timestamp)
|
|
298
|
+
const keptMessages = sortedMessages.slice(-this.config.maxMessagesPerChannel)
|
|
299
|
+
cleanedCount += messages.length - keptMessages.length
|
|
300
|
+
cleanedMessages[channelKey] = keptMessages
|
|
301
|
+
this.logInfo(`频道 ${channelKey} 清理了 ${messages.length - keptMessages.length} 条旧消息,保留最新 ${keptMessages.length} 条`)
|
|
302
|
+
} else {
|
|
303
|
+
cleanedMessages[channelKey] = messages
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (cleanedCount > 0) {
|
|
308
|
+
this.logInfo('总共清理超量消息:', cleanedCount, '条')
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
...data,
|
|
313
|
+
messages: cleanedMessages
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async addMessageToFile(messageInfo: MessageInfo) {
|
|
318
|
+
const channelKey = `${messageInfo.selfId}:${messageInfo.channelId}`
|
|
319
|
+
|
|
320
|
+
// 添加到待写入队列
|
|
321
|
+
if (!this.pendingMessages.has(channelKey)) {
|
|
322
|
+
this.pendingMessages.set(channelKey, [])
|
|
323
|
+
}
|
|
324
|
+
this.pendingMessages.get(channelKey)!.push(messageInfo)
|
|
325
|
+
|
|
326
|
+
// 更新内存缓存
|
|
327
|
+
const data = this.memoryCache || this.readChatDataFromFile()
|
|
328
|
+
|
|
329
|
+
if (!data.messages[channelKey]) {
|
|
330
|
+
data.messages[channelKey] = []
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const existingMessage = data.messages[channelKey].find(m => m.id === messageInfo.id)
|
|
334
|
+
if (!existingMessage) {
|
|
335
|
+
if (!messageInfo.timestamp) {
|
|
336
|
+
messageInfo.timestamp = Date.now()
|
|
337
|
+
}
|
|
338
|
+
const cleanedMessageInfo = this.utils.cleanBase64Content(messageInfo) as MessageInfo
|
|
339
|
+
data.messages[channelKey].push(cleanedMessageInfo)
|
|
340
|
+
|
|
341
|
+
if (data.messages[channelKey].length > this.config.maxMessagesPerChannel) {
|
|
342
|
+
data.messages[channelKey].sort((a, b) => a.timestamp - b.timestamp)
|
|
343
|
+
data.messages[channelKey] = data.messages[channelKey].slice(-this.config.maxMessagesPerChannel)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
this.memoryCache = data
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// 安排写入
|
|
350
|
+
this.scheduleWrite(channelKey)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
dispose() {
|
|
354
|
+
// 取消所有定时器
|
|
355
|
+
for (const [channelKey, timer] of this.writeTimers.entries()) {
|
|
356
|
+
timer()
|
|
357
|
+
this.flushPendingMessages(channelKey)
|
|
358
|
+
}
|
|
359
|
+
this.writeTimers.clear()
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
private logInfo(...args: any[]) {
|
|
363
|
+
if (this.config.loggerinfo) {
|
|
364
|
+
(this.logger.info as (...args: any[]) => void)(...args)
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|