Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added chatlog
Binary file not shown.
2 changes: 1 addition & 1 deletion internal/chatlog/database/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func NewService(ctx *ctx.Context) *Service {
}

func (s *Service) Start() error {
db, err := wechatdb.New(s.ctx.WorkDir, s.ctx.Platform, s.ctx.Version)
db, err := wechatdb.New(s.ctx.WorkDir, s.ctx.DataDir, s.ctx.Platform, s.ctx.Version)
if err != nil {
return err
}
Expand Down
68 changes: 67 additions & 1 deletion internal/model/message_darwinv3.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package model

import (
"crypto/md5"
"encoding/hex"
"fmt"
"os"
"path/filepath"
"strings"
"time"
)
Expand Down Expand Up @@ -29,7 +34,7 @@ type MessageDarwinV3 struct {
MesDes int `json:"mesDes"` // 0: 发送, 1: 接收
}

func (m *MessageDarwinV3) Wrap(talker string) *Message {
func (m *MessageDarwinV3) Wrap(talker string, dataDir string) *Message {

_m := &Message{
Time: time.Unix(m.MsgCreateTime, 0),
Expand All @@ -38,6 +43,7 @@ func (m *MessageDarwinV3) Wrap(talker string) *Message {
IsChatRoom: strings.HasSuffix(talker, "@chatroom"),
IsSelf: m.MesDes == 0,
Version: WeChatDarwinV3,
Contents: make(map[string]interface{}),
}

content := m.MsgContent
Expand All @@ -53,5 +59,65 @@ func (m *MessageDarwinV3) Wrap(talker string) *Message {

_m.ParseMediaInfo(content)

// 图片消息
if _m.Type == 3 && dataDir != "" {
// 计算talker的MD5
talkerMD5 := md5.Sum([]byte(talker))
talkerMD5Str := hex.EncodeToString(talkerMD5[:])

// 将消息时间转换成秒
timeStr := fmt.Sprintf("%d", m.MsgCreateTime)

// 构建搜索目录
searchDir := filepath.Join(dataDir, "Message", "MessageTemp", talkerMD5Str, "Image")

// 按优先级查找图片文件
patterns := []string{
fmt.Sprintf("%s_.pic.jpg", timeStr),
fmt.Sprintf("%s_.pic_hd.jpg", timeStr),
fmt.Sprintf("%s_.pic_thumb.jpg", timeStr),
}

for _, pattern := range patterns {
if entries, err := os.ReadDir(searchDir); err == nil {
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), pattern) {
// 找到文件,设置相对路径
_m.Contents["imgfile"] = filepath.Join("/Message/MessageTemp", talkerMD5Str, "Image", entry.Name())
break
}
}
if _, exists := _m.Contents["imgfile"]; exists {
break // 找到文件就退出
}
}
}
}

// 视频消息
if _m.Type == 43 && dataDir != "" {
// 计算talker的MD5
talkerMD5 := md5.Sum([]byte(talker))
talkerMD5Str := hex.EncodeToString(talkerMD5[:])

// 将消息时间转换成秒
timeStr := fmt.Sprintf("%d", m.MsgCreateTime)

// 构建搜索目录
searchDir := filepath.Join(dataDir, "Message", "MessageTemp", talkerMD5Str, "Video")

// 查找视频文件
videoPattern := fmt.Sprintf("%s.mp4", timeStr)
if entries, err := os.ReadDir(searchDir); err == nil {
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), videoPattern) {
// 找到文件,设置相对路径
_m.Contents["videofile"] = filepath.Join("/Message/MessageTemp", talkerMD5Str, "Video", entry.Name())
break
}
}
}
}

return _m
}
66 changes: 65 additions & 1 deletion internal/model/message_v3.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package model

import (
"crypto/md5"
"encoding/hex"
"fmt"
"os"
"path/filepath"
"strings"
"time"
Expand Down Expand Up @@ -52,7 +55,7 @@ type MessageV3 struct {
BytesExtra []byte `json:"BytesExtra"` // protobuf 额外数据,记录群聊发送人等信息
}

func (m *MessageV3) Wrap() *Message {
func (m *MessageV3) Wrap(dataDir string) *Message {

_m := &Message{
Seq: m.Sequence,
Expand All @@ -64,6 +67,7 @@ func (m *MessageV3) Wrap() *Message {
SubType: int64(m.SubType),
Content: m.StrContent,
Version: WeChatV3,
Contents: make(map[string]interface{}),
}

if !_m.IsChatRoom && !_m.IsSelf {
Expand All @@ -79,6 +83,66 @@ func (m *MessageV3) Wrap() *Message {

_m.ParseMediaInfo(_m.Content)

// 图片消息
if _m.Type == 3 && dataDir != "" {
// 计算talker的MD5
talkerMD5 := md5.Sum([]byte(m.StrTalker))
talkerMD5Str := hex.EncodeToString(talkerMD5[:])

// 将消息时间转换成秒
timeStr := fmt.Sprintf("%d", m.CreateTime)

// 构建搜索目录
searchDir := filepath.Join(dataDir, "Message", "MessageTemp", talkerMD5Str, "Image")

// 按优先级查找图片文件
patterns := []string{
fmt.Sprintf("%s_.pic.jpg", timeStr),
fmt.Sprintf("%s_.pic_hd.jpg", timeStr),
fmt.Sprintf("%s_.pic_thumb.jpg", timeStr),
}

for _, pattern := range patterns {
if entries, err := os.ReadDir(searchDir); err == nil {
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), pattern) {
// 找到文件,设置相对路径
_m.Contents["imgfile"] = filepath.Join("/Message/MessageTemp", talkerMD5Str, "Image", entry.Name())
break
}
}
if _, exists := _m.Contents["imgfile"]; exists {
break // 找到文件就退出
}
}
}
}

// 视频消息
if _m.Type == 43 && dataDir != "" {
// 计算talker的MD5
talkerMD5 := md5.Sum([]byte(m.StrTalker))
talkerMD5Str := hex.EncodeToString(talkerMD5[:])

// 将消息时间转换成秒
timeStr := fmt.Sprintf("%d", m.CreateTime)

// 构建搜索目录
searchDir := filepath.Join(dataDir, "Message", "MessageTemp", talkerMD5Str, "Video")

// 查找视频文件
videoPattern := fmt.Sprintf("%s.mp4", timeStr)
if entries, err := os.ReadDir(searchDir); err == nil {
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), videoPattern) {
// 找到文件,设置相对路径
_m.Contents["videofile"] = filepath.Join("/Message/MessageTemp", talkerMD5Str, "Video", entry.Name())
break
}
}
}
}

// 语音消息
if _m.Type == 34 {
_m.Contents["voice"] = fmt.Sprint(m.MsgSvrID)
Expand Down
10 changes: 6 additions & 4 deletions internal/wechatdb/datasource/darwinv3/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,18 @@ var Groups = []*dbm.Group{
}

type DataSource struct {
path string
dbm *dbm.DBManager
path string
dataDir string
dbm *dbm.DBManager

talkerDBMap map[string]string
user2DisplayName map[string]string
}

func New(path string) (*DataSource, error) {
func New(path string, dataDir string) (*DataSource, error) {
ds := &DataSource{
path: path,
dataDir: dataDir,
dbm: dbm.NewDBManager(path),
talkerDBMap: make(map[string]string),
user2DisplayName: make(map[string]string),
Expand Down Expand Up @@ -277,7 +279,7 @@ func (ds *DataSource) GetMessages(ctx context.Context, startTime, endTime time.T
}

// 将消息包装为通用模型
message := msg.Wrap(talkerItem)
message := msg.Wrap(talkerItem, ds.dataDir)

// 应用sender过滤
if len(senders) > 0 {
Expand Down
10 changes: 5 additions & 5 deletions internal/wechatdb/datasource/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ type DataSource interface {
Close() error
}

func New(path string, platform string, version int) (DataSource, error) {
func New(workDir string, dataDir string, platform string, version int) (DataSource, error) {
switch {
case platform == "windows" && version == 3:
return windowsv3.New(path)
return windowsv3.New(workDir, dataDir)
case platform == "windows" && version == 4:
return v4.New(path)
return v4.New(workDir)
case platform == "darwin" && version == 3:
return darwinv3.New(path)
return darwinv3.New(workDir, dataDir)
case platform == "darwin" && version == 4:
return v4.New(path)
return v4.New(workDir)
default:
return nil, errors.PlatformUnsupported(platform, version)
}
Expand Down
12 changes: 7 additions & 5 deletions internal/wechatdb/datasource/windowsv3/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,19 @@ type MessageDBInfo struct {

// DataSource 实现了 DataSource 接口
type DataSource struct {
path string
dbm *dbm.DBManager
path string
dataDir string
dbm *dbm.DBManager

// 消息数据库信息
messageInfos []MessageDBInfo
}

// New 创建一个新的 WindowsV3DataSource
func New(path string) (*DataSource, error) {
func New(path string, dataDir string) (*DataSource, error) {
ds := &DataSource{
path: path,
dataDir: dataDir,
dbm: dbm.NewDBManager(path),
messageInfos: make([]MessageDBInfo, 0),
}
Expand Down Expand Up @@ -327,8 +329,8 @@ func (ds *DataSource) GetMessages(ctx context.Context, startTime, endTime time.T
msg.CompressContent = compressContent
msg.BytesExtra = bytesExtra

// 将消息转换为标准格式
message := msg.Wrap()
// 将消息转换为标准格式
message := msg.Wrap(ds.dataDir)

// 应用sender过滤
if len(senders) > 0 {
Expand Down
10 changes: 6 additions & 4 deletions internal/wechatdb/wechatdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@ import (
)

type DB struct {
path string
workDir string
dataDir string
platform string
version int
ds datasource.DataSource
repo *repository.Repository
}

func New(path string, platform string, version int) (*DB, error) {
func New(workDir string, dataDir string, platform string, version int) (*DB, error) {

w := &DB{
path: path,
workDir: workDir,
dataDir: dataDir,
platform: platform,
version: version,
}
Expand All @@ -44,7 +46,7 @@ func (w *DB) Close() error {

func (w *DB) Initialize() error {
var err error
w.ds, err = datasource.New(w.path, w.platform, w.version)
w.ds, err = datasource.New(w.workDir, w.dataDir, w.platform, w.version)
if err != nil {
return err
}
Expand Down