880 lines
22 KiB
Go
880 lines
22 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"mime"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"wechatDataBackup/pkg/utils"
|
|
"wechatDataBackup/pkg/wechat"
|
|
|
|
"github.com/spf13/viper"
|
|
"github.com/wailsapp/wails/v2/pkg/runtime"
|
|
)
|
|
|
|
const (
|
|
defaultConfig = "config"
|
|
configDefaultUserKey = "userConfig.defaultUser"
|
|
configUsersKey = "userConfig.users"
|
|
configExportPathKey = "exportPath"
|
|
appVersion = "v1.2.4"
|
|
)
|
|
|
|
type FileLoader struct {
|
|
http.Handler
|
|
FilePrefix string
|
|
}
|
|
|
|
func NewFileLoader(prefix string) *FileLoader {
|
|
mime.AddExtensionType(".mp3", "audio/mpeg")
|
|
return &FileLoader{FilePrefix: prefix}
|
|
}
|
|
|
|
func (h *FileLoader) SetFilePrefix(prefix string) {
|
|
h.FilePrefix = prefix
|
|
log.Println("SetFilePrefix", h.FilePrefix)
|
|
}
|
|
|
|
func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
|
requestedFilename := h.FilePrefix + "\\" + strings.TrimPrefix(req.URL.Path, "/")
|
|
|
|
file, err := os.Open(requestedFilename)
|
|
if err != nil {
|
|
http.Error(res, fmt.Sprintf("Could not load file %s", requestedFilename), http.StatusBadRequest)
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
fileInfo, err := file.Stat()
|
|
if err != nil {
|
|
http.Error(res, "Could not retrieve file info", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
fileSize := fileInfo.Size()
|
|
rangeHeader := req.Header.Get("Range")
|
|
if rangeHeader == "" {
|
|
// 无 Range 请求,直接返回整个文件
|
|
res.Header().Set("Content-Length", strconv.FormatInt(fileSize, 10))
|
|
http.ServeContent(res, req, requestedFilename, fileInfo.ModTime(), file)
|
|
return
|
|
}
|
|
|
|
var start, end int64
|
|
if strings.HasPrefix(rangeHeader, "bytes=") {
|
|
ranges := strings.Split(strings.TrimPrefix(rangeHeader, "bytes="), "-")
|
|
start, _ = strconv.ParseInt(ranges[0], 10, 64)
|
|
|
|
if len(ranges) > 1 && ranges[1] != "" {
|
|
end, _ = strconv.ParseInt(ranges[1], 10, 64)
|
|
} else {
|
|
end = fileSize - 1
|
|
}
|
|
} else {
|
|
http.Error(res, "Invalid Range header", http.StatusRequestedRangeNotSatisfiable)
|
|
return
|
|
}
|
|
|
|
if start < 0 || end >= fileSize || start > end {
|
|
http.Error(res, "Requested range not satisfiable", http.StatusRequestedRangeNotSatisfiable)
|
|
return
|
|
}
|
|
|
|
contentType := mime.TypeByExtension(filepath.Ext(requestedFilename))
|
|
if contentType == "" {
|
|
contentType = "application/octet-stream"
|
|
}
|
|
res.Header().Set("Content-Type", contentType)
|
|
res.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", start, end, fileSize))
|
|
res.Header().Set("Content-Length", strconv.FormatInt(end-start+1, 10))
|
|
res.WriteHeader(http.StatusPartialContent)
|
|
buffer := make([]byte, 102400)
|
|
file.Seek(start, 0)
|
|
for current := start; current <= end; {
|
|
readSize := int64(len(buffer))
|
|
if end-current+1 < readSize {
|
|
readSize = end - current + 1
|
|
}
|
|
|
|
n, err := file.Read(buffer[:readSize])
|
|
if err != nil {
|
|
break
|
|
}
|
|
|
|
res.Write(buffer[:n])
|
|
current += int64(n)
|
|
}
|
|
}
|
|
|
|
// App struct
|
|
type App struct {
|
|
ctx context.Context
|
|
infoList *wechat.WeChatInfoList
|
|
provider *wechat.WechatDataProvider
|
|
defaultUser string
|
|
users []string
|
|
firstStart bool
|
|
firstInit bool
|
|
FLoader *FileLoader
|
|
}
|
|
|
|
type WeChatInfo struct {
|
|
ProcessID uint32 `json:"PID"`
|
|
FilePath string `json:"FilePath"`
|
|
AcountName string `json:"AcountName"`
|
|
Version string `json:"Version"`
|
|
Is64Bits bool `json:"Is64Bits"`
|
|
DBKey string `json:"DBkey"`
|
|
}
|
|
|
|
type WeChatInfoList struct {
|
|
Info []WeChatInfo `json:"Info"`
|
|
Total int `json:"Total"`
|
|
}
|
|
|
|
type WeChatAccountInfos struct {
|
|
CurrentAccount string `json:"CurrentAccount"`
|
|
Info []wechat.WeChatAccountInfo `json:"Info"`
|
|
Total int `json:"Total"`
|
|
}
|
|
|
|
type ErrorMessage struct {
|
|
ErrorStr string `json:"error"`
|
|
}
|
|
|
|
// NewApp creates a new App application struct
|
|
func NewApp() *App {
|
|
a := &App{}
|
|
log.Println("App version:", appVersion)
|
|
a.firstInit = true
|
|
a.FLoader = NewFileLoader(".\\")
|
|
viper.SetConfigName(defaultConfig)
|
|
viper.SetConfigType("json")
|
|
viper.AddConfigPath(".")
|
|
if err := viper.ReadInConfig(); err == nil {
|
|
a.defaultUser = viper.GetString(configDefaultUserKey)
|
|
a.users = viper.GetStringSlice(configUsersKey)
|
|
prefix := viper.GetString(configExportPathKey)
|
|
if prefix != "" {
|
|
log.Println("SetFilePrefix", prefix)
|
|
a.FLoader.SetFilePrefix(prefix)
|
|
}
|
|
} else {
|
|
log.Println("not config exist")
|
|
}
|
|
log.Printf("default: %s users: %v\n", a.defaultUser, a.users)
|
|
if len(a.users) == 0 {
|
|
a.firstStart = true
|
|
}
|
|
|
|
return a
|
|
}
|
|
|
|
// startup is called when the app starts. The context is saved
|
|
// so we can call the runtime methods
|
|
func (a *App) startup(ctx context.Context) {
|
|
a.ctx = ctx
|
|
}
|
|
|
|
func (a *App) beforeClose(ctx context.Context) (prevent bool) {
|
|
return false
|
|
}
|
|
|
|
func (a *App) shutdown(ctx context.Context) {
|
|
if a.provider != nil {
|
|
a.provider.WechatWechatDataProviderClose()
|
|
a.provider = nil
|
|
}
|
|
log.Printf("App Version %s exit!", appVersion)
|
|
}
|
|
|
|
func (a *App) GetWeChatAllInfo() string {
|
|
infoList := WeChatInfoList{}
|
|
infoList.Info = make([]WeChatInfo, 0)
|
|
infoList.Total = 0
|
|
|
|
if a.provider != nil {
|
|
a.provider.WechatWechatDataProviderClose()
|
|
a.provider = nil
|
|
}
|
|
|
|
a.infoList = wechat.GetWeChatAllInfo()
|
|
for i := range a.infoList.Info {
|
|
var info WeChatInfo
|
|
info.ProcessID = a.infoList.Info[i].ProcessID
|
|
info.FilePath = a.infoList.Info[i].FilePath
|
|
info.AcountName = a.infoList.Info[i].AcountName
|
|
info.Version = a.infoList.Info[i].Version
|
|
info.Is64Bits = a.infoList.Info[i].Is64Bits
|
|
info.DBKey = a.infoList.Info[i].DBKey
|
|
infoList.Info = append(infoList.Info, info)
|
|
infoList.Total += 1
|
|
log.Printf("ProcessID %d, FilePath %s, AcountName %s, Version %s, Is64Bits %t", info.ProcessID, info.FilePath, info.AcountName, info.Version, info.Is64Bits)
|
|
}
|
|
infoStr, _ := json.Marshal(infoList)
|
|
// log.Println(string(infoStr))
|
|
|
|
return string(infoStr)
|
|
}
|
|
|
|
func (a *App) ExportWeChatAllData(full bool, acountName string) {
|
|
|
|
if a.provider != nil {
|
|
a.provider.WechatWechatDataProviderClose()
|
|
a.provider = nil
|
|
}
|
|
|
|
progress := make(chan string)
|
|
go func() {
|
|
var pInfo *wechat.WeChatInfo
|
|
for i := range a.infoList.Info {
|
|
if a.infoList.Info[i].AcountName == acountName {
|
|
pInfo = &a.infoList.Info[i]
|
|
break
|
|
}
|
|
}
|
|
|
|
if pInfo == nil {
|
|
close(progress)
|
|
runtime.EventsEmit(a.ctx, "exportData", fmt.Sprintf("{\"status\":\"error\", \"result\":\"%s error\"}", acountName))
|
|
return
|
|
}
|
|
|
|
prefixExportPath := a.FLoader.FilePrefix + "\\User\\"
|
|
_, err := os.Stat(prefixExportPath)
|
|
if err != nil {
|
|
os.Mkdir(prefixExportPath, os.ModeDir)
|
|
}
|
|
|
|
expPath := prefixExportPath + pInfo.AcountName
|
|
_, err = os.Stat(expPath)
|
|
if err == nil {
|
|
if !full {
|
|
os.RemoveAll(expPath + "\\Msg")
|
|
} else {
|
|
os.RemoveAll(expPath)
|
|
}
|
|
}
|
|
|
|
_, err = os.Stat(expPath)
|
|
if err != nil {
|
|
os.Mkdir(expPath, os.ModeDir)
|
|
}
|
|
|
|
go wechat.ExportWeChatAllData(*pInfo, expPath, progress)
|
|
|
|
for p := range progress {
|
|
log.Println(p)
|
|
runtime.EventsEmit(a.ctx, "exportData", p)
|
|
}
|
|
|
|
a.defaultUser = pInfo.AcountName
|
|
hasUser := false
|
|
for _, user := range a.users {
|
|
if user == pInfo.AcountName {
|
|
hasUser = true
|
|
break
|
|
}
|
|
}
|
|
if !hasUser {
|
|
a.users = append(a.users, pInfo.AcountName)
|
|
}
|
|
a.setCurrentConfig()
|
|
}()
|
|
}
|
|
|
|
func (a *App) createWechatDataProvider(resPath string, prefix string) error {
|
|
if a.provider != nil && a.provider.SelfInfo != nil && filepath.Base(resPath) == a.provider.SelfInfo.UserName {
|
|
log.Println("WechatDataProvider not need create:", a.provider.SelfInfo.UserName)
|
|
return nil
|
|
}
|
|
|
|
if a.provider != nil {
|
|
a.provider.WechatWechatDataProviderClose()
|
|
a.provider = nil
|
|
log.Println("createWechatDataProvider WechatWechatDataProviderClose")
|
|
}
|
|
|
|
provider, err := wechat.CreateWechatDataProvider(resPath, prefix)
|
|
if err != nil {
|
|
log.Println("CreateWechatDataProvider failed:", resPath)
|
|
return err
|
|
}
|
|
|
|
a.provider = provider
|
|
// infoJson, _ := json.Marshal(a.provider.SelfInfo)
|
|
// runtime.EventsEmit(a.ctx, "selfInfo", string(infoJson))
|
|
return nil
|
|
}
|
|
|
|
func (a *App) WeChatInit() {
|
|
|
|
if a.firstInit {
|
|
a.firstInit = false
|
|
a.scanAccountByPath(a.FLoader.FilePrefix)
|
|
log.Println("scanAccountByPath:", a.FLoader.FilePrefix)
|
|
}
|
|
|
|
if len(a.defaultUser) == 0 {
|
|
log.Println("not defaultUser")
|
|
return
|
|
}
|
|
|
|
expPath := a.FLoader.FilePrefix + "\\User\\" + a.defaultUser
|
|
prefixPath := "\\User\\" + a.defaultUser
|
|
wechat.ExportWeChatHeadImage(expPath)
|
|
if a.createWechatDataProvider(expPath, prefixPath) == nil {
|
|
infoJson, _ := json.Marshal(a.provider.SelfInfo)
|
|
runtime.EventsEmit(a.ctx, "selfInfo", string(infoJson))
|
|
}
|
|
}
|
|
|
|
func (a *App) GetWechatSessionList(pageIndex int, pageSize int) string {
|
|
if a.provider == nil {
|
|
log.Println("provider not init")
|
|
return "{\"Total\":0}"
|
|
}
|
|
log.Printf("pageIndex: %d\n", pageIndex)
|
|
list, err := a.provider.WeChatGetSessionList(pageIndex, pageSize)
|
|
if err != nil {
|
|
return "{\"Total\":0}"
|
|
}
|
|
|
|
listStr, _ := json.Marshal(list)
|
|
log.Println("GetWechatSessionList:", list.Total)
|
|
return string(listStr)
|
|
}
|
|
|
|
func (a *App) GetWechatContactList(pageIndex int, pageSize int) string {
|
|
if a.provider == nil {
|
|
log.Println("provider not init")
|
|
return "{\"Total\":0}"
|
|
}
|
|
log.Printf("pageIndex: %d\n", pageIndex)
|
|
list, err := a.provider.WeChatGetContactList(pageIndex, pageSize)
|
|
if err != nil {
|
|
return "{\"Total\":0}"
|
|
}
|
|
|
|
listStr, _ := json.Marshal(list)
|
|
log.Println("WeChatGetContactList:", list.Total)
|
|
return string(listStr)
|
|
}
|
|
|
|
func (a *App) GetWechatMessageListByTime(userName string, time int64, pageSize int, direction string) string {
|
|
log.Println("GetWechatMessageListByTime:", userName, pageSize, time, direction)
|
|
if len(userName) == 0 {
|
|
return "{\"Total\":0, \"Rows\":[]}"
|
|
}
|
|
dire := wechat.Message_Search_Forward
|
|
if direction == "backward" {
|
|
dire = wechat.Message_Search_Backward
|
|
} else if direction == "both" {
|
|
dire = wechat.Message_Search_Both
|
|
}
|
|
list, err := a.provider.WeChatGetMessageListByTime(userName, time, pageSize, dire)
|
|
if err != nil {
|
|
log.Println("GetWechatMessageListByTime failed:", err)
|
|
return ""
|
|
}
|
|
listStr, _ := json.Marshal(list)
|
|
log.Println("GetWechatMessageListByTime:", list.Total)
|
|
|
|
return string(listStr)
|
|
}
|
|
|
|
func (a *App) GetWechatMessageListByType(userName string, time int64, pageSize int, msgType string, direction string) string {
|
|
log.Println("GetWechatMessageListByType:", userName, pageSize, time, msgType, direction)
|
|
if len(userName) == 0 {
|
|
return "{\"Total\":0, \"Rows\":[]}"
|
|
}
|
|
dire := wechat.Message_Search_Forward
|
|
if direction == "backward" {
|
|
dire = wechat.Message_Search_Backward
|
|
} else if direction == "both" {
|
|
dire = wechat.Message_Search_Both
|
|
}
|
|
list, err := a.provider.WeChatGetMessageListByType(userName, time, pageSize, msgType, dire)
|
|
if err != nil {
|
|
log.Println("WeChatGetMessageListByType failed:", err)
|
|
return ""
|
|
}
|
|
listStr, _ := json.Marshal(list)
|
|
log.Println("WeChatGetMessageListByType:", list.Total)
|
|
|
|
return string(listStr)
|
|
}
|
|
|
|
func (a *App) GetWechatMessageListByKeyWord(userName string, time int64, keyword string, msgType string, pageSize int) string {
|
|
log.Println("GetWechatMessageListByKeyWord:", userName, pageSize, time, msgType)
|
|
if len(userName) == 0 {
|
|
return "{\"Total\":0, \"Rows\":[]}"
|
|
}
|
|
list, err := a.provider.WeChatGetMessageListByKeyWord(userName, time, keyword, msgType, pageSize)
|
|
if err != nil {
|
|
log.Println("WeChatGetMessageListByKeyWord failed:", err)
|
|
return ""
|
|
}
|
|
listStr, _ := json.Marshal(list)
|
|
log.Println("WeChatGetMessageListByKeyWord:", list.Total, list.KeyWord)
|
|
|
|
return string(listStr)
|
|
}
|
|
|
|
func (a *App) GetWechatMessageDate(userName string) string {
|
|
log.Println("GetWechatMessageDate:", userName)
|
|
if len(userName) == 0 {
|
|
return "{\"Total\":0, \"Date\":[]}"
|
|
}
|
|
|
|
messageData, err := a.provider.WeChatGetMessageDate(userName)
|
|
if err != nil {
|
|
log.Println("GetWechatMessageDate:", err)
|
|
return ""
|
|
}
|
|
|
|
messageDataStr, _ := json.Marshal(messageData)
|
|
log.Println("GetWechatMessageDate:", messageData.Total)
|
|
|
|
return string(messageDataStr)
|
|
}
|
|
|
|
func (a *App) setCurrentConfig() {
|
|
viper.Set(configDefaultUserKey, a.defaultUser)
|
|
viper.Set(configUsersKey, a.users)
|
|
viper.Set(configExportPathKey, a.FLoader.FilePrefix)
|
|
err := viper.SafeWriteConfig()
|
|
if err != nil {
|
|
log.Println(err)
|
|
err = viper.WriteConfig()
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
type userList struct {
|
|
Users []string `json:"Users"`
|
|
}
|
|
|
|
func (a *App) GetWeChatUserList() string {
|
|
|
|
l := userList{}
|
|
l.Users = a.users
|
|
|
|
usersStr, _ := json.Marshal(l)
|
|
str := string(usersStr)
|
|
log.Println("users:", str)
|
|
return str
|
|
}
|
|
|
|
func (a *App) OpenFileOrExplorer(filePath string, explorer bool) string {
|
|
// if root, err := os.Getwd(); err == nil {
|
|
// filePath = root + filePath[1:]
|
|
// }
|
|
// log.Println("OpenFileOrExplorer:", filePath)
|
|
|
|
path := a.FLoader.FilePrefix + filePath
|
|
err := utils.OpenFileOrExplorer(path, explorer)
|
|
if err != nil {
|
|
return "{\"result\": \"OpenFileOrExplorer failed\", \"status\":\"failed\"}"
|
|
}
|
|
|
|
return fmt.Sprintf("{\"result\": \"%s\", \"status\":\"OK\"}", "")
|
|
}
|
|
|
|
func (a *App) GetWeChatRoomUserList(roomId string) string {
|
|
userlist, err := a.provider.WeChatGetChatRoomUserList(roomId)
|
|
if err != nil {
|
|
log.Println("WeChatGetChatRoomUserList:", err)
|
|
return ""
|
|
}
|
|
|
|
userListStr, _ := json.Marshal(userlist)
|
|
|
|
return string(userListStr)
|
|
}
|
|
|
|
func (a *App) GetAppVersion() string {
|
|
return appVersion
|
|
}
|
|
|
|
func (a *App) GetAppIsFirstStart() bool {
|
|
defer func() { a.firstStart = false }()
|
|
return a.firstStart
|
|
}
|
|
|
|
func (a *App) GetWechatLocalAccountInfo() string {
|
|
infos := WeChatAccountInfos{}
|
|
infos.Info = make([]wechat.WeChatAccountInfo, 0)
|
|
infos.Total = 0
|
|
infos.CurrentAccount = a.defaultUser
|
|
for i := range a.users {
|
|
resPath := a.FLoader.FilePrefix + "\\User\\" + a.users[i]
|
|
if _, err := os.Stat(resPath); err != nil {
|
|
log.Println("GetWechatLocalAccountInfo:", resPath, err)
|
|
continue
|
|
}
|
|
|
|
prefixResPath := "\\User\\" + a.users[i]
|
|
info, err := wechat.WechatGetAccountInfo(resPath, prefixResPath, a.users[i])
|
|
if err != nil {
|
|
log.Println("GetWechatLocalAccountInfo", err)
|
|
continue
|
|
}
|
|
|
|
infos.Info = append(infos.Info, *info)
|
|
infos.Total += 1
|
|
}
|
|
|
|
infoString, _ := json.Marshal(infos)
|
|
log.Println(string(infoString))
|
|
|
|
return string(infoString)
|
|
}
|
|
|
|
func (a *App) WechatSwitchAccount(account string) bool {
|
|
for i := range a.users {
|
|
if a.users[i] == account {
|
|
if a.provider != nil {
|
|
a.provider.WechatWechatDataProviderClose()
|
|
a.provider = nil
|
|
}
|
|
a.defaultUser = account
|
|
a.setCurrentConfig()
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (a *App) GetExportPathStat() string {
|
|
path := a.FLoader.FilePrefix
|
|
log.Println("utils.GetPathStat ++")
|
|
stat, err := utils.GetPathStat(path)
|
|
log.Println("utils.GetPathStat --")
|
|
if err != nil {
|
|
log.Println("GetPathStat error:", path, err)
|
|
var msg ErrorMessage
|
|
msg.ErrorStr = fmt.Sprintf("%s:%v", path, err)
|
|
msgStr, _ := json.Marshal(msg)
|
|
return string(msgStr)
|
|
}
|
|
|
|
statString, _ := json.Marshal(stat)
|
|
|
|
return string(statString)
|
|
}
|
|
|
|
func (a *App) ExportPathIsCanWrite() bool {
|
|
path := a.FLoader.FilePrefix
|
|
return utils.PathIsCanWriteFile(path)
|
|
}
|
|
|
|
func (a *App) OpenExportPath() {
|
|
path := a.FLoader.FilePrefix
|
|
runtime.BrowserOpenURL(a.ctx, path)
|
|
}
|
|
|
|
func (a *App) OpenDirectoryDialog() string {
|
|
dialogOptions := runtime.OpenDialogOptions{
|
|
Title: "选择导出路径",
|
|
}
|
|
selectedDir, err := runtime.OpenDirectoryDialog(a.ctx, dialogOptions)
|
|
if err != nil {
|
|
log.Println("OpenDirectoryDialog:", err)
|
|
return ""
|
|
}
|
|
|
|
if selectedDir == "" {
|
|
log.Println("Cancel selectedDir")
|
|
return ""
|
|
}
|
|
|
|
if selectedDir == a.FLoader.FilePrefix {
|
|
log.Println("same path No need SetFilePrefix")
|
|
return ""
|
|
}
|
|
|
|
if !utils.PathIsCanWriteFile(selectedDir) {
|
|
log.Println("PathIsCanWriteFile:", selectedDir, "error")
|
|
return ""
|
|
}
|
|
|
|
a.FLoader.SetFilePrefix(selectedDir)
|
|
log.Println("OpenDirectoryDialog:", selectedDir)
|
|
a.scanAccountByPath(selectedDir)
|
|
return selectedDir
|
|
}
|
|
|
|
func (a *App) scanAccountByPath(path string) error {
|
|
infos := WeChatAccountInfos{}
|
|
infos.Info = make([]wechat.WeChatAccountInfo, 0)
|
|
infos.Total = 0
|
|
infos.CurrentAccount = ""
|
|
|
|
userPath := path + "\\User\\"
|
|
if _, err := os.Stat(userPath); err != nil {
|
|
return err
|
|
}
|
|
|
|
dirs, err := os.ReadDir(userPath)
|
|
if err != nil {
|
|
log.Println("ReadDir", err)
|
|
return err
|
|
}
|
|
|
|
for i := range dirs {
|
|
if !dirs[i].Type().IsDir() {
|
|
continue
|
|
}
|
|
log.Println("dirs[i].Name():", dirs[i].Name())
|
|
resPath := path + "\\User\\" + dirs[i].Name()
|
|
prefixResPath := "\\User\\" + dirs[i].Name()
|
|
info, err := wechat.WechatGetAccountInfo(resPath, prefixResPath, dirs[i].Name())
|
|
if err != nil {
|
|
log.Println("GetWechatLocalAccountInfo", err)
|
|
continue
|
|
}
|
|
|
|
infos.Info = append(infos.Info, *info)
|
|
infos.Total += 1
|
|
}
|
|
|
|
users := make([]string, 0)
|
|
for i := 0; i < infos.Total; i++ {
|
|
users = append(users, infos.Info[i].AccountName)
|
|
}
|
|
|
|
a.users = users
|
|
found := false
|
|
for i := range a.users {
|
|
if a.defaultUser == a.users[i] {
|
|
found = true
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
a.defaultUser = ""
|
|
}
|
|
if a.defaultUser == "" && len(a.users) > 0 {
|
|
a.defaultUser = a.users[0]
|
|
}
|
|
|
|
if len(a.users) > 0 {
|
|
a.setCurrentConfig()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (a *App) OepnLogFileExplorer() {
|
|
utils.OpenFileOrExplorer(".\\app.log", true)
|
|
}
|
|
|
|
func (a *App) SaveFileDialog(file string, alisa string) string {
|
|
filePath := a.FLoader.FilePrefix + file
|
|
if _, err := os.Stat(filePath); err != nil {
|
|
log.Println("SaveFileDialog:", err)
|
|
return err.Error()
|
|
}
|
|
|
|
savePath, err := runtime.SaveFileDialog(a.ctx, runtime.SaveDialogOptions{
|
|
DefaultFilename: alisa,
|
|
Title: "选择保存路径",
|
|
})
|
|
if err != nil {
|
|
log.Println("SaveFileDialog:", err)
|
|
return err.Error()
|
|
}
|
|
|
|
if savePath == "" {
|
|
return ""
|
|
}
|
|
|
|
dirPath := filepath.Dir(savePath)
|
|
if !utils.PathIsCanWriteFile(dirPath) {
|
|
errStr := "Path Is Can't Write File: " + filepath.Dir(savePath)
|
|
log.Println(errStr)
|
|
return errStr
|
|
}
|
|
|
|
_, err = utils.CopyFile(filePath, savePath)
|
|
if err != nil {
|
|
log.Println("Error CopyFile", filePath, savePath, err)
|
|
return err.Error()
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func (a *App) GetSessionLastTime(userName string) string {
|
|
if a.provider == nil || userName == "" {
|
|
lastTime := &wechat.WeChatLastTime{}
|
|
lastTimeString, _ := json.Marshal(lastTime)
|
|
return string(lastTimeString)
|
|
}
|
|
|
|
lastTime := a.provider.WeChatGetSessionLastTime(userName)
|
|
|
|
lastTimeString, _ := json.Marshal(lastTime)
|
|
|
|
return string(lastTimeString)
|
|
}
|
|
|
|
func (a *App) SetSessionLastTime(userName string, stamp int64, messageId string) string {
|
|
if a.provider == nil {
|
|
return ""
|
|
}
|
|
|
|
lastTime := &wechat.WeChatLastTime{
|
|
UserName: userName,
|
|
Timestamp: stamp,
|
|
MessageId: messageId,
|
|
}
|
|
err := a.provider.WeChatSetSessionLastTime(lastTime)
|
|
if err != nil {
|
|
log.Println("WeChatSetSessionLastTime failed:", err.Error())
|
|
return err.Error()
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func (a *App) SetSessionBookMask(userName, tag, info string) string {
|
|
if a.provider == nil || userName == "" {
|
|
return "invaild params"
|
|
}
|
|
err := a.provider.WeChatSetSessionBookMask(userName, tag, info)
|
|
if err != nil {
|
|
log.Println("WeChatSetSessionBookMask failed:", err.Error())
|
|
return err.Error()
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func (a *App) DelSessionBookMask(markId string) string {
|
|
if a.provider == nil || markId == "" {
|
|
return "invaild params"
|
|
}
|
|
|
|
err := a.provider.WeChatDelSessionBookMask(markId)
|
|
if err != nil {
|
|
log.Println("WeChatDelSessionBookMask failed:", err.Error())
|
|
return err.Error()
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func (a *App) GetSessionBookMaskList(userName string) string {
|
|
if a.provider == nil || userName == "" {
|
|
return "invaild params"
|
|
}
|
|
markLIst, err := a.provider.WeChatGetSessionBookMaskList(userName)
|
|
if err != nil {
|
|
log.Println("WeChatGetSessionBookMaskList failed:", err.Error())
|
|
_list := &wechat.WeChatBookMarkList{}
|
|
_listString, _ := json.Marshal(_list)
|
|
return string(_listString)
|
|
}
|
|
|
|
markLIstString, _ := json.Marshal(markLIst)
|
|
return string(markLIstString)
|
|
}
|
|
|
|
func (a *App) SelectedDirDialog(title string) string {
|
|
dialogOptions := runtime.OpenDialogOptions{
|
|
Title: title,
|
|
}
|
|
selectedDir, err := runtime.OpenDirectoryDialog(a.ctx, dialogOptions)
|
|
if err != nil {
|
|
log.Println("OpenDirectoryDialog:", err)
|
|
return ""
|
|
}
|
|
|
|
if selectedDir == "" {
|
|
return ""
|
|
}
|
|
|
|
return selectedDir
|
|
}
|
|
|
|
func (a *App) ExportWeChatDataByUserName(userName, path string) string {
|
|
if a.provider == nil || userName == "" || path == "" {
|
|
return "invaild params" + userName
|
|
}
|
|
|
|
if !utils.PathIsCanWriteFile(path) {
|
|
log.Println("PathIsCanWriteFile: " + path)
|
|
return "PathIsCanWriteFile: " + path
|
|
}
|
|
|
|
exPath := path + "\\" + "wechatDataBackup_" + userName
|
|
if _, err := os.Stat(exPath); err != nil {
|
|
os.MkdirAll(exPath, os.ModePerm)
|
|
} else {
|
|
return "path exist:" + exPath
|
|
}
|
|
|
|
log.Println("ExportWeChatDataByUserName:", userName, exPath)
|
|
err := a.provider.WeChatExportDataByUserName(userName, exPath)
|
|
if err != nil {
|
|
log.Println("WeChatExportDataByUserName failed:", err)
|
|
return "WeChatExportDataByUserName failed:" + err.Error()
|
|
}
|
|
|
|
config := map[string]interface{}{
|
|
"exportpath": ".\\",
|
|
"userconfig": map[string]interface{}{
|
|
"defaultuser": a.defaultUser,
|
|
"users": []string{a.defaultUser},
|
|
},
|
|
}
|
|
|
|
configJson, err := json.MarshalIndent(config, "", " ")
|
|
if err != nil {
|
|
log.Println("MarshalIndent:", err)
|
|
return "MarshalIndent:" + err.Error()
|
|
}
|
|
|
|
configPath := exPath + "\\" + "config.json"
|
|
err = os.WriteFile(configPath, configJson, os.ModePerm)
|
|
if err != nil {
|
|
log.Println("WriteFile:", err)
|
|
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 ""
|
|
}
|
|
|
|
func (a *App) GetAppIsShareData() bool {
|
|
if a.provider != nil {
|
|
return a.provider.IsShareData
|
|
}
|
|
return false
|
|
}
|