Compare commits

..

No commits in common. "main" and "v1.2.1" have entirely different histories.
main ... v1.2.1

23 changed files with 585 additions and 642 deletions

3
.gitignore vendored
View File

@ -30,5 +30,4 @@ env
User
config.json
wechatDataBackup.exe
app.log
app-*.log
app.log

View File

@ -1,34 +1,13 @@
<p align="center" style="text-align: center">
<img src="./res/logo_256.png" width="15%"><br/>
</p>
<p align="center">
<b>wechatDataBackup: PC微信聊天记录数据导出工具</b>
<br/>
<br/>
<a href="https://github.com/git-jiadong/wechatDataBackup/stargazers">
<img src="https://img.shields.io/github/stars/git-jiadong/wechatDataBackup" alt="GitHub Star"/>
</a>
<a href="https://github.com/git-jiadong/wechatDataBackup/releases">
<img src="https://img.shields.io/github/downloads/git-jiadong/wechatDataBackup/total" alt="downloads" />
</a>
<a href="https://github.com/git-jiadong/wechatDataBackup/releases">
<img src="https://img.shields.io/github/v/release/git-jiadong/wechatDataBackup" alt="releases version"/>
</a>
<a href="https://github.com/git-jiadong/wechatDataBackup/commits/main">
<img src="https://img.shields.io/github/last-commit/git-jiadong/wechatDataBackup" alt="last commit" />
</a>
<a href="https://github.com/git-jiadong/wechatDataBackup" >
<img src="https://img.shields.io/github/languages/top/git-jiadong/wechatDataBackup" alt="languages"/>
</a>
<a href="https://github.com/git-jiadong/wechatDataBackup" >
<img src="https://img.shields.io/github/repo-size/git-jiadong/wechatDataBackup" alt="repo size" />
</a>
<a href="https://github.com/git-jiadong/wechatDataBackup/blob/main/LICENSE">
<img src="https://img.shields.io/github/license/git-jiadong/wechatDataBackup" alt="license" />
</a>
</p>
# wechatDataBackup
PC微信聊天记录数据导出工具
[![GitHub stars](https://img.shields.io/github/stars/git-jiadong/wechatDataBackup)](https://github.com/git-jiadong/wechatDataBackup/stargazers)
[![GitHub all releases](https://img.shields.io/github/downloads/git-jiadong/wechatDataBackup/total)](https://github.com/git-jiadong/wechatDataBackup/releases)
[![GitHub release](https://img.shields.io/github/v/release/git-jiadong/wechatDataBackup)](https://github.com/git-jiadong/wechatDataBackup/releases)
[![GitHub last commit](https://img.shields.io/github/last-commit/git-jiadong/wechatDataBackup)](https://github.com/git-jiadong/wechatDataBackup/commits/main)
[![GitHub top language](https://img.shields.io/github/languages/top/git-jiadong/wechatDataBackup)](https://github.com/git-jiadong/wechatDataBackup)
[![GitHub repo size](https://img.shields.io/github/repo-size/git-jiadong/wechatDataBackup)](https://github.com/git-jiadong/wechatDataBackup)
[![GitHub license](https://img.shields.io/github/license/git-jiadong/wechatDataBackup)](https://github.com/git-jiadong/wechatDataBackup/blob/main/LICENSE)
* 基于wails开发 + React前端实现PC端微信聊天记录一键导出功能。
* 导出后数据可以做永久化保存,即使微信停止支持,聊天记录也可以随时查看。

25
app.go
View File

@ -23,7 +23,7 @@ const (
configDefaultUserKey = "userConfig.defaultUser"
configUsersKey = "userConfig.users"
configExportPathKey = "exportPath"
appVersion = "v1.2.4"
appVersion = "v1.2.1"
)
type FileLoader struct {
@ -832,6 +832,14 @@ func (a *App) ExportWeChatDataByUserName(userName, path string) string {
return "WeChatExportDataByUserName failed:" + err.Error()
}
exeSrcPath := a.FLoader.FilePrefix + "\\" + "wechatDataBackup.exe"
exeDstPath := exPath + "\\" + "wechatDataBackup.exe"
_, err = utils.CopyFile(exeSrcPath, exeDstPath)
if err != nil {
log.Println("CopyFile:", err)
return "CopyFile:" + err.Error()
}
config := map[string]interface{}{
"exportpath": ".\\",
"userconfig": map[string]interface{}{
@ -853,21 +861,6 @@ func (a *App) ExportWeChatDataByUserName(userName, path string) string {
return "WriteFile:" + err.Error()
}
exeSrcPath, err := os.Executable()
if err != nil {
log.Println("Executable:", exeSrcPath)
return "Executable:" + err.Error()
}
exeDstPath := exPath + "\\" + "wechatDataBackup.exe"
log.Printf("Copy [%s] -> [%s]\n", exeSrcPath, exeDstPath)
_, err = utils.CopyFile(exeSrcPath, exeDstPath)
if err != nil {
log.Println("CopyFile:", err)
return "CopyFile:" + err.Error()
}
return ""
return ""
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 411 KiB

View File

@ -1,16 +1,3 @@
## v1.2.4
1. 修复FileStorage\Image文件没有导出的问题
2. 增加图片定位到聊天位置的功能
3. 导出界面增加提示
## v1.2.3
1. 修改程序ICON
## v1.2.2
1. UI统一使用“思源黑体”字体
2. 修复导出分享会话时可执行文件可能拷贝错误的情况
3. 修复微信存储路径为网盘时,解密会失败的情况
## v1.2.0
1. 实现最后浏览位置记录和书签功能
2. 实现会话导出分享功能

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

533
frontend/dist/assets/index.e4a8c0f4.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

View File

@ -4,8 +4,8 @@
<meta charset="UTF-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>wechatDataBackup</title>
<script type="module" crossorigin src="/assets/index.8be36b27.js"></script>
<link rel="stylesheet" href="/assets/index.00f6955e.css">
<script type="module" crossorigin src="/assets/index.e4a8c0f4.js"></script>
<link rel="stylesheet" href="/assets/index.0393a903.css">
</head>
<body >
<div id="root"></div>

View File

@ -310,7 +310,6 @@ func exportWeChatVideoAndFile(info WeChatInfo, expPath string, progress chan<- s
videoRootPath := info.FilePath + "\\FileStorage\\Video"
fileRootPath := info.FilePath + "\\FileStorage\\File"
cacheRootPath := info.FilePath + "\\FileStorage\\Cache"
rootPaths := []string{videoRootPath, fileRootPath, cacheRootPath}
handleNumber := int64(0)
@ -327,9 +326,6 @@ func exportWeChatVideoAndFile(info WeChatInfo, expPath string, progress chan<- s
go func() {
for _, rootPath := range rootPaths {
log.Println(rootPath)
if _, err := os.Stat(rootPath); err != nil {
continue
}
err := filepath.Walk(rootPath, func(path string, finfo os.FileInfo, err error) error {
if err != nil {
log.Printf("filepath.Walk%v\n", err)
@ -403,51 +399,43 @@ func exportWeChatVideoAndFile(info WeChatInfo, expPath string, progress chan<- s
func exportWeChatBat(info WeChatInfo, expPath string, progress chan<- string) {
progress <- "{\"status\":\"processing\", \"result\":\"export WeChat Dat start\", \"progress\": 21}"
datRootPath := info.FilePath + "\\FileStorage\\MsgAttach"
imageRootPath := info.FilePath + "\\FileStorage\\Image"
rootPaths := []string{datRootPath, imageRootPath}
fileInfo, err := os.Stat(datRootPath)
if err != nil || !fileInfo.IsDir() {
progress <- fmt.Sprintf("{\"status\":\"error\", \"result\":\"%s error\"}", datRootPath)
return
}
handleNumber := int64(0)
fileNumber := int64(0)
for i := range rootPaths {
fileNumber += getPathFileNumber(rootPaths[i], ".dat")
}
log.Println("DatFileNumber ", fileNumber)
fileNumber := getPathFileNumber(datRootPath, ".dat")
var wg sync.WaitGroup
var reportWg sync.WaitGroup
quitChan := make(chan struct{})
taskChan := make(chan [2]string, 100)
go func() {
for i := range rootPaths {
if _, err := os.Stat(rootPaths[i]); err != nil {
continue
}
err := filepath.Walk(rootPaths[i], func(path string, finfo os.FileInfo, err error) error {
if err != nil {
log.Printf("filepath.Walk%v\n", err)
return err
}
if !finfo.IsDir() && strings.HasSuffix(path, ".dat") {
expFile := expPath + path[len(info.FilePath):]
_, err := os.Stat(filepath.Dir(expFile))
if err != nil {
os.MkdirAll(filepath.Dir(expFile), 0644)
}
task := [2]string{path, expFile}
taskChan <- task
return nil
}
return nil
})
err = filepath.Walk(datRootPath, func(path string, finfo os.FileInfo, err error) error {
if err != nil {
log.Println("filepath.Walk:", err)
progress <- fmt.Sprintf("{\"status\":\"error\", \"result\":\"%v\"}", err)
log.Printf("filepath.Walk%v\n", err)
return err
}
if !finfo.IsDir() && strings.HasSuffix(path, ".dat") {
expFile := expPath + path[len(info.FilePath):]
_, err := os.Stat(filepath.Dir(expFile))
if err != nil {
os.MkdirAll(filepath.Dir(expFile), 0644)
}
task := [2]string{path, expFile}
taskChan <- task
return nil
}
return nil
})
if err != nil {
log.Println("filepath.Walk:", err)
progress <- fmt.Sprintf("{\"status\":\"error\", \"result\":\"%v\"}", err)
}
close(taskChan)
}()
@ -457,7 +445,7 @@ func exportWeChatBat(info WeChatInfo, expPath string, progress chan<- string) {
go func() {
defer wg.Done()
for task := range taskChan {
_, err := os.Stat(task[1])
_, err = os.Stat(task[1])
if err == nil {
atomic.AddInt64(&handleNumber, 1)
continue
@ -610,7 +598,7 @@ func GetWeChatInfo() (list *WeChatInfoList) {
for _, f := range files {
if strings.HasSuffix(f.Path, "\\Media.db") {
// fmt.Printf("opened %s\n", f.Path[4:])
filePath := f.Path
filePath := f.Path[4:]
parts := strings.Split(filePath, string(filepath.Separator))
if len(parts) < 4 {
log.Println("Error filePath " + filePath)

View File

@ -182,7 +182,6 @@ type WeChatMessage struct {
}
type WeChatMessageList struct {
MsgType string `json:"MsgType"`
KeyWord string `json:"KeyWord"`
Total int `json:"Total"`
Rows []WeChatMessage `json:"Rows"`
@ -693,7 +692,6 @@ func (P *WechatDataProvider) WeChatGetMessageListByKeyWord(userName string, time
List := &WeChatMessageList{}
List.Rows = make([]WeChatMessage, 0)
List.KeyWord = keyWord
List.MsgType = msgType
_time := time
selectPagesize := pageSize
if keyWord != "" || msgType != "" {
@ -734,7 +732,6 @@ func (P *WechatDataProvider) WeChatGetMessageListByType(userName string, time in
List := &WeChatMessageList{}
List.Rows = make([]WeChatMessage, 0)
List.MsgType = msgType
selectTime := time
selectpageSize := 30
needSize := pageSize

Binary file not shown.

Before

Width:  |  Height:  |  Size: 470 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB