refactor: 重构数据库逻辑

This commit is contained in:
digua
2025-12-02 22:37:40 +08:00
parent 77b6035b13
commit 16e3b552c4
17 changed files with 1977 additions and 1843 deletions

View File

@@ -25,6 +25,20 @@ import type {
ParsedMessage,
} from '../types'
import { getFileSize, createProgress, readFileHeadBytes } from '../utils'
import * as path from 'path'
// ==================== 辅助函数 ====================
/**
* 从文件名提取群名
* 返回不含扩展名的文件名
*/
function extractNameFromFilePath(filePath: string): string {
const basename = path.basename(filePath)
// 移除 .json 扩展名
const name = basename.replace(/\.json$/i, '')
return name || '未知群聊'
}
// ==================== 特征定义 ====================
@@ -80,18 +94,47 @@ async function* parseChatLab(options: ParseOptions): AsyncGenerator<ParseEvent,
type: ChatType.GROUP,
}
try {
const metaMatch = headContent.match(/"meta"\s*:\s*(\{[^}]+\})/)
if (metaMatch) {
const metaObj = JSON.parse(metaMatch[1])
meta = {
name: metaObj.name || '未知群聊',
platform: (metaObj.platform as ChatPlatform) || ChatPlatform.UNKNOWN,
type: (metaObj.type as ChatType) || ChatType.GROUP,
// 使用更健壮的方式解析嵌套 JSON 对象
// 因为 meta 可能包含 sources 数组(嵌套对象),简单的正则无法正确匹配
const metaStartMatch = headContent.match(/"meta"\s*:\s*\{/)
if (metaStartMatch && metaStartMatch.index !== undefined) {
const startIndex = metaStartMatch.index + metaStartMatch[0].length - 1 // 指向 {
let depth = 0
let endIndex = startIndex
// 遍历字符找到匹配的闭合 }
for (let i = startIndex; i < headContent.length; i++) {
const char = headContent[i]
if (char === '{') {
depth++
} else if (char === '}') {
depth--
if (depth === 0) {
endIndex = i
break
}
}
}
if (endIndex > startIndex) {
const metaJson = headContent.slice(startIndex, endIndex + 1)
const metaObj = JSON.parse(metaJson)
meta = {
name: metaObj.name || '未知群聊',
platform: (metaObj.platform as ChatPlatform) || ChatPlatform.UNKNOWN,
type: (metaObj.type as ChatType) || ChatType.GROUP,
}
}
}
} catch {
// 使用默认值
}
// 如果群名仍是默认值,使用文件名作为后备
if (meta.name === '未知群聊') {
meta.name = extractNameFromFilePath(filePath)
}
yield { type: 'meta', data: meta }
// 解析 members如果在文件开头能找到

View File

@@ -15,6 +15,7 @@
*/
import * as fs from 'fs'
import * as path from 'path'
import * as readline from 'readline'
import { ChatPlatform, ChatType, MessageType } from '../../../../src/types/chat'
import type {
@@ -29,6 +30,17 @@ import type {
} from '../types'
import { getFileSize, createProgress } from '../utils'
// ==================== 辅助函数 ====================
/**
* 从文件名提取群名
*/
function extractNameFromFilePath(filePath: string): string {
const basename = path.basename(filePath)
const name = basename.replace(/\.txt$/i, '')
return name || '未知群聊'
}
// ==================== 特征定义 ====================
export const feature: FormatFeature = {
@@ -226,9 +238,9 @@ async function* parseTxt(options: ParseOptions): AsyncGenerator<ParseEvent, void
// 保存最后一条消息
saveCurrentMessage()
// 发送 meta
// 发送 meta(如果群名仍是默认值,使用文件名作为后备)
const meta: ParsedMeta = {
name: groupName,
name: groupName === '未知群聊' ? extractNameFromFilePath(filePath) : groupName,
platform: ChatPlatform.QQ,
type: ChatType.GROUP,
}

View File

@@ -17,6 +17,7 @@
*/
import * as fs from 'fs'
import * as path from 'path'
import { parser } from 'stream-json'
import { pick } from 'stream-json/filters/Pick'
import { streamValues } from 'stream-json/streamers/StreamValues'
@@ -34,6 +35,17 @@ import type {
} from '../types'
import { getFileSize, createProgress, readFileHeadBytes, parseTimestamp, isValidYear } from '../utils'
// ==================== 辅助函数 ====================
/**
* 从文件名提取群名
*/
function extractNameFromFilePath(filePath: string): string {
const basename = path.basename(filePath)
const name = basename.replace(/\.json$/i, '')
return name || '未知群聊'
}
// ==================== 特征定义 ====================
export const feature: FormatFeature = {
@@ -159,7 +171,7 @@ async function* parseV4(options: ParseOptions): AsyncGenerator<ParseEvent, void,
// 发送 meta
const meta: ParsedMeta = {
name: chatInfo.name,
name: chatInfo.name === '未知群聊' ? extractNameFromFilePath(filePath) : chatInfo.name,
platform: ChatPlatform.QQ,
type: chatInfo.type === 'group' ? ChatType.GROUP : ChatType.PRIVATE,
}