1. 增加首次使用的引导功能

2. 增加多开微信可选择导出功能
3. 增加多账号数据可以切换查看功能
This commit is contained in:
HAL 2024-09-23 02:29:19 +08:00
parent e6d8ab9de9
commit 073d586aea
7 changed files with 784 additions and 101 deletions

142
app.go
View File

@ -18,16 +18,17 @@ const (
defaultConfig = "config" defaultConfig = "config"
configDefaultUserKey = "userConfig.defaultUser" configDefaultUserKey = "userConfig.defaultUser"
configUsersKey = "userConfig.users" configUsersKey = "userConfig.users"
appVersion = "v1.0.2" appVersion = "v1.0.3"
) )
// App struct // App struct
type App struct { type App struct {
ctx context.Context ctx context.Context
info wechat.WeChatInfo infoList *wechat.WeChatInfoList
provider *wechat.WechatDataProvider provider *wechat.WechatDataProvider
defaultUser string defaultUser string
users []string users []string
firstStart bool
} }
type WeChatInfo struct { type WeChatInfo struct {
@ -39,6 +40,17 @@ type WeChatInfo struct {
DBKey string `json:"DBkey"` 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"`
}
// NewApp creates a new App application struct // NewApp creates a new App application struct
func NewApp() *App { func NewApp() *App {
a := &App{} a := &App{}
@ -52,6 +64,7 @@ func NewApp() *App {
// log.Println(a.defaultUser) // log.Println(a.defaultUser)
// log.Println(a.users) // log.Println(a.users)
} else { } else {
a.firstStart = true
log.Println("not config exist") log.Println("not config exist")
} }
@ -65,39 +78,41 @@ func (a *App) startup(ctx context.Context) {
} }
func (a *App) beforeClose(ctx context.Context) (prevent bool) { func (a *App) beforeClose(ctx context.Context) (prevent bool) {
dialog, err := runtime.MessageDialog(ctx, runtime.MessageDialogOptions{
Type: runtime.QuestionDialog,
Title: "Quit?",
Message: "Are you sure you want to quit?",
})
if err != nil || dialog == "Yes" { if a.provider != nil {
a.provider.WechatWechatDataProviderClose() a.provider.WechatWechatDataProviderClose()
a.provider = nil a.provider = nil
return false
} }
return true return false
} }
func (a *App) GetWeChatAllInfo() string { func (a *App) GetWeChatAllInfo() string {
a.info, _ = wechat.GetWeChatAllInfo() infoList := WeChatInfoList{}
infoList.Info = make([]WeChatInfo, 0)
infoList.Total = 0
a.infoList = wechat.GetWeChatAllInfo()
for i := range a.infoList.Info {
var info WeChatInfo var info WeChatInfo
info.ProcessID = a.info.ProcessID info.ProcessID = a.infoList.Info[i].ProcessID
info.FilePath = a.info.FilePath info.FilePath = a.infoList.Info[i].FilePath
info.AcountName = a.info.AcountName info.AcountName = a.infoList.Info[i].AcountName
info.Version = a.info.Version info.Version = a.infoList.Info[i].Version
info.Is64Bits = a.info.Is64Bits info.Is64Bits = a.infoList.Info[i].Is64Bits
info.DBKey = a.info.DBKey info.DBKey = a.infoList.Info[i].DBKey
infoList.Info = append(infoList.Info, info)
infoStr, _ := json.Marshal(info) infoList.Total += 1
log.Println(string(infoStr)) 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) return string(infoStr)
} }
func (a *App) ExportWeChatAllData(full bool) { func (a *App) ExportWeChatAllData(full bool, acountName string) {
if a.provider != nil { if a.provider != nil {
a.provider.WechatWechatDataProviderClose() a.provider.WechatWechatDataProviderClose()
@ -106,13 +121,26 @@ func (a *App) ExportWeChatAllData(full bool) {
progress := make(chan string) progress := make(chan string)
go func() { 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
}
_, err := os.Stat(".\\User") _, err := os.Stat(".\\User")
if err != nil { if err != nil {
os.Mkdir(".\\User", os.ModeDir) os.Mkdir(".\\User", os.ModeDir)
} }
expPath := ".\\User\\" + a.info.AcountName expPath := ".\\User\\" + pInfo.AcountName
_, err = os.Stat(expPath) _, err = os.Stat(expPath)
if err == nil { if err == nil {
if !full { if !full {
@ -127,26 +155,23 @@ func (a *App) ExportWeChatAllData(full bool) {
os.Mkdir(expPath, os.ModeDir) os.Mkdir(expPath, os.ModeDir)
} }
go wechat.ExportWeChatAllData(a.info, expPath, progress) go wechat.ExportWeChatAllData(*pInfo, expPath, progress)
for p := range progress { for p := range progress {
log.Println(p) log.Println(p)
runtime.EventsEmit(a.ctx, "exportData", p) runtime.EventsEmit(a.ctx, "exportData", p)
} }
if len(a.defaultUser) == 0 { a.defaultUser = pInfo.AcountName
a.defaultUser = a.info.AcountName
}
hasUser := false hasUser := false
for _, user := range a.users { for _, user := range a.users {
if user == a.info.AcountName { if user == pInfo.AcountName {
hasUser = true hasUser = true
break break
} }
} }
if !hasUser { if !hasUser {
a.users = append(a.users, a.info.AcountName) a.users = append(a.users, pInfo.AcountName)
} }
a.setCurrentConfig() a.setCurrentConfig()
}() }()
@ -158,6 +183,12 @@ func (a *App) createWechatDataProvider(resPath string) error {
return nil return nil
} }
if a.provider != nil {
a.provider.WechatWechatDataProviderClose()
a.provider = nil
log.Println("createWechatDataProvider WechatWechatDataProviderClose")
}
provider, err := wechat.CreateWechatDataProvider(resPath) provider, err := wechat.CreateWechatDataProvider(resPath)
if err != nil { if err != nil {
log.Println("CreateWechatDataProvider failed:", resPath) log.Println("CreateWechatDataProvider failed:", resPath)
@ -256,6 +287,10 @@ func (a *App) setCurrentConfig() {
err := viper.SafeWriteConfig() err := viper.SafeWriteConfig()
if err != nil { if err != nil {
log.Println(err) log.Println(err)
err = viper.WriteConfig()
if err != nil {
log.Println(err)
}
} }
} }
@ -302,3 +337,52 @@ func (a *App) GetWeChatRoomUserList(roomId string) string {
func (a *App) GetAppVersion() string { func (a *App) GetAppVersion() string {
return appVersion 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 := ".\\User\\" + a.users[i]
if _, err := os.Stat(resPath); err != nil {
log.Println("GetWechatLocalAccountInfo:", resPath, err)
continue
}
info, err := wechat.WechatGetAccountInfo(resPath, 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
}

View File

@ -1,3 +1,8 @@
## v1.0.3
1. 增加首次使用的引导功能
2. 增加多开微信可选择导出功能
3. 增加多账号数据可以切换查看功能
## v1.0.2 ## v1.0.2
1. 对话列表按照导出时微信显示顺序显示 1. 对话列表按照导出时微信显示顺序显示
2. 增加版本更新检测按钮 2. 增加版本更新检测按钮

503
frontend/dist/assets/index.425764f5.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,8 +4,8 @@
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/> <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>wechatDataBackup</title> <title>wechatDataBackup</title>
<script type="module" crossorigin src="/assets/index.c5ad2349.js"></script> <script type="module" crossorigin src="/assets/index.425764f5.js"></script>
<link rel="stylesheet" href="/assets/index.abf5d552.css"> <link rel="stylesheet" href="/assets/index.b10575d2.css">
</head> </head>
<body > <body >
<div id="root"></div> <div id="root"></div>

View File

@ -38,22 +38,25 @@ type WeChatInfo struct {
DBKey string DBKey string
} }
type WeChatInfoList struct {
Info []WeChatInfo `json:"Info"`
Total int `json:"Total"`
}
type wechatMediaMSG struct { type wechatMediaMSG struct {
Key string Key string
MsgSvrID int MsgSvrID int
Buf []byte Buf []byte
} }
func GetWeChatAllInfo() (WeChatInfo, error) { func GetWeChatAllInfo() *WeChatInfoList {
info, err := GetWeChatInfo() list := GetWeChatInfo()
if err != nil {
log.Println("GetWeChatInfo:", err) for i := range list.Info {
return info, err list.Info[i].DBKey = GetWeChatKey(&list.Info[i])
} }
info.DBKey = GetWeChatKey(&info) return list
return info, nil
} }
func ExportWeChatAllData(info WeChatInfo, expPath string, progress chan<- string) { func ExportWeChatAllData(info WeChatInfo, expPath string, progress chan<- string) {
@ -98,6 +101,8 @@ func exportWeChatVoice(info WeChatInfo, expPath string, progress chan<- string)
} }
var wg sync.WaitGroup var wg sync.WaitGroup
var reportWg sync.WaitGroup
quitChan := make(chan struct{})
index = -1 index = -1
MSGChan := make(chan wechatMediaMSG, 100) MSGChan := make(chan wechatMediaMSG, 100)
go func() { go func() {
@ -156,22 +161,27 @@ func exportWeChatVoice(info WeChatInfo, expPath string, progress chan<- string)
}() }()
} }
wg.Add(1) reportWg.Add(1)
go func() { go func() {
defer wg.Done() defer reportWg.Done()
for { for {
if handleNumber >= fileNumber { select {
break case <-quitChan:
} log.Println("WeChat voice report progress end")
return
default:
filePercent := float64(handleNumber) / float64(fileNumber) filePercent := float64(handleNumber) / float64(fileNumber)
totalPercent := 61 + (filePercent * (100 - 61)) totalPercent := 61 + (filePercent * (100 - 61))
totalPercentStr := fmt.Sprintf("{\"status\":\"processing\", \"result\":\"export WeChat voice doing\", \"progress\": %d}", int(totalPercent)) totalPercentStr := fmt.Sprintf("{\"status\":\"processing\", \"result\":\"export WeChat voice doing\", \"progress\": %d}", int(totalPercent))
progress <- totalPercentStr progress <- totalPercentStr
time.Sleep(time.Second) time.Sleep(time.Second)
} }
}
}() }()
wg.Wait() wg.Wait()
close(quitChan)
reportWg.Wait()
progress <- "{\"status\":\"processing\", \"result\":\"export WeChat voice end\", \"progress\": 100}" progress <- "{\"status\":\"processing\", \"result\":\"export WeChat voice end\", \"progress\": 100}"
} }
@ -190,6 +200,8 @@ func exportWeChatVideoAndFile(info WeChatInfo, expPath string, progress chan<- s
log.Println("VideoAndFile ", fileNumber) log.Println("VideoAndFile ", fileNumber)
var wg sync.WaitGroup var wg sync.WaitGroup
var reportWg sync.WaitGroup
quitChan := make(chan struct{})
taskChan := make(chan [2]string, 100) taskChan := make(chan [2]string, 100)
go func() { go func() {
for _, rootPath := range rootPaths { for _, rootPath := range rootPaths {
@ -241,21 +253,26 @@ func exportWeChatVideoAndFile(info WeChatInfo, expPath string, progress chan<- s
} }
}() }()
} }
wg.Add(1) reportWg.Add(1)
go func() { go func() {
defer wg.Done() defer reportWg.Done()
for { for {
if handleNumber >= fileNumber { select {
break case <-quitChan:
} log.Println("WeChat Video and File report progress end")
return
default:
filePercent := float64(handleNumber) / float64(fileNumber) filePercent := float64(handleNumber) / float64(fileNumber)
totalPercent := 41 + (filePercent * (60 - 41)) totalPercent := 41 + (filePercent * (60 - 41))
totalPercentStr := fmt.Sprintf("{\"status\":\"processing\", \"result\":\"export WeChat Video and File doing\", \"progress\": %d}", int(totalPercent)) totalPercentStr := fmt.Sprintf("{\"status\":\"processing\", \"result\":\"export WeChat Video and File doing\", \"progress\": %d}", int(totalPercent))
progress <- totalPercentStr progress <- totalPercentStr
time.Sleep(time.Second) time.Sleep(time.Second)
} }
}
}() }()
wg.Wait() wg.Wait()
close(quitChan)
reportWg.Wait()
progress <- "{\"status\":\"processing\", \"result\":\"export WeChat Video and File end\", \"progress\": 60}" progress <- "{\"status\":\"processing\", \"result\":\"export WeChat Video and File end\", \"progress\": 60}"
} }
@ -271,6 +288,8 @@ func exportWeChatBat(info WeChatInfo, expPath string, progress chan<- string) {
handleNumber := int64(0) handleNumber := int64(0)
fileNumber := getPathFileNumber(datRootPath, ".dat") fileNumber := getPathFileNumber(datRootPath, ".dat")
var wg sync.WaitGroup var wg sync.WaitGroup
var reportWg sync.WaitGroup
quitChan := make(chan struct{})
taskChan := make(chan [2]string, 100) taskChan := make(chan [2]string, 100)
go func() { go func() {
err = filepath.Walk(datRootPath, func(path string, finfo os.FileInfo, err error) error { err = filepath.Walk(datRootPath, func(path string, finfo os.FileInfo, err error) error {
@ -320,22 +339,26 @@ func exportWeChatBat(info WeChatInfo, expPath string, progress chan<- string) {
} }
}() }()
} }
wg.Add(1) reportWg.Add(1)
go func() { go func() {
defer wg.Done() defer reportWg.Done()
for { for {
if handleNumber >= fileNumber { select {
break case <-quitChan:
} log.Println("WeChat Dat report progress end")
return
default:
filePercent := float64(handleNumber) / float64(fileNumber) filePercent := float64(handleNumber) / float64(fileNumber)
totalPercent := 21 + (filePercent * (40 - 21)) totalPercent := 21 + (filePercent * (40 - 21))
totalPercentStr := fmt.Sprintf("{\"status\":\"processing\", \"result\":\"export WeChat Dat doing\", \"progress\": %d}", int(totalPercent)) totalPercentStr := fmt.Sprintf("{\"status\":\"processing\", \"result\":\"export WeChat Dat doing\", \"progress\": %d}", int(totalPercent))
progress <- totalPercentStr progress <- totalPercentStr
time.Sleep(time.Second) time.Sleep(time.Second)
} }
}
}() }()
wg.Wait() wg.Wait()
close(quitChan)
reportWg.Wait()
progress <- "{\"status\":\"processing\", \"result\":\"export WeChat Dat end\", \"progress\": 40}" progress <- "{\"status\":\"processing\", \"result\":\"export WeChat Dat end\", \"progress\": 40}"
} }
@ -353,6 +376,8 @@ func exportWeChatDateBase(info WeChatInfo, expPath string, progress chan<- strin
handleNumber := int64(0) handleNumber := int64(0)
fileNumber := getPathFileNumber(info.FilePath+"\\Msg", ".db") fileNumber := getPathFileNumber(info.FilePath+"\\Msg", ".db")
var wg sync.WaitGroup var wg sync.WaitGroup
var reportWg sync.WaitGroup
quitChan := make(chan struct{})
taskChan := make(chan [2]string, 20) taskChan := make(chan [2]string, 20)
go func() { go func() {
err = filepath.Walk(info.FilePath+"\\Msg", func(path string, finfo os.FileInfo, err error) error { err = filepath.Walk(info.FilePath+"\\Msg", func(path string, finfo os.FileInfo, err error) error {
@ -399,49 +424,55 @@ func exportWeChatDateBase(info WeChatInfo, expPath string, progress chan<- strin
}() }()
} }
wg.Add(1) reportWg.Add(1)
go func() { go func() {
defer wg.Done() defer reportWg.Done()
for { for {
if handleNumber >= fileNumber { select {
break case <-quitChan:
} log.Println("WeChat DateBase report progress end")
return
default:
filePercent := float64(handleNumber) / float64(fileNumber) filePercent := float64(handleNumber) / float64(fileNumber)
totalPercent := 1 + (filePercent * (20 - 1)) totalPercent := 1 + (filePercent * (20 - 1))
totalPercentStr := fmt.Sprintf("{\"status\":\"processing\", \"result\":\"export WeChat DateBase doing\", \"progress\": %d}", int(totalPercent)) totalPercentStr := fmt.Sprintf("{\"status\":\"processing\", \"result\":\"export WeChat DateBase doing\", \"progress\": %d}", int(totalPercent))
progress <- totalPercentStr progress <- totalPercentStr
time.Sleep(time.Second) time.Sleep(time.Second)
} }
}
}() }()
wg.Wait() wg.Wait()
close(quitChan)
reportWg.Wait()
progress <- "{\"status\":\"processing\", \"result\":\"export WeChat DateBase end\", \"progress\": 20}" progress <- "{\"status\":\"processing\", \"result\":\"export WeChat DateBase end\", \"progress\": 20}"
return true return true
} }
func GetWeChatInfo() (info WeChatInfo, rerr error) { func GetWeChatInfo() (list *WeChatInfoList) {
info = WeChatInfo{} list = &WeChatInfoList{}
list.Info = make([]WeChatInfo, 0)
list.Total = 0
processes, err := process.Processes() processes, err := process.Processes()
if err != nil { if err != nil {
log.Println("Error getting processes:", err) log.Println("Error getting processes:", err)
rerr = err
return return
} }
found := false
for _, p := range processes { for _, p := range processes {
name, err := p.Name() name, err := p.Name()
if err != nil { if err != nil {
continue continue
} }
info := WeChatInfo{}
if name == "WeChat.exe" { if name == "WeChat.exe" {
found = true
info.ProcessID = uint32(p.Pid) info.ProcessID = uint32(p.Pid)
info.Is64Bits, _ = Is64BitProcess(info.ProcessID) info.Is64Bits, _ = Is64BitProcess(info.ProcessID)
log.Println("ProcessID", info.ProcessID) log.Println("ProcessID", info.ProcessID)
files, err := p.OpenFiles() files, err := p.OpenFiles()
if err != nil { if err != nil {
log.Println("OpenFiles failed") log.Println("OpenFiles failed")
return continue
} }
for _, f := range files { for _, f := range files {
@ -450,7 +481,8 @@ func GetWeChatInfo() (info WeChatInfo, rerr error) {
filePath := f.Path[4:] filePath := f.Path[4:]
parts := strings.Split(filePath, string(filepath.Separator)) parts := strings.Split(filePath, string(filepath.Separator))
if len(parts) < 4 { if len(parts) < 4 {
return info, errors.New("Error filePath " + filePath) log.Println("Error filePath " + filePath)
break
} }
info.FilePath = strings.Join(parts[:len(parts)-2], string(filepath.Separator)) info.FilePath = strings.Join(parts[:len(parts)-2], string(filepath.Separator))
info.AcountName = strings.Join(parts[len(parts)-3:len(parts)-2], string(filepath.Separator)) info.AcountName = strings.Join(parts[len(parts)-3:len(parts)-2], string(filepath.Separator))
@ -459,14 +491,14 @@ func GetWeChatInfo() (info WeChatInfo, rerr error) {
} }
if len(info.FilePath) == 0 { if len(info.FilePath) == 0 {
rerr = errors.New("wechat not log in") log.Println("wechat not log in")
return continue
} }
hModuleSnap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPMODULE|windows.TH32CS_SNAPMODULE32, uint32(p.Pid)) hModuleSnap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPMODULE|windows.TH32CS_SNAPMODULE32, uint32(p.Pid))
if err != nil { if err != nil {
log.Println("CreateToolhelp32Snapshot failed", err) log.Println("CreateToolhelp32Snapshot failed", err)
return continue
} }
defer windows.CloseHandle(hModuleSnap) defer windows.CloseHandle(hModuleSnap)
@ -476,7 +508,7 @@ func GetWeChatInfo() (info WeChatInfo, rerr error) {
err = windows.Module32First(hModuleSnap, &me32) err = windows.Module32First(hModuleSnap, &me32)
if err != nil { if err != nil {
log.Println("Module32First failed", err) log.Println("Module32First failed", err)
return continue
} }
for ; err == nil; err = windows.Module32Next(hModuleSnap, &me32) { for ; err == nil; err = windows.Module32Next(hModuleSnap, &me32) {
@ -493,19 +525,19 @@ func GetWeChatInfo() (info WeChatInfo, rerr error) {
infoSize, err := windows.GetFileVersionInfoSize(driverPath, &zero) infoSize, err := windows.GetFileVersionInfoSize(driverPath, &zero)
if err != nil { if err != nil {
log.Println("GetFileVersionInfoSize failed", err) log.Println("GetFileVersionInfoSize failed", err)
return break
} }
versionInfo := make([]byte, infoSize) versionInfo := make([]byte, infoSize)
if err = windows.GetFileVersionInfo(driverPath, 0, infoSize, unsafe.Pointer(&versionInfo[0])); err != nil { if err = windows.GetFileVersionInfo(driverPath, 0, infoSize, unsafe.Pointer(&versionInfo[0])); err != nil {
log.Println("GetFileVersionInfo failed", err) log.Println("GetFileVersionInfo failed", err)
return break
} }
var fixedInfo *windows.VS_FIXEDFILEINFO var fixedInfo *windows.VS_FIXEDFILEINFO
fixedInfoLen := uint32(unsafe.Sizeof(*fixedInfo)) fixedInfoLen := uint32(unsafe.Sizeof(*fixedInfo))
err = windows.VerQueryValue(unsafe.Pointer(&versionInfo[0]), `\`, (unsafe.Pointer)(&fixedInfo), &fixedInfoLen) err = windows.VerQueryValue(unsafe.Pointer(&versionInfo[0]), `\`, (unsafe.Pointer)(&fixedInfo), &fixedInfoLen)
if err != nil { if err != nil {
log.Println("VerQueryValue failed", err) log.Println("VerQueryValue failed", err)
return break
} }
// fmt.Printf("%s: v%d.%d.%d.%d\n", windows.UTF16ToString(me32.Module[:]), // fmt.Printf("%s: v%d.%d.%d.%d\n", windows.UTF16ToString(me32.Module[:]),
// (fixedInfo.FileVersionMS>>16)&0xff, // (fixedInfo.FileVersionMS>>16)&0xff,
@ -518,16 +550,13 @@ func GetWeChatInfo() (info WeChatInfo, rerr error) {
(fixedInfo.FileVersionMS>>0)&0xff, (fixedInfo.FileVersionMS>>0)&0xff,
(fixedInfo.FileVersionLS>>16)&0xff, (fixedInfo.FileVersionLS>>16)&0xff,
(fixedInfo.FileVersionLS>>0)&0xff) (fixedInfo.FileVersionLS>>0)&0xff)
list.Info = append(list.Info, info)
list.Total += 1
break break
} }
} }
} }
} }
if !found {
rerr = errors.New("not found process")
}
return return
} }
@ -567,7 +596,7 @@ func GetWeChatKey(info *WeChatInfo) string {
for { for {
index := hasDeviceSybmol(buffer[offset:]) index := hasDeviceSybmol(buffer[offset:])
if index == -1 { if index == -1 {
fmt.Println("hasDeviceSybmolxxxx") log.Println("hasDeviceSybmolxxxx")
break break
} }
fmt.Printf("hasDeviceSybmol: 0x%X\n", index) fmt.Printf("hasDeviceSybmol: 0x%X\n", index)
@ -638,7 +667,7 @@ func findDBkey(handle windows.Handle, path string, keys [][]byte) (string, error
if keyAddrPtr == 0x00 { if keyAddrPtr == 0x00 {
continue continue
} }
log.Println("keyAddrPtr: 0x%X\n", keyAddrPtr) log.Printf("keyAddrPtr: 0x%X\n", keyAddrPtr)
keyBuffer := make([]byte, 0x20) keyBuffer := make([]byte, 0x20)
err = windows.ReadProcessMemory(handle, uintptr(keyAddrPtr), &keyBuffer[0], uintptr(len(keyBuffer)), nil) err = windows.ReadProcessMemory(handle, uintptr(keyAddrPtr), &keyBuffer[0], uintptr(len(keyBuffer)), nil)
if err != nil { if err != nil {

View File

@ -144,6 +144,15 @@ type WeChatUserList struct {
Total int `json:"Total"` Total int `json:"Total"`
} }
type WeChatAccountInfo struct {
AccountName string `json:"AccountName"`
AliasName string `json:"AliasName"`
ReMarkName string `json:"ReMarkName"`
NickName string `json:"NickName"`
SmallHeadImgUrl string `json:"SmallHeadImgUrl"`
BigHeadImgUrl string `json:"BigHeadImgUrl"`
}
type wechatMsgDB struct { type wechatMsgDB struct {
path string path string
db *sql.DB db *sql.DB
@ -220,13 +229,19 @@ func CreateWechatDataProvider(resPath string) (*WechatDataProvider, error) {
func (P *WechatDataProvider) WechatWechatDataProviderClose() { func (P *WechatDataProvider) WechatWechatDataProviderClose() {
if P.microMsg != nil { if P.microMsg != nil {
P.microMsg.Close() err := P.microMsg.Close()
if err != nil {
log.Println("db close:", err)
}
} }
for _, db := range P.msgDBs { for _, db := range P.msgDBs {
db.db.Close() err := db.db.Close()
if err != nil {
log.Println("db close:", err)
} }
log.Println("WechatWechatDataProviderClose") }
log.Println("WechatWechatDataProviderClose:", P.resPath)
} }
func (P *WechatDataProvider) WechatGetUserInfoByName(name string) (*WeChatUserInfo, error) { func (P *WechatDataProvider) WechatGetUserInfoByName(name string) (*WeChatUserInfo, error) {
@ -876,3 +891,49 @@ func (P *WechatDataProvider) WechatGetUserInfoByNameOnCache(name string) (*WeCha
return pinfo, nil return pinfo, nil
} }
func WechatGetAccountInfo(resPath, accountName string) (*WeChatAccountInfo, error) {
MicroMsgDBPath := resPath + "\\Msg\\" + MicroMsgDB
if _, err := os.Stat(MicroMsgDBPath); err != nil {
log.Println("MicroMsgDBPath:", MicroMsgDBPath, err)
return nil, err
}
microMsg, err := sql.Open("sqlite3", MicroMsgDBPath)
if err != nil {
log.Printf("open db %s error: %v", MicroMsgDBPath, err)
return nil, err
}
defer microMsg.Close()
info := &WeChatAccountInfo{}
var UserName, Alias, ReMark, NickName string
querySql := fmt.Sprintf("select ifnull(UserName,'') as UserName, ifnull(Alias,'') as Alias, ifnull(ReMark,'') as ReMark, ifnull(NickName,'') as NickName from Contact where UserName='%s';", accountName)
// log.Println(querySql)
err = microMsg.QueryRow(querySql).Scan(&UserName, &Alias, &ReMark, &NickName)
if err != nil {
log.Println("not found User:", err)
return nil, err
}
log.Printf("UserName %s, Alias %s, ReMark %s, NickName %s\n", UserName, Alias, ReMark, NickName)
var smallHeadImgUrl, bigHeadImgUrl string
querySql = fmt.Sprintf("select ifnull(smallHeadImgUrl,'') as smallHeadImgUrl, ifnull(bigHeadImgUrl,'') as bigHeadImgUrl from ContactHeadImgUrl where usrName='%s';", UserName)
// log.Println(querySql)
err = microMsg.QueryRow(querySql).Scan(&smallHeadImgUrl, &bigHeadImgUrl)
if err != nil {
log.Println("not find headimg", err)
}
info.AccountName = UserName
info.AliasName = Alias
info.ReMarkName = ReMark
info.NickName = NickName
info.SmallHeadImgUrl = smallHeadImgUrl
info.BigHeadImgUrl = bigHeadImgUrl
// log.Println(info)
return info, nil
}