mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-06-14 03:26:37 +08:00
feat: 支持平台消息id和回复id,同时进行表迁移
This commit is contained in:
@@ -106,11 +106,14 @@ function createDatabase(sessionId: string): Database.Database {
|
|||||||
ts INTEGER NOT NULL,
|
ts INTEGER NOT NULL,
|
||||||
type INTEGER NOT NULL,
|
type INTEGER NOT NULL,
|
||||||
content TEXT,
|
content TEXT,
|
||||||
|
reply_to_message_id TEXT DEFAULT NULL,
|
||||||
|
platform_message_id TEXT DEFAULT NULL,
|
||||||
FOREIGN KEY(sender_id) REFERENCES member(id)
|
FOREIGN KEY(sender_id) REFERENCES member(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_message_ts ON message(ts);
|
CREATE INDEX IF NOT EXISTS idx_message_ts ON message(ts);
|
||||||
CREATE INDEX IF NOT EXISTS idx_message_sender ON message(sender_id);
|
CREATE INDEX IF NOT EXISTS idx_message_sender ON message(sender_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_message_platform_id ON message(platform_message_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_member_name_history_member_id ON member_name_history(member_id);
|
CREATE INDEX IF NOT EXISTS idx_member_name_history_member_id ON member_name_history(member_id);
|
||||||
`)
|
`)
|
||||||
|
|
||||||
@@ -201,8 +204,8 @@ export function importData(parseResult: ParseResult): string {
|
|||||||
const groupNicknameTracker = new Map<string, { currentName: string; lastSeenTs: number }>()
|
const groupNicknameTracker = new Map<string, { currentName: string; lastSeenTs: number }>()
|
||||||
|
|
||||||
const insertMessage = db.prepare(`
|
const insertMessage = db.prepare(`
|
||||||
INSERT INTO message (sender_id, sender_account_name, sender_group_nickname, ts, type, content)
|
INSERT INTO message (sender_id, sender_account_name, sender_group_nickname, ts, type, content, reply_to_message_id, platform_message_id)
|
||||||
VALUES (?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
`)
|
`)
|
||||||
const insertNameHistory = db.prepare(`
|
const insertNameHistory = db.prepare(`
|
||||||
INSERT INTO member_name_history (member_id, name_type, name, start_ts, end_ts)
|
INSERT INTO member_name_history (member_id, name_type, name, start_ts, end_ts)
|
||||||
@@ -230,7 +233,9 @@ export function importData(parseResult: ParseResult): string {
|
|||||||
msg.senderGroupNickname || null,
|
msg.senderGroupNickname || null,
|
||||||
msg.timestamp,
|
msg.timestamp,
|
||||||
msg.type,
|
msg.type,
|
||||||
msg.content
|
msg.content,
|
||||||
|
msg.replyToMessageId || null,
|
||||||
|
msg.platformMessageId || null
|
||||||
)
|
)
|
||||||
|
|
||||||
// 追踪 account_name 变化
|
// 追踪 account_name 变化
|
||||||
|
|||||||
@@ -56,15 +56,37 @@ const migrations: Migration[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
version: 2,
|
version: 2,
|
||||||
description: '添加 roles 字段到 member 表',
|
description: '添加 roles、reply_to_message_id、platform_message_id 字段',
|
||||||
userMessage: '支持成员角色(群主、管理员等)',
|
userMessage: '支持成员角色、消息回复关系和回复内容预览',
|
||||||
up: (db) => {
|
up: (db) => {
|
||||||
// 检查 roles 列是否已存在(防止重复执行)
|
// 检查 roles 列是否已存在(防止重复执行)
|
||||||
const tableInfo = db.prepare('PRAGMA table_info(member)').all() as Array<{ name: string }>
|
const memberTableInfo = db.prepare('PRAGMA table_info(member)').all() as Array<{ name: string }>
|
||||||
const hasRolesColumn = tableInfo.some((col) => col.name === 'roles')
|
const hasRolesColumn = memberTableInfo.some((col) => col.name === 'roles')
|
||||||
if (!hasRolesColumn) {
|
if (!hasRolesColumn) {
|
||||||
db.exec("ALTER TABLE member ADD COLUMN roles TEXT DEFAULT '[]'")
|
db.exec("ALTER TABLE member ADD COLUMN roles TEXT DEFAULT '[]'")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查 message 表的列
|
||||||
|
const messageTableInfo = db.prepare('PRAGMA table_info(message)').all() as Array<{ name: string }>
|
||||||
|
|
||||||
|
// 检查 reply_to_message_id 列是否已存在
|
||||||
|
const hasReplyColumn = messageTableInfo.some((col) => col.name === 'reply_to_message_id')
|
||||||
|
if (!hasReplyColumn) {
|
||||||
|
db.exec('ALTER TABLE message ADD COLUMN reply_to_message_id TEXT DEFAULT NULL')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加 platform_message_id 列(存储平台原始消息 ID,用于回复关联查询)
|
||||||
|
const hasPlatformMsgIdColumn = messageTableInfo.some((col) => col.name === 'platform_message_id')
|
||||||
|
if (!hasPlatformMsgIdColumn) {
|
||||||
|
db.exec('ALTER TABLE message ADD COLUMN platform_message_id TEXT DEFAULT NULL')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建索引以加速回复查询
|
||||||
|
try {
|
||||||
|
db.exec('CREATE INDEX IF NOT EXISTS idx_message_platform_id ON message(platform_message_id)')
|
||||||
|
} catch {
|
||||||
|
// 索引可能已存在
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ interface JsonlMessage {
|
|||||||
timestamp: number
|
timestamp: number
|
||||||
type: number
|
type: number
|
||||||
content: string | null
|
content: string | null
|
||||||
|
replyToMessageId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 任意 JSONL 行 */
|
/** 任意 JSONL 行 */
|
||||||
@@ -215,6 +216,7 @@ async function* parseChatLabJsonl(options: ParseOptions): AsyncGenerator<ParseEv
|
|||||||
timestamp: parsed.timestamp,
|
timestamp: parsed.timestamp,
|
||||||
type: parsed.type as MessageType,
|
type: parsed.type as MessageType,
|
||||||
content: parsed.content,
|
content: parsed.content,
|
||||||
|
replyToMessageId: parsed.replyToMessageId,
|
||||||
})
|
})
|
||||||
messagesProcessed++
|
messagesProcessed++
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ interface ChatLabMessage {
|
|||||||
timestamp: number // 秒级时间戳
|
timestamp: number // 秒级时间戳
|
||||||
type: number // MessageType
|
type: number // MessageType
|
||||||
content: string | null
|
content: string | null
|
||||||
|
replyToMessageId?: string // 回复的目标消息 ID(平台原始 ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ChatLabMember {
|
interface ChatLabMember {
|
||||||
@@ -204,6 +205,7 @@ async function* parseChatLab(options: ParseOptions): AsyncGenerator<ParseEvent,
|
|||||||
timestamp: msg.timestamp,
|
timestamp: msg.timestamp,
|
||||||
type: msg.type,
|
type: msg.type,
|
||||||
content: msg.content,
|
content: msg.content,
|
||||||
|
replyToMessageId: msg.replyToMessageId,
|
||||||
})
|
})
|
||||||
|
|
||||||
messagesProcessed++
|
messagesProcessed++
|
||||||
|
|||||||
@@ -387,6 +387,7 @@ async function* parseDiscordExporter(options: ParseOptions): AsyncGenerator<Pars
|
|||||||
timestamp: parseTimestamp(msg.timestamp),
|
timestamp: parseTimestamp(msg.timestamp),
|
||||||
type: messageType,
|
type: messageType,
|
||||||
content: content || null,
|
content: content || null,
|
||||||
|
replyToMessageId: msg.reference?.messageId || undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
messagesProcessed++
|
messagesProcessed++
|
||||||
|
|||||||
@@ -181,6 +181,8 @@ function createDatabaseWithoutIndexes(sessionId: string): Database.Database {
|
|||||||
ts INTEGER NOT NULL,
|
ts INTEGER NOT NULL,
|
||||||
type INTEGER NOT NULL,
|
type INTEGER NOT NULL,
|
||||||
content TEXT,
|
content TEXT,
|
||||||
|
reply_to_message_id TEXT DEFAULT NULL,
|
||||||
|
platform_message_id TEXT DEFAULT NULL,
|
||||||
FOREIGN KEY(sender_id) REFERENCES member(id)
|
FOREIGN KEY(sender_id) REFERENCES member(id)
|
||||||
);
|
);
|
||||||
`)
|
`)
|
||||||
@@ -195,6 +197,7 @@ function createIndexes(db: Database.Database): void {
|
|||||||
db.exec(`
|
db.exec(`
|
||||||
CREATE INDEX IF NOT EXISTS idx_message_ts ON message(ts);
|
CREATE INDEX IF NOT EXISTS idx_message_ts ON message(ts);
|
||||||
CREATE INDEX IF NOT EXISTS idx_message_sender ON message(sender_id);
|
CREATE INDEX IF NOT EXISTS idx_message_sender ON message(sender_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_message_platform_id ON message(platform_message_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_member_name_history_member_id ON member_name_history(member_id);
|
CREATE INDEX IF NOT EXISTS idx_member_name_history_member_id ON member_name_history(member_id);
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
@@ -268,8 +271,8 @@ export async function streamImport(filePath: string, requestId: string): Promise
|
|||||||
`)
|
`)
|
||||||
const getMemberId = db.prepare(`SELECT id FROM member WHERE platform_id = ?`)
|
const getMemberId = db.prepare(`SELECT id FROM member WHERE platform_id = ?`)
|
||||||
const insertMessage = db.prepare(`
|
const insertMessage = db.prepare(`
|
||||||
INSERT INTO message (sender_id, sender_account_name, sender_group_nickname, ts, type, content)
|
INSERT INTO message (sender_id, sender_account_name, sender_group_nickname, ts, type, content, reply_to_message_id, platform_message_id)
|
||||||
VALUES (?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
`)
|
`)
|
||||||
const insertNameHistory = db.prepare(`
|
const insertNameHistory = db.prepare(`
|
||||||
INSERT INTO member_name_history (member_id, name_type, name, start_ts, end_ts) VALUES (?, ?, ?, ?, ?)
|
INSERT INTO member_name_history (member_id, name_type, name, start_ts, end_ts) VALUES (?, ?, ?, ?, ?)
|
||||||
@@ -467,7 +470,9 @@ export async function streamImport(filePath: string, requestId: string): Promise
|
|||||||
msg.senderGroupNickname || null,
|
msg.senderGroupNickname || null,
|
||||||
msg.timestamp,
|
msg.timestamp,
|
||||||
msg.type,
|
msg.type,
|
||||||
safeContent
|
safeContent,
|
||||||
|
msg.replyToMessageId || null,
|
||||||
|
msg.platformMessageId || null
|
||||||
)
|
)
|
||||||
messageInsertTime += Date.now() - t0
|
messageInsertTime += Date.now() - t0
|
||||||
messageCountInBatch++
|
messageCountInBatch++
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ export interface MessageResult {
|
|||||||
content: string
|
content: string
|
||||||
timestamp: number
|
timestamp: number
|
||||||
type: number
|
type: number
|
||||||
|
replyToMessageId: string | null
|
||||||
|
replyToContent: string | null
|
||||||
|
replyToSenderName: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,6 +56,9 @@ interface DbMessageRow {
|
|||||||
content: string
|
content: string
|
||||||
timestamp: number
|
timestamp: number
|
||||||
type: number
|
type: number
|
||||||
|
reply_to_message_id: string | null
|
||||||
|
replyToContent: string | null
|
||||||
|
replyToSenderName: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,6 +85,9 @@ function sanitizeMessageRow(row: DbMessageRow): MessageResult {
|
|||||||
content: row.content != null ? String(row.content) : '',
|
content: row.content != null ? String(row.content) : '',
|
||||||
timestamp: Number(row.timestamp),
|
timestamp: Number(row.timestamp),
|
||||||
type: Number(row.type),
|
type: Number(row.type),
|
||||||
|
replyToMessageId: row.reply_to_message_id || null,
|
||||||
|
replyToContent: row.replyToContent || null,
|
||||||
|
replyToSenderName: row.replyToSenderName || null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,9 +165,14 @@ export function getRecentMessages(
|
|||||||
m.avatar,
|
m.avatar,
|
||||||
msg.content,
|
msg.content,
|
||||||
msg.ts as timestamp,
|
msg.ts as timestamp,
|
||||||
msg.type
|
msg.type,
|
||||||
|
msg.reply_to_message_id,
|
||||||
|
reply_msg.content as replyToContent,
|
||||||
|
COALESCE(reply_m.group_nickname, reply_m.account_name, reply_m.platform_id) as replyToSenderName
|
||||||
FROM message msg
|
FROM message msg
|
||||||
JOIN member m ON msg.sender_id = m.id
|
JOIN member m ON msg.sender_id = m.id
|
||||||
|
LEFT JOIN message reply_msg ON msg.reply_to_message_id = reply_msg.platform_message_id
|
||||||
|
LEFT JOIN member reply_m ON reply_msg.sender_id = reply_m.id
|
||||||
WHERE 1=1
|
WHERE 1=1
|
||||||
${timeCondition}
|
${timeCondition}
|
||||||
${SYSTEM_FILTER}
|
${SYSTEM_FILTER}
|
||||||
@@ -218,9 +232,14 @@ export function getAllRecentMessages(
|
|||||||
m.avatar,
|
m.avatar,
|
||||||
msg.content,
|
msg.content,
|
||||||
msg.ts as timestamp,
|
msg.ts as timestamp,
|
||||||
msg.type
|
msg.type,
|
||||||
|
msg.reply_to_message_id,
|
||||||
|
reply_msg.content as replyToContent,
|
||||||
|
COALESCE(reply_m.group_nickname, reply_m.account_name, reply_m.platform_id) as replyToSenderName
|
||||||
FROM message msg
|
FROM message msg
|
||||||
JOIN member m ON msg.sender_id = m.id
|
JOIN member m ON msg.sender_id = m.id
|
||||||
|
LEFT JOIN message reply_msg ON msg.reply_to_message_id = reply_msg.platform_message_id
|
||||||
|
LEFT JOIN member reply_m ON reply_msg.sender_id = reply_m.id
|
||||||
WHERE 1=1
|
WHERE 1=1
|
||||||
${timeCondition}
|
${timeCondition}
|
||||||
ORDER BY msg.ts DESC
|
ORDER BY msg.ts DESC
|
||||||
@@ -296,9 +315,14 @@ export function searchMessages(
|
|||||||
m.avatar,
|
m.avatar,
|
||||||
msg.content,
|
msg.content,
|
||||||
msg.ts as timestamp,
|
msg.ts as timestamp,
|
||||||
msg.type
|
msg.type,
|
||||||
|
msg.reply_to_message_id,
|
||||||
|
reply_msg.content as replyToContent,
|
||||||
|
COALESCE(reply_m.group_nickname, reply_m.account_name, reply_m.platform_id) as replyToSenderName
|
||||||
FROM message msg
|
FROM message msg
|
||||||
JOIN member m ON msg.sender_id = m.id
|
JOIN member m ON msg.sender_id = m.id
|
||||||
|
LEFT JOIN message reply_msg ON msg.reply_to_message_id = reply_msg.platform_message_id
|
||||||
|
LEFT JOIN member reply_m ON reply_msg.sender_id = reply_m.id
|
||||||
WHERE ${keywordCondition}
|
WHERE ${keywordCondition}
|
||||||
${timeCondition}
|
${timeCondition}
|
||||||
${senderCondition}
|
${senderCondition}
|
||||||
@@ -381,9 +405,14 @@ export function getMessageContext(
|
|||||||
m.avatar,
|
m.avatar,
|
||||||
msg.content,
|
msg.content,
|
||||||
msg.ts as timestamp,
|
msg.ts as timestamp,
|
||||||
msg.type
|
msg.type,
|
||||||
|
msg.reply_to_message_id,
|
||||||
|
reply_msg.content as replyToContent,
|
||||||
|
COALESCE(reply_m.group_nickname, reply_m.account_name, reply_m.platform_id) as replyToSenderName
|
||||||
FROM message msg
|
FROM message msg
|
||||||
JOIN member m ON msg.sender_id = m.id
|
JOIN member m ON msg.sender_id = m.id
|
||||||
|
LEFT JOIN message reply_msg ON msg.reply_to_message_id = reply_msg.platform_message_id
|
||||||
|
LEFT JOIN member reply_m ON reply_msg.sender_id = reply_m.id
|
||||||
WHERE msg.id IN (${placeholders})
|
WHERE msg.id IN (${placeholders})
|
||||||
ORDER BY msg.id ASC
|
ORDER BY msg.id ASC
|
||||||
`
|
`
|
||||||
@@ -435,9 +464,14 @@ export function getMessagesBefore(
|
|||||||
m.avatar,
|
m.avatar,
|
||||||
msg.content,
|
msg.content,
|
||||||
msg.ts as timestamp,
|
msg.ts as timestamp,
|
||||||
msg.type
|
msg.type,
|
||||||
|
msg.reply_to_message_id,
|
||||||
|
reply_msg.content as replyToContent,
|
||||||
|
COALESCE(reply_m.group_nickname, reply_m.account_name, reply_m.platform_id) as replyToSenderName
|
||||||
FROM message msg
|
FROM message msg
|
||||||
JOIN member m ON msg.sender_id = m.id
|
JOIN member m ON msg.sender_id = m.id
|
||||||
|
LEFT JOIN message reply_msg ON msg.reply_to_message_id = reply_msg.platform_message_id
|
||||||
|
LEFT JOIN member reply_m ON reply_msg.sender_id = reply_m.id
|
||||||
WHERE msg.id < ?
|
WHERE msg.id < ?
|
||||||
${timeCondition}
|
${timeCondition}
|
||||||
${keywordCondition}
|
${keywordCondition}
|
||||||
@@ -500,9 +534,14 @@ export function getMessagesAfter(
|
|||||||
m.avatar,
|
m.avatar,
|
||||||
msg.content,
|
msg.content,
|
||||||
msg.ts as timestamp,
|
msg.ts as timestamp,
|
||||||
msg.type
|
msg.type,
|
||||||
|
msg.reply_to_message_id,
|
||||||
|
reply_msg.content as replyToContent,
|
||||||
|
COALESCE(reply_m.group_nickname, reply_m.account_name, reply_m.platform_id) as replyToSenderName
|
||||||
FROM message msg
|
FROM message msg
|
||||||
JOIN member m ON msg.sender_id = m.id
|
JOIN member m ON msg.sender_id = m.id
|
||||||
|
LEFT JOIN message reply_msg ON msg.reply_to_message_id = reply_msg.platform_message_id
|
||||||
|
LEFT JOIN member reply_m ON reply_msg.sender_id = reply_m.id
|
||||||
WHERE msg.id > ?
|
WHERE msg.id > ?
|
||||||
${timeCondition}
|
${timeCondition}
|
||||||
${keywordCondition}
|
${keywordCondition}
|
||||||
@@ -585,9 +624,14 @@ export function getConversationBetween(
|
|||||||
m.avatar,
|
m.avatar,
|
||||||
msg.content,
|
msg.content,
|
||||||
msg.ts as timestamp,
|
msg.ts as timestamp,
|
||||||
msg.type
|
msg.type,
|
||||||
|
msg.reply_to_message_id,
|
||||||
|
reply_msg.content as replyToContent,
|
||||||
|
COALESCE(reply_m.group_nickname, reply_m.account_name, reply_m.platform_id) as replyToSenderName
|
||||||
FROM message msg
|
FROM message msg
|
||||||
JOIN member m ON msg.sender_id = m.id
|
JOIN member m ON msg.sender_id = m.id
|
||||||
|
LEFT JOIN message reply_msg ON msg.reply_to_message_id = reply_msg.platform_message_id
|
||||||
|
LEFT JOIN member reply_m ON reply_msg.sender_id = reply_m.id
|
||||||
WHERE msg.sender_id IN (?, ?)
|
WHERE msg.sender_id IN (?, ?)
|
||||||
${timeCondition}
|
${timeCondition}
|
||||||
AND msg.content IS NOT NULL AND msg.content != ''
|
AND msg.content IS NOT NULL AND msg.content != ''
|
||||||
|
|||||||
@@ -250,6 +250,19 @@ function highlightContent(content: string): string {
|
|||||||
class="relative inline-block rounded-lg px-3 py-2 transition-shadow"
|
class="relative inline-block rounded-lg px-3 py-2 transition-shadow"
|
||||||
:class="[bubbleColor, isTarget ? 'ring-2 ring-yellow-400 dark:ring-yellow-500' : '']"
|
:class="[bubbleColor, isTarget ? 'ring-2 ring-yellow-400 dark:ring-yellow-500' : '']"
|
||||||
>
|
>
|
||||||
|
<!-- 回复引用样式 -->
|
||||||
|
<div
|
||||||
|
v-if="message.replyToMessageId"
|
||||||
|
class="mb-2 border-l-2 border-gray-300 dark:border-gray-600 pl-2 text-xs text-gray-500 dark:text-gray-400"
|
||||||
|
>
|
||||||
|
<span class="font-medium">{{ t('replyTo') }}</span>
|
||||||
|
<span v-if="message.replyToSenderName" class="ml-1 text-gray-600 dark:text-gray-300">
|
||||||
|
{{ message.replyToSenderName }}
|
||||||
|
</span>
|
||||||
|
<p v-if="message.replyToContent" class="mt-0.5 line-clamp-2 italic">
|
||||||
|
{{ message.replyToContent }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<p
|
<p
|
||||||
class="whitespace-pre-wrap break-words text-sm text-gray-700 dark:text-gray-200"
|
class="whitespace-pre-wrap break-words text-sm text-gray-700 dark:text-gray-200"
|
||||||
v-html="highlightContent(message.content || '')"
|
v-html="highlightContent(message.content || '')"
|
||||||
@@ -320,12 +333,14 @@ function highlightContent(content: string): string {
|
|||||||
"zh-CN": {
|
"zh-CN": {
|
||||||
"viewContext": "查看上下文",
|
"viewContext": "查看上下文",
|
||||||
"contextTitle": "消息上下文(前后各10条)",
|
"contextTitle": "消息上下文(前后各10条)",
|
||||||
"noContext": "暂无上下文"
|
"noContext": "暂无上下文",
|
||||||
|
"replyTo": "回复"
|
||||||
},
|
},
|
||||||
"en-US": {
|
"en-US": {
|
||||||
"viewContext": "View Context",
|
"viewContext": "View Context",
|
||||||
"contextTitle": "Message Context (10 before and after)",
|
"contextTitle": "Message Context (10 before and after)",
|
||||||
"noContext": "No context available"
|
"noContext": "No context available",
|
||||||
|
"replyTo": "Reply to"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ export interface DbMessage {
|
|||||||
ts: number // 时间戳(秒)
|
ts: number // 时间戳(秒)
|
||||||
type: MessageType // 消息类型
|
type: MessageType // 消息类型
|
||||||
content: string | null // 纯文本内容
|
content: string | null // 纯文本内容
|
||||||
|
reply_to_message_id: string | null // 回复的目标消息 ID(平台原始 ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== Parser 解析结果 ====================
|
// ==================== Parser 解析结果 ====================
|
||||||
@@ -187,12 +188,14 @@ export interface ParsedMember {
|
|||||||
* 解析后的消息
|
* 解析后的消息
|
||||||
*/
|
*/
|
||||||
export interface ParsedMessage {
|
export interface ParsedMessage {
|
||||||
|
platformMessageId?: string // 消息的平台原始 ID(用于回复关联查询)
|
||||||
senderPlatformId: string // 发送者平台ID
|
senderPlatformId: string // 发送者平台ID
|
||||||
senderAccountName: string // 发送时的账号名称
|
senderAccountName: string // 发送时的账号名称
|
||||||
senderGroupNickname?: string // 发送时的群昵称(可为空)
|
senderGroupNickname?: string // 发送时的群昵称(可为空)
|
||||||
timestamp: number // 时间戳(秒)
|
timestamp: number // 时间戳(秒)
|
||||||
type: MessageType // 消息类型
|
type: MessageType // 消息类型
|
||||||
content: string | null // 内容
|
content: string | null // 内容
|
||||||
|
replyToMessageId?: string // 回复的目标消息 ID(平台原始 ID,可为空)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -182,4 +182,7 @@ export interface ChatRecordMessage {
|
|||||||
content: string
|
content: string
|
||||||
timestamp: number
|
timestamp: number
|
||||||
type: number
|
type: number
|
||||||
|
replyToMessageId: string | null // 回复的目标消息 ID(平台原始 ID)
|
||||||
|
replyToContent: string | null // 被回复消息的内容预览
|
||||||
|
replyToSenderName: string | null // 被回复消息的发送者名称
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user