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/src/types.ts CHANGED
@@ -1,62 +1,62 @@
1
- import { h } from 'koishi'
2
-
3
- export interface BotInfo {
4
- selfId: string
5
- platform: string
6
- username: string
7
- avatar?: string
8
- status: 'online' | 'offline'
9
- }
10
-
11
- export interface ChannelInfo {
12
- id: string
13
- name: string
14
- type: number | string
15
- channelId?: string
16
- guildName?: string
17
- isDirect?: boolean
18
- }
19
-
20
- export interface QuoteInfo {
21
- messageId: string
22
- id: string
23
- content: string
24
- elements?: h[]
25
- user: {
26
- id: string
27
- name: string
28
- userId: string
29
- avatar?: string
30
- username: string
31
- }
32
- timestamp: number
33
- }
34
-
35
- export interface MessageInfo {
36
- id: string
37
- content: string
38
- userId: string
39
- username: string
40
- avatar?: string
41
- timestamp: number
42
- channelId: string
43
- selfId: string
44
- elements?: h[]
45
- type: 'user' | 'bot'
46
- guildId?: string
47
- guildName?: string
48
- platform: string
49
- quote?: QuoteInfo
50
- isDirect?: boolean
51
- sending?: boolean
52
- realId?: string
53
- }
54
-
55
- export interface ChatData {
56
- bots: Record<string, BotInfo>
57
- channels: Record<string, Record<string, ChannelInfo>>
58
- messages: Record<string, MessageInfo[]>
59
- pinnedBots: string[]
60
- pinnedChannels: string[]
61
- lastSaveTime?: number
62
- }
1
+ import { h } from 'koishi'
2
+
3
+ export interface BotInfo {
4
+ selfId: string
5
+ platform: string
6
+ username: string
7
+ avatar?: string
8
+ status: 'online' | 'offline'
9
+ }
10
+
11
+ export interface ChannelInfo {
12
+ id: string
13
+ name: string
14
+ type: number | string
15
+ channelId?: string
16
+ guildName?: string
17
+ isDirect?: boolean
18
+ }
19
+
20
+ export interface QuoteInfo {
21
+ messageId: string
22
+ id: string
23
+ content: string
24
+ elements?: h[]
25
+ user: {
26
+ id: string
27
+ name: string
28
+ userId: string
29
+ avatar?: string
30
+ username: string
31
+ }
32
+ timestamp: number
33
+ }
34
+
35
+ export interface MessageInfo {
36
+ id: string
37
+ content: string
38
+ userId: string
39
+ username: string
40
+ avatar?: string
41
+ timestamp: number
42
+ channelId: string
43
+ selfId: string
44
+ elements?: h[]
45
+ type: 'user' | 'bot'
46
+ guildId?: string
47
+ guildName?: string
48
+ platform: string
49
+ quote?: QuoteInfo
50
+ isDirect?: boolean
51
+ sending?: boolean
52
+ realId?: string
53
+ }
54
+
55
+ export interface ChatData {
56
+ bots: Record<string, BotInfo>
57
+ channels: Record<string, Record<string, ChannelInfo>>
58
+ messages: Record<string, MessageInfo[]>
59
+ pinnedBots: string[]
60
+ pinnedChannels: string[]
61
+ lastSaveTime?: number
62
+ }
package/src/utils.ts CHANGED
@@ -8,7 +8,6 @@ import { pathToFileURL } from 'node:url'
8
8
  export class Utils {
9
9
  constructor(private config: Config, private ctx?: Context) { }
10
10
 
11
- // 检查平台是否被屏蔽
12
11
  isPlatformBlocked(platform: string): boolean {
13
12
  if (!this.config.blockedPlatforms || this.config.blockedPlatforms.length === 0) {
14
13
  return false
@@ -29,7 +28,6 @@ export class Utils {
29
28
  return false
30
29
  }
31
30
 
32
- // 递归提取所有文本内容的函数
33
31
  extractTextContent(elements: any[]): string {
34
32
  let text = ''
35
33
  for (const element of elements) {
@@ -46,16 +44,13 @@ export class Utils {
46
44
  return text
47
45
  }
48
46
 
49
- // 检查字符串是否为base64格式
50
47
  private isBase64(str: string): boolean {
51
48
  if (!str || typeof str !== 'string') return false
52
49
 
53
- // 检查是否以data:开头的base64格式
54
50
  if (str.startsWith('data:')) {
55
51
  return str.includes('base64,')
56
52
  }
57
53
 
58
- // 检查纯base64字符串(长度大于100且符合base64格式)
59
54
  if (str.length > 100) {
60
55
  const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/
61
56
  return base64Regex.test(str)
@@ -64,7 +59,6 @@ export class Utils {
64
59
  return false
65
60
  }
66
61
 
67
- // 持久化 base64 图片并返回本地文件 URL
68
62
  persistBase64Image(base64Data: string): string {
69
63
  if (!this.ctx || !base64Data.startsWith('data:image/')) return base64Data
70
64
 
@@ -72,17 +66,14 @@ export class Utils {
72
66
  const dir = join(this.ctx.baseDir, 'data', 'chat-patch', 'persist-images')
73
67
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
74
68
 
75
- // 生成文件名:时间戳 + 内容哈希
76
69
  const hash = createHash('md5').update(base64Data).digest('hex')
77
70
  const ext = base64Data.split(';')[0].split('/')[1] || 'png'
78
71
  const filename = `${Date.now()}_${hash}.${ext}`
79
72
  const filePath = join(dir, filename)
80
73
 
81
- // 写入文件
82
74
  const base64Content = base64Data.split(',')[1]
83
75
  writeFileSync(filePath, Buffer.from(base64Content, 'base64'))
84
76
 
85
- // 清理旧图片
86
77
  this.cleanupPersistImages(dir)
87
78
 
88
79
  return pathToFileURL(filePath).href
@@ -103,8 +94,6 @@ export class Utils {
103
94
  } catch (e) { }
104
95
  }
105
96
 
106
- // 清理对象中的base64内容,改为持久化存储
107
- // isBotMessage: 是否为机器人发送的消息
108
97
  cleanBase64Content(obj: any, isBotMessage: boolean = false): any {
109
98
  if (obj === null || obj === undefined) {
110
99
  return obj
@@ -112,7 +101,7 @@ export class Utils {
112
101
 
113
102
  if (typeof obj === 'string') {
114
103
  if (this.isBase64(obj)) {
115
- // 如果是机器人消息且是非图片的Base64,直接返回占位符
104
+
116
105
  if (isBotMessage && !obj.startsWith('data:image/')) {
117
106
  return '[富媒体内容已省略]'
118
107
  }
@@ -128,16 +117,15 @@ export class Utils {
128
117
  if (typeof obj === 'object') {
129
118
  const cleaned: any = {}
130
119
  for (const [key, value] of Object.entries(obj)) {
131
- // 检查元素类型,如果是机器人消息的非图片元素,跳过Base64处理
120
+
132
121
  if (isBotMessage && obj.type && !['text', 'image', 'img'].includes(obj.type)) {
133
- // 对于video、audio等元素,如果src是Base64,替换为占位符
122
+
134
123
  if (typeof value === 'string' && (key === 'src' || key === 'url' || key === 'file') && this.isBase64(value)) {
135
124
  cleaned[key] = '[富媒体内容已省略]'
136
125
  continue
137
126
  }
138
127
  }
139
128
 
140
- // 特别处理常见的base64字段
141
129
  if (typeof value === 'string' && (
142
130
  key === 'src' ||
143
131
  key === 'url' ||
@@ -145,7 +133,7 @@ export class Utils {
145
133
  key === 'data' ||
146
134
  key === 'content'
147
135
  ) && this.isBase64(value)) {
148
- // 如果是机器人消息且不是图片Base64,跳过
136
+
149
137
  if (isBotMessage && !value.startsWith('data:image/')) {
150
138
  cleaned[key] = '[富媒体内容已省略]'
151
139
  } else {