Support Media Message (#9)
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -14,6 +13,7 @@ import (
|
||||
"github.com/sjzar/chatlog/pkg/util"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -21,6 +21,7 @@ const (
|
||||
ContactFilePattern = "^wccontact_new2\\.db$"
|
||||
ChatRoomFilePattern = "^group_new\\.db$"
|
||||
SessionFilePattern = "^session_new\\.db$"
|
||||
MediaFilePattern = "^hldata\\.db$"
|
||||
)
|
||||
|
||||
type DataSource struct {
|
||||
@@ -29,6 +30,7 @@ type DataSource struct {
|
||||
contactDb *sql.DB
|
||||
chatRoomDb *sql.DB
|
||||
sessionDb *sql.DB
|
||||
mediaDb *sql.DB
|
||||
|
||||
talkerDBMap map[string]*sql.DB
|
||||
user2DisplayName map[string]string
|
||||
@@ -54,6 +56,9 @@ func New(path string) (*DataSource, error) {
|
||||
if err := ds.initSessionDb(path); err != nil {
|
||||
return nil, fmt.Errorf("初始化会话数据库失败: %w", err)
|
||||
}
|
||||
if err := ds.initMediaDb(path); err != nil {
|
||||
return nil, fmt.Errorf("初始化会话数据库失败: %w", err)
|
||||
}
|
||||
|
||||
return ds, nil
|
||||
}
|
||||
@@ -138,7 +143,7 @@ func (ds *DataSource) initChatRoomDb(path string) error {
|
||||
return fmt.Errorf("连接群聊数据库失败: %w", err)
|
||||
}
|
||||
|
||||
rows, err := ds.chatRoomDb.Query("SELECT m_nsUsrName, nickname FROM GroupMember")
|
||||
rows, err := ds.chatRoomDb.Query("SELECT m_nsUsrName, IFNULL(nickname,\"\") FROM GroupMember")
|
||||
if err != nil {
|
||||
log.Printf("警告: 获取群聊成员失败: %v", err)
|
||||
return nil
|
||||
@@ -173,6 +178,21 @@ func (ds *DataSource) initSessionDb(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *DataSource) initMediaDb(path string) error {
|
||||
files, err := util.FindFilesWithPatterns(path, MediaFilePattern, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查找媒体数据库文件失败: %w", err)
|
||||
}
|
||||
if len(files) == 0 {
|
||||
return fmt.Errorf("未找到媒体数据库文件: %s", path)
|
||||
}
|
||||
ds.mediaDb, err = sql.Open("sqlite3", files[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("连接媒体数据库失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMessages 实现获取消息的方法
|
||||
func (ds *DataSource) GetMessages(ctx context.Context, startTime, endTime time.Time, talker string, limit, offset int) ([]*model.Message, error) {
|
||||
// 在 darwinv3 中,每个联系人/群聊的消息存储在单独的表中,表名为 Chat_md5(talker)
|
||||
@@ -191,7 +211,7 @@ func (ds *DataSource) GetMessages(ctx context.Context, startTime, endTime time.T
|
||||
|
||||
// 构建查询条件
|
||||
query := fmt.Sprintf(`
|
||||
SELECT msgCreateTime, msgContent, messageType, mesDes, msgSource, CompressContent, ConBlob
|
||||
SELECT msgCreateTime, msgContent, messageType, mesDes
|
||||
FROM %s
|
||||
WHERE msgCreateTime >= ? AND msgCreateTime <= ?
|
||||
ORDER BY msgCreateTime ASC
|
||||
@@ -216,15 +236,11 @@ func (ds *DataSource) GetMessages(ctx context.Context, startTime, endTime time.T
|
||||
messages := []*model.Message{}
|
||||
for rows.Next() {
|
||||
var msg model.MessageDarwinV3
|
||||
var compressContent, conBlob []byte
|
||||
err := rows.Scan(
|
||||
&msg.MesCreateTime,
|
||||
&msg.MesContent,
|
||||
&msg.MesType,
|
||||
&msg.MsgCreateTime,
|
||||
&msg.MsgContent,
|
||||
&msg.MessageType,
|
||||
&msg.MesDes,
|
||||
&msg.MesSource,
|
||||
&compressContent,
|
||||
&conBlob,
|
||||
)
|
||||
if err != nil {
|
||||
log.Printf("警告: 扫描消息行失败: %v", err)
|
||||
@@ -260,13 +276,13 @@ func (ds *DataSource) GetContacts(ctx context.Context, key string, limit, offset
|
||||
|
||||
if key != "" {
|
||||
// 按照关键字查询
|
||||
query = `SELECT IFNULL(m_nsUsrName,""), nickname, IFNULL(m_nsRemark,""), m_uiSex, IFNULL(m_nsAliasName,"")
|
||||
query = `SELECT IFNULL(m_nsUsrName,""), IFNULL(nickname,""), IFNULL(m_nsRemark,""), m_uiSex, IFNULL(m_nsAliasName,"")
|
||||
FROM WCContact
|
||||
WHERE m_nsUsrName = ? OR nickname = ? OR m_nsRemark = ? OR m_nsAliasName = ?`
|
||||
args = []interface{}{key, key, key, key}
|
||||
} else {
|
||||
// 查询所有联系人
|
||||
query = `SELECT IFNULL(m_nsUsrName,""), nickname, IFNULL(m_nsRemark,""), m_uiSex, IFNULL(m_nsAliasName,"")
|
||||
query = `SELECT IFNULL(m_nsUsrName,""), IFNULL(nickname,""), IFNULL(m_nsRemark,""), m_uiSex, IFNULL(m_nsAliasName,"")
|
||||
FROM WCContact`
|
||||
}
|
||||
|
||||
@@ -314,13 +330,13 @@ func (ds *DataSource) GetChatRooms(ctx context.Context, key string, limit, offse
|
||||
|
||||
if key != "" {
|
||||
// 按照关键字查询
|
||||
query = `SELECT IFNULL(m_nsUsrName,""), nickname, IFNULL(m_nsRemark,""), IFNULL(m_nsChatRoomMemList,""), IFNULL(m_nsChatRoomAdminList,"")
|
||||
query = `SELECT IFNULL(m_nsUsrName,""), IFNULL(nickname,""), IFNULL(m_nsRemark,""), IFNULL(m_nsChatRoomMemList,""), IFNULL(m_nsChatRoomAdminList,"")
|
||||
FROM GroupContact
|
||||
WHERE m_nsUsrName = ? OR nickname = ? OR m_nsRemark = ?`
|
||||
args = []interface{}{key, key, key}
|
||||
} else {
|
||||
// 查询所有群聊
|
||||
query = `SELECT IFNULL(m_nsUsrName,""), nickname, IFNULL(m_nsRemark,""), IFNULL(m_nsChatRoomMemList,""), IFNULL(m_nsChatRoomAdminList,"")
|
||||
query = `SELECT IFNULL(m_nsUsrName,""), IFNULL(nickname,""), IFNULL(m_nsRemark,""), IFNULL(m_nsChatRoomMemList,""), IFNULL(m_nsChatRoomAdminList,"")
|
||||
FROM GroupContact`
|
||||
}
|
||||
|
||||
@@ -364,7 +380,7 @@ func (ds *DataSource) GetChatRooms(ctx context.Context, key string, limit, offse
|
||||
if err == nil && len(contacts) > 0 && strings.HasSuffix(contacts[0].UserName, "@chatroom") {
|
||||
// 再次尝试通过用户名查找群聊
|
||||
rows, err := ds.chatRoomDb.QueryContext(ctx,
|
||||
`SELECT IFNULL(m_nsUsrName,""), nickname, IFNULL(m_nsRemark,""), IFNULL(m_nsChatRoomMemList,""), IFNULL(m_nsChatRoomAdminList,"")
|
||||
`SELECT IFNULL(m_nsUsrName,""), IFNULL(nickname,""), IFNULL(m_nsRemark,""), IFNULL(m_nsChatRoomMemList,""), IFNULL(m_nsChatRoomAdminList,"")
|
||||
FROM GroupContact
|
||||
WHERE m_nsUsrName = ?`,
|
||||
contacts[0].UserName)
|
||||
@@ -470,6 +486,58 @@ func (ds *DataSource) GetSessions(ctx context.Context, key string, limit, offset
|
||||
return sessions, nil
|
||||
}
|
||||
|
||||
func (ds *DataSource) GetMedia(ctx context.Context, _type string, key string) (*model.Media, error) {
|
||||
if key == "" {
|
||||
return nil, fmt.Errorf("key 不能为空")
|
||||
}
|
||||
query := `SELECT
|
||||
r.mediaMd5,
|
||||
r.mediaSize,
|
||||
r.inodeNumber,
|
||||
r.modifyTime,
|
||||
d.relativePath,
|
||||
d.fileName
|
||||
FROM
|
||||
HlinkMediaRecord r
|
||||
JOIN
|
||||
HlinkMediaDetail d ON r.inodeNumber = d.inodeNumber
|
||||
WHERE
|
||||
r.mediaMd5 = ?`
|
||||
args := []interface{}{key}
|
||||
// 执行查询
|
||||
rows, err := ds.mediaDb.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询媒体失败: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var media *model.Media
|
||||
for rows.Next() {
|
||||
var mediaDarwinV3 model.MediaDarwinV3
|
||||
err := rows.Scan(
|
||||
&mediaDarwinV3.MediaMd5,
|
||||
&mediaDarwinV3.MediaSize,
|
||||
&mediaDarwinV3.InodeNumber,
|
||||
&mediaDarwinV3.ModifyTime,
|
||||
&mediaDarwinV3.RelativePath,
|
||||
&mediaDarwinV3.FileName,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("扫描会话行失败: %w", err)
|
||||
}
|
||||
|
||||
// 包装成通用模型
|
||||
media = mediaDarwinV3.Wrap()
|
||||
}
|
||||
|
||||
if media == nil {
|
||||
return nil, fmt.Errorf("未找到媒体 %s", key)
|
||||
}
|
||||
|
||||
return media, nil
|
||||
}
|
||||
|
||||
// Close 实现关闭数据库连接的方法
|
||||
func (ds *DataSource) Close() error {
|
||||
var errs []error
|
||||
@@ -502,6 +570,13 @@ func (ds *DataSource) Close() error {
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭媒体数据库连接
|
||||
if ds.mediaDb != nil {
|
||||
if err := ds.mediaDb.Close(); err != nil {
|
||||
errs = append(errs, fmt.Errorf("关闭媒体数据库失败: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return fmt.Errorf("关闭数据库连接时发生错误: %v", errs)
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ type DataSource interface {
|
||||
// 最近会话
|
||||
GetSessions(ctx context.Context, key string, limit, offset int) ([]*model.Session, error)
|
||||
|
||||
// 媒体
|
||||
GetMedia(ctx context.Context, _type string, key string) (*model.Media, error)
|
||||
|
||||
Close() error
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ const (
|
||||
MessageFilePattern = "^message_([0-9]?[0-9])?\\.db$"
|
||||
ContactFilePattern = "^contact\\.db$"
|
||||
SessionFilePattern = "^session\\.db$"
|
||||
MediaFilePattern = "^hardlink\\.db$"
|
||||
)
|
||||
|
||||
// MessageDBInfo 存储消息数据库的信息
|
||||
@@ -36,6 +37,7 @@ type DataSource struct {
|
||||
messageDbs map[string]*sql.DB
|
||||
contactDb *sql.DB
|
||||
sessionDb *sql.DB
|
||||
mediaDb *sql.DB
|
||||
|
||||
// 消息数据库信息
|
||||
messageFiles []MessageDBInfo
|
||||
@@ -57,6 +59,9 @@ func New(path string) (*DataSource, error) {
|
||||
if err := ds.initSessionDb(path); err != nil {
|
||||
return nil, fmt.Errorf("初始化会话数据库失败: %w", err)
|
||||
}
|
||||
if err := ds.initMediaDb(path); err != nil {
|
||||
return nil, fmt.Errorf("初始化媒体数据库失败: %w", err)
|
||||
}
|
||||
|
||||
return ds, nil
|
||||
}
|
||||
@@ -175,6 +180,21 @@ func (ds *DataSource) initSessionDb(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *DataSource) initMediaDb(path string) error {
|
||||
files, err := util.FindFilesWithPatterns(path, MediaFilePattern, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查找媒体数据库文件失败: %w", err)
|
||||
}
|
||||
if len(files) == 0 {
|
||||
return fmt.Errorf("未找到媒体数据库文件: %s", path)
|
||||
}
|
||||
ds.mediaDb, err = sql.Open("sqlite3", files[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("连接媒体数据库失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getDBInfosForTimeRange 获取时间范围内的数据库信息
|
||||
func (ds *DataSource) getDBInfosForTimeRange(startTime, endTime time.Time) []MessageDBInfo {
|
||||
var dbs []MessageDBInfo
|
||||
@@ -602,6 +622,81 @@ func (ds *DataSource) GetSessions(ctx context.Context, key string, limit, offset
|
||||
return sessions, nil
|
||||
}
|
||||
|
||||
func (ds *DataSource) GetMedia(ctx context.Context, _type string, key string) (*model.Media, error) {
|
||||
if key == "" {
|
||||
return nil, fmt.Errorf("key 不能为空")
|
||||
}
|
||||
|
||||
if len(key) != 32 {
|
||||
return nil, fmt.Errorf("key 长度必须为 32")
|
||||
}
|
||||
|
||||
var table string
|
||||
switch _type {
|
||||
case "image":
|
||||
table = "image_hardlink_info_v3"
|
||||
case "video":
|
||||
table = "video_hardlink_info_v3"
|
||||
case "file":
|
||||
table = "file_hardlink_info_v3"
|
||||
default:
|
||||
return nil, fmt.Errorf("不支持的媒体类型: %s", _type)
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(`
|
||||
SELECT
|
||||
f.md5,
|
||||
f.file_name,
|
||||
f.file_size,
|
||||
f.modify_time,
|
||||
IFNULL(d1.username,""),
|
||||
IFNULL(d2.username,"")
|
||||
FROM
|
||||
%s f
|
||||
LEFT JOIN
|
||||
dir2id d1 ON d1.rowid = f.dir1
|
||||
LEFT JOIN
|
||||
dir2id d2 ON d2.rowid = f.dir2
|
||||
`, table)
|
||||
query += " WHERE f.md5 = ? OR f.file_name LIKE ? || '%'"
|
||||
args := []interface{}{key, key}
|
||||
|
||||
rows, err := ds.mediaDb.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询媒体失败: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var media *model.Media
|
||||
for rows.Next() {
|
||||
var mediaV4 model.MediaV4
|
||||
err := rows.Scan(
|
||||
&mediaV4.Key,
|
||||
&mediaV4.Name,
|
||||
&mediaV4.Size,
|
||||
&mediaV4.ModifyTime,
|
||||
&mediaV4.Dir1,
|
||||
&mediaV4.Dir2,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("扫描会话行失败: %w", err)
|
||||
}
|
||||
mediaV4.Type = _type
|
||||
media = mediaV4.Wrap()
|
||||
|
||||
// 跳过缩略图
|
||||
if _type == "image" && !strings.Contains(media.Name, "_t") {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if media == nil {
|
||||
return nil, fmt.Errorf("未找到媒体 %s", key)
|
||||
}
|
||||
|
||||
return media, nil
|
||||
}
|
||||
|
||||
func (ds *DataSource) Close() error {
|
||||
var errs []error
|
||||
|
||||
@@ -626,6 +721,12 @@ func (ds *DataSource) Close() error {
|
||||
}
|
||||
}
|
||||
|
||||
if ds.mediaDb != nil {
|
||||
if err := ds.mediaDb.Close(); err != nil {
|
||||
errs = append(errs, fmt.Errorf("关闭媒体数据库失败: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return fmt.Errorf("关闭数据库连接时发生错误: %v", errs)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package windowsv3
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
@@ -18,6 +19,9 @@ import (
|
||||
const (
|
||||
MessageFilePattern = "^MSG([0-9]?[0-9])?\\.db$"
|
||||
ContactFilePattern = "^MicroMsg.db$"
|
||||
ImageFilePattern = "^HardLinkImage\\.db$"
|
||||
VideoFilePattern = "^HardLinkVideo\\.db$"
|
||||
FileFilePattern = "^HardLinkFile\\.db$"
|
||||
)
|
||||
|
||||
// MessageDBInfo 保存消息数据库的信息
|
||||
@@ -37,6 +41,10 @@ type DataSource struct {
|
||||
// 联系人数据库
|
||||
contactDbFile string
|
||||
contactDb *sql.DB
|
||||
|
||||
imageDb *sql.DB
|
||||
videoDb *sql.DB
|
||||
fileDb *sql.DB
|
||||
}
|
||||
|
||||
// New 创建一个新的 WindowsV3DataSource
|
||||
@@ -56,6 +64,10 @@ func New(path string) (*DataSource, error) {
|
||||
return nil, fmt.Errorf("初始化联系人数据库失败: %w", err)
|
||||
}
|
||||
|
||||
if err := ds.initMediaDb(path); err != nil {
|
||||
return nil, fmt.Errorf("初始化多媒体数据库失败: %w", err)
|
||||
}
|
||||
|
||||
return ds, nil
|
||||
}
|
||||
|
||||
@@ -178,6 +190,53 @@ func (ds *DataSource) initContactDb(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// initContactDb 初始化联系人数据库
|
||||
func (ds *DataSource) initMediaDb(path string) error {
|
||||
files, err := util.FindFilesWithPatterns(path, ImageFilePattern, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查找图片数据库文件失败: %w", err)
|
||||
}
|
||||
|
||||
if len(files) == 0 {
|
||||
return fmt.Errorf("未找到图片数据库文件: %s", path)
|
||||
}
|
||||
|
||||
ds.imageDb, err = sql.Open("sqlite3", files[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("连接图片数据库失败: %w", err)
|
||||
}
|
||||
|
||||
files, err = util.FindFilesWithPatterns(path, VideoFilePattern, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查找视频数据库文件失败: %w", err)
|
||||
}
|
||||
|
||||
if len(files) == 0 {
|
||||
return fmt.Errorf("未找到视频数据库文件: %s", path)
|
||||
}
|
||||
|
||||
ds.videoDb, err = sql.Open("sqlite3", files[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("连接视频数据库失败: %w", err)
|
||||
}
|
||||
|
||||
files, err = util.FindFilesWithPatterns(path, FileFilePattern, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("查找文件数据库文件失败: %w", err)
|
||||
}
|
||||
|
||||
if len(files) == 0 {
|
||||
return fmt.Errorf("未找到文件数据库文件: %s", path)
|
||||
}
|
||||
|
||||
ds.fileDb, err = sql.Open("sqlite3", files[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("连接文件数据库失败: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getDBInfosForTimeRange 获取时间范围内的数据库信息
|
||||
func (ds *DataSource) getDBInfosForTimeRange(startTime, endTime time.Time) []MessageDBInfo {
|
||||
var dbs []MessageDBInfo
|
||||
@@ -589,6 +648,84 @@ func (ds *DataSource) GetSessions(ctx context.Context, key string, limit, offset
|
||||
return sessions, nil
|
||||
}
|
||||
|
||||
func (ds *DataSource) GetMedia(ctx context.Context, _type string, key string) (*model.Media, error) {
|
||||
if key == "" {
|
||||
return nil, fmt.Errorf("key 不能为空")
|
||||
}
|
||||
|
||||
md5key, err := hex.DecodeString(key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("解析 key 失败: %w", err)
|
||||
}
|
||||
|
||||
var db *sql.DB
|
||||
var table1, table2 string
|
||||
|
||||
switch _type {
|
||||
case "image":
|
||||
db = ds.imageDb
|
||||
table1 = "HardLinkImageAttribute"
|
||||
table2 = "HardLinkImageID"
|
||||
case "video":
|
||||
db = ds.videoDb
|
||||
table1 = "HardLinkVideoAttribute"
|
||||
table2 = "HardLinkVideoID"
|
||||
case "file":
|
||||
db = ds.fileDb
|
||||
table1 = "HardLinkFileAttribute"
|
||||
table2 = "HardLinkFileID"
|
||||
default:
|
||||
return nil, fmt.Errorf("不支持的媒体类型: %s", _type)
|
||||
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(`
|
||||
SELECT
|
||||
a.FileName,
|
||||
a.ModifyTime,
|
||||
IFNULL(d1.Dir,"") AS Dir1,
|
||||
IFNULL(d2.Dir,"") AS Dir2
|
||||
FROM
|
||||
%s a
|
||||
LEFT JOIN
|
||||
%s d1 ON a.DirID1 = d1.DirId
|
||||
LEFT JOIN
|
||||
%s d2 ON a.DirID2 = d2.DirId
|
||||
WHERE
|
||||
a.Md5 = ?
|
||||
`, table1, table2, table2)
|
||||
args := []interface{}{md5key}
|
||||
|
||||
rows, err := db.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询媒体失败: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var media *model.Media
|
||||
for rows.Next() {
|
||||
var mediaV3 model.MediaV3
|
||||
err := rows.Scan(
|
||||
&mediaV3.Name,
|
||||
&mediaV3.ModifyTime,
|
||||
&mediaV3.Dir1,
|
||||
&mediaV3.Dir2,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("扫描会话行失败: %w", err)
|
||||
}
|
||||
mediaV3.Type = _type
|
||||
mediaV3.Key = key
|
||||
media = mediaV3.Wrap()
|
||||
}
|
||||
|
||||
if media == nil {
|
||||
return nil, fmt.Errorf("未找到媒体 %s", key)
|
||||
}
|
||||
|
||||
return media, nil
|
||||
}
|
||||
|
||||
// Close 实现 DataSource 接口的 Close 方法
|
||||
func (ds *DataSource) Close() error {
|
||||
var errs []error
|
||||
@@ -607,6 +744,22 @@ func (ds *DataSource) Close() error {
|
||||
}
|
||||
}
|
||||
|
||||
if ds.imageDb != nil {
|
||||
if err := ds.imageDb.Close(); err != nil {
|
||||
errs = append(errs, fmt.Errorf("关闭图片数据库失败: %w", err))
|
||||
}
|
||||
}
|
||||
if ds.videoDb != nil {
|
||||
if err := ds.videoDb.Close(); err != nil {
|
||||
errs = append(errs, fmt.Errorf("关闭视频数据库失败: %w", err))
|
||||
}
|
||||
}
|
||||
if ds.fileDb != nil {
|
||||
if err := ds.fileDb.Close(); err != nil {
|
||||
errs = append(errs, fmt.Errorf("关闭文件数据库失败: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return fmt.Errorf("关闭数据库连接时发生错误: %v", errs)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user