1. 图片/视频查看重新实现,保持与微信一致
2. 增加软件信息页面 3. 修复企业联系人头像和名称不显示问题 4. 修复撤回消息显示不正常的问题
This commit is contained in:
parent
30ccdd6c65
commit
d34225785c
@ -9,6 +9,7 @@ PC微信聊天记录数据导出工具
|
||||
效果图如下:
|
||||
|
||||

|
||||

|
||||
|
||||
## 演示视频
|
||||
[演示视频](https://www.bilibili.com/video/BV1bPH1eWEEy/?share_source=copy_web&vd_source=b5cfa9258a9ad9900a00e9c1ce3cb4b6)
|
||||
@ -47,7 +48,7 @@ wails build
|
||||
- [x] 多开账号数据切换
|
||||
- [x] 头像使用本地头像
|
||||
- [ ] 支持更多消息类型显示
|
||||
- [ ] 图片查看器重绘
|
||||
- [x] 图片查看器重绘
|
||||
- [ ] 实现表情预先下载(实现完全离线查看)
|
||||
- [ ] 聊天报告
|
||||
- [ ] AI本地模型应用
|
||||
@ -64,6 +65,10 @@ A: 这是由于可能数据存在于内存中还没有回写到磁盘导致的
|
||||
**Q: 有些图片、视频打不开**<br>
|
||||
A: 这是电脑端微信没有点开过这个消息,默认只加载了预览图而已,如果手机有打开过可以把手机的记录迁移到电脑,迁移后重新退出登陆一次微信导出即可。<br>
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/?utm_source=bestxtools.com#git-jiadong/wechatDataBackup&Date)
|
||||
|
||||
## 免责声明
|
||||
**⚠️ 本项目仅供学习、研究使用,严禁商业使用**<br/>
|
||||
**⚠️ 用于网络安全用途的,请确保在国家法律法规下使用**<br/>
|
||||
|
141
app.go
141
app.go
@ -5,9 +5,11 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"wechatDataBackup/pkg/utils"
|
||||
"wechatDataBackup/pkg/wechat"
|
||||
@ -21,7 +23,7 @@ const (
|
||||
configDefaultUserKey = "userConfig.defaultUser"
|
||||
configUsersKey = "userConfig.users"
|
||||
configExportPathKey = "exportPath"
|
||||
appVersion = "v1.0.5"
|
||||
appVersion = "v1.0.6"
|
||||
)
|
||||
|
||||
type FileLoader struct {
|
||||
@ -30,6 +32,7 @@ type FileLoader struct {
|
||||
}
|
||||
|
||||
func NewFileLoader(prefix string) *FileLoader {
|
||||
mime.AddExtensionType(".mp3", "audio/mpeg")
|
||||
return &FileLoader{FilePrefix: prefix}
|
||||
}
|
||||
|
||||
@ -39,16 +42,74 @@ func (h *FileLoader) SetFilePrefix(prefix string) {
|
||||
}
|
||||
|
||||
func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||
var err error
|
||||
requestedFilename := h.FilePrefix + "\\" + strings.TrimPrefix(req.URL.Path, "/")
|
||||
// log.Println("Requesting file:", requestedFilename)
|
||||
fileData, err := os.ReadFile(requestedFilename)
|
||||
|
||||
file, err := os.Open(requestedFilename)
|
||||
if err != nil {
|
||||
res.WriteHeader(http.StatusBadRequest)
|
||||
res.Write([]byte(fmt.Sprintf("Could not load file %s", requestedFilename)))
|
||||
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
|
||||
}
|
||||
|
||||
res.Write(fileData)
|
||||
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
|
||||
@ -90,7 +151,7 @@ type ErrorMessage struct {
|
||||
// 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)
|
||||
@ -306,7 +367,7 @@ func (a *App) GetWechatContactList(pageIndex int, pageSize int) string {
|
||||
}
|
||||
|
||||
func (a *App) GetWechatMessageListByTime(userName string, time int64, pageSize int, direction string) string {
|
||||
log.Println("GetWechatMessageList:", userName, pageSize, time, direction)
|
||||
log.Println("GetWechatMessageListByTime:", userName, pageSize, time, direction)
|
||||
if len(userName) == 0 {
|
||||
return "{\"Total\":0, \"Rows\":[]}"
|
||||
}
|
||||
@ -318,11 +379,33 @@ func (a *App) GetWechatMessageListByTime(userName string, time int64, pageSize i
|
||||
}
|
||||
list, err := a.provider.WeChatGetMessageListByTime(userName, time, pageSize, dire)
|
||||
if err != nil {
|
||||
log.Println("WeChatGetMessageList failed:", err)
|
||||
log.Println("GetWechatMessageListByTime failed:", err)
|
||||
return ""
|
||||
}
|
||||
listStr, _ := json.Marshal(list)
|
||||
log.Println("GetWechatMessageList:", list.Total)
|
||||
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)
|
||||
}
|
||||
@ -594,3 +677,39 @@ func (a *App) scanAccountByPath(path string) error {
|
||||
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 ""
|
||||
}
|
||||
|
@ -1,3 +1,9 @@
|
||||
## v1.0.6
|
||||
1. 图片/视频查看重新实现,保持与微信一致
|
||||
2. 增加软件信息页面
|
||||
3. 修复企业联系人头像和名称不显示问题
|
||||
4. 修复撤回消息显示不正常的问题
|
||||
|
||||
## v1.0.5
|
||||
1. 修复联系人搜索显示异常的问题
|
||||
2. 修复启动时界面加载显示慢的问题
|
||||
|
BIN
frontend/dist/assets/errorImg.719abbab.png
vendored
Normal file
BIN
frontend/dist/assets/errorImg.719abbab.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
503
frontend/dist/assets/index.5130ac24.js
vendored
503
frontend/dist/assets/index.5130ac24.js
vendored
File diff suppressed because one or more lines are too long
1
frontend/dist/assets/index.a11c4643.css
vendored
Normal file
1
frontend/dist/assets/index.a11c4643.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
frontend/dist/assets/index.bee21395.css
vendored
1
frontend/dist/assets/index.bee21395.css
vendored
File diff suppressed because one or more lines are too long
533
frontend/dist/assets/index.d5e97187.js
vendored
Normal file
533
frontend/dist/assets/index.d5e97187.js
vendored
Normal file
File diff suppressed because one or more lines are too long
503
frontend/dist/assets/index.e451d83d.js
vendored
503
frontend/dist/assets/index.e451d83d.js
vendored
File diff suppressed because one or more lines are too long
1
frontend/dist/assets/index.f70722f4.css
vendored
1
frontend/dist/assets/index.f70722f4.css
vendored
File diff suppressed because one or more lines are too long
4
frontend/dist/index.html
vendored
4
frontend/dist/index.html
vendored
@ -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.5130ac24.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index.f70722f4.css">
|
||||
<script type="module" crossorigin src="/assets/index.d5e97187.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index.a11c4643.css">
|
||||
</head>
|
||||
<body >
|
||||
<div id="root"></div>
|
||||
|
@ -1,7 +1,9 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
@ -120,3 +122,31 @@ func PathIsCanWriteFile(path string) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func CopyFile(src, dst string) (int64, error) {
|
||||
stat, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if stat.IsDir() {
|
||||
return 0, errors.New(src + " is dir")
|
||||
}
|
||||
sourceFile, err := os.Open(src)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer sourceFile.Close()
|
||||
|
||||
destFile, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer destFile.Close()
|
||||
|
||||
bytesWritten, err := io.Copy(destFile, sourceFile)
|
||||
if err != nil {
|
||||
return bytesWritten, err
|
||||
}
|
||||
|
||||
return bytesWritten, nil
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ type WechatDataProvider struct {
|
||||
resPath string
|
||||
prefixResPath string
|
||||
microMsg *sql.DB
|
||||
|
||||
openIMContact *sql.DB
|
||||
msgDBs []*wechatMsgDB
|
||||
userInfoMap map[string]WeChatUserInfo
|
||||
userInfoMtx sync.Mutex
|
||||
@ -191,6 +191,7 @@ type WechatDataProvider struct {
|
||||
|
||||
const (
|
||||
MicroMsgDB = "MicroMsg.db"
|
||||
OpenIMContactDB = "OpenIMContact.db"
|
||||
)
|
||||
|
||||
type byTime []*wechatMsgDB
|
||||
@ -239,6 +240,15 @@ func CreateWechatDataProvider(resPath string, prefixRes string) (*WechatDataProv
|
||||
return provider, err
|
||||
}
|
||||
|
||||
var openIMContact *sql.DB
|
||||
OpenIMContactDBPath := resPath + "\\Msg\\" + OpenIMContactDB
|
||||
if _, err := os.Stat(OpenIMContactDBPath); err == nil {
|
||||
openIMContact, err = sql.Open("sqlite3", OpenIMContactDBPath)
|
||||
if err != nil {
|
||||
log.Printf("open db %s error: %v", OpenIMContactDBPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
index := 0
|
||||
for {
|
||||
msgDBPath := fmt.Sprintf("%s\\Msg\\Multi\\MSG%d.db", provider.resPath, index)
|
||||
@ -262,6 +272,7 @@ func CreateWechatDataProvider(resPath string, prefixRes string) (*WechatDataProv
|
||||
}
|
||||
provider.userInfoMap = make(map[string]WeChatUserInfo)
|
||||
provider.microMsg = microMsg
|
||||
provider.openIMContact = openIMContact
|
||||
provider.SelfInfo, err = provider.WechatGetUserInfoByNameOnCache(userName)
|
||||
if err != nil {
|
||||
log.Printf("WechatGetUserInfoByName %s failed: %v", userName, err)
|
||||
@ -288,6 +299,13 @@ func (P *WechatDataProvider) WechatWechatDataProviderClose() {
|
||||
}
|
||||
}
|
||||
|
||||
if P.openIMContact != nil {
|
||||
err := P.openIMContact.Close()
|
||||
if err != nil {
|
||||
log.Println("db close:", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, db := range P.msgDBs {
|
||||
err := db.db.Close()
|
||||
if err != nil {
|
||||
@ -336,6 +354,47 @@ func (P *WechatDataProvider) WechatGetUserInfoByName(name string) (*WeChatUserIn
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (P *WechatDataProvider) WechatGetOpenIMMUserInfoByName(name string) (*WeChatUserInfo, error) {
|
||||
info := &WeChatUserInfo{}
|
||||
|
||||
var UserName, ReMark, NickName string
|
||||
querySql := fmt.Sprintf("select ifnull(UserName,'') as UserName, ifnull(ReMark,'') as ReMark, ifnull(NickName,'') as NickName from OpenIMContact where UserName='%s';", name)
|
||||
// log.Println(querySql)
|
||||
if P.openIMContact != nil {
|
||||
err := P.openIMContact.QueryRow(querySql).Scan(&UserName, &ReMark, &NickName)
|
||||
if err != nil {
|
||||
log.Println("not found User:", err)
|
||||
return info, err
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("UserName %s, ReMark %s, NickName %s\n", UserName, 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 := P.microMsg.QueryRow(querySql).Scan(&smallHeadImgUrl, &bigHeadImgUrl)
|
||||
if err != nil {
|
||||
log.Println("not find headimg", err)
|
||||
}
|
||||
|
||||
info.UserName = UserName
|
||||
info.Alias = ""
|
||||
info.ReMark = ReMark
|
||||
info.NickName = NickName
|
||||
info.SmallHeadImgUrl = smallHeadImgUrl
|
||||
info.BigHeadImgUrl = bigHeadImgUrl
|
||||
info.IsGroup = strings.HasSuffix(UserName, "@chatroom")
|
||||
|
||||
localHeadImgPath := fmt.Sprintf("%s\\FileStorage\\HeadImage\\%s.headimg", P.resPath, name)
|
||||
relativePath := fmt.Sprintf("%s\\FileStorage\\HeadImage\\%s.headimg", P.prefixResPath, name)
|
||||
if _, err = os.Stat(localHeadImgPath); err == nil {
|
||||
info.LocalHeadImgUrl = relativePath
|
||||
}
|
||||
// log.Println(info)
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (P *WechatDataProvider) WeChatGetSessionList(pageIndex int, pageSize int) (*WeChatSessionList, error) {
|
||||
List := &WeChatSessionList{}
|
||||
List.Rows = make([]WeChatSession, 0)
|
||||
@ -364,7 +423,7 @@ func (P *WechatDataProvider) WeChatGetSessionList(pageIndex int, pageSize int) (
|
||||
|
||||
session.UserName = strUsrName
|
||||
session.NickName = strNickName
|
||||
session.Content = strContent
|
||||
session.Content = revokemsg_parse(strContent)
|
||||
session.Time = nTime
|
||||
session.IsGroup = strings.HasSuffix(strUsrName, "@chatroom")
|
||||
info, err := P.WechatGetUserInfoByNameOnCache(strUsrName)
|
||||
@ -502,7 +561,7 @@ func (P *WechatDataProvider) weChatGetMessageListByTime(userName string, time in
|
||||
message.IsSender = IsSender
|
||||
message.CreateTime = CreateTime
|
||||
message.Talker = StrTalker
|
||||
message.Content = StrContent
|
||||
message.Content = revokemsg_parse(StrContent)
|
||||
message.IsChatRoom = strings.HasSuffix(StrTalker, "@chatroom")
|
||||
message.compressContent = make([]byte, len(CompressContent))
|
||||
message.bytesExtra = make([]byte, len(BytesExtra))
|
||||
@ -564,6 +623,87 @@ func (P *WechatDataProvider) WeChatGetMessageListByKeyWord(userName string, time
|
||||
return List, nil
|
||||
}
|
||||
|
||||
func (P *WechatDataProvider) WeChatGetMessageListByType(userName string, time int64, pageSize int, msgType string, direction Message_Search_Direction) (*WeChatMessageList, error) {
|
||||
|
||||
List := &WeChatMessageList{}
|
||||
List.Rows = make([]WeChatMessage, 0)
|
||||
selectTime := time
|
||||
selectpageSize := 30
|
||||
needSize := pageSize
|
||||
|
||||
if msgType != "" {
|
||||
selectpageSize = 600
|
||||
}
|
||||
if direction == Message_Search_Both {
|
||||
needSize = pageSize / 2
|
||||
}
|
||||
for direction == Message_Search_Forward || direction == Message_Search_Both {
|
||||
selectList, err := P.weChatGetMessageListByTime(userName, selectTime, selectpageSize, Message_Search_Forward)
|
||||
if err != nil {
|
||||
return List, err
|
||||
}
|
||||
|
||||
if selectList.Total == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
for i, _ := range selectList.Rows {
|
||||
if weChatMessageTypeFilter(&selectList.Rows[i], msgType) {
|
||||
List.Rows = append(List.Rows, selectList.Rows[i])
|
||||
List.Total += 1
|
||||
needSize -= 1
|
||||
if needSize <= 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if needSize <= 0 {
|
||||
break
|
||||
}
|
||||
selectTime = selectList.Rows[selectList.Total-1].CreateTime - 1
|
||||
log.Printf("Forward selectTime %d, selectpageSize %d needSize %d\n", selectTime, selectpageSize, needSize)
|
||||
}
|
||||
|
||||
selectTime = time
|
||||
if direction == Message_Search_Both {
|
||||
needSize = pageSize / 2
|
||||
}
|
||||
for direction == Message_Search_Backward || direction == Message_Search_Both {
|
||||
selectList, err := P.weChatGetMessageListByTime(userName, selectTime, selectpageSize, Message_Search_Backward)
|
||||
if err != nil {
|
||||
return List, err
|
||||
}
|
||||
|
||||
if selectList.Total == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
tmpTotal := 0
|
||||
tmpRows := make([]WeChatMessage, 0)
|
||||
for i := selectList.Total - 1; i >= 0; i-- {
|
||||
if weChatMessageTypeFilter(&selectList.Rows[i], msgType) {
|
||||
tmpRows = append([]WeChatMessage{selectList.Rows[i]}, tmpRows...)
|
||||
tmpTotal += 1
|
||||
needSize -= 1
|
||||
if needSize <= 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if tmpTotal > 0 {
|
||||
List.Rows = append(tmpRows, List.Rows...)
|
||||
List.Total += tmpTotal
|
||||
}
|
||||
selectTime = selectList.Rows[0].CreateTime + 1
|
||||
if needSize <= 0 {
|
||||
break
|
||||
}
|
||||
log.Printf("Backward selectTime %d, selectpageSize %d needSize %d\n", selectTime, selectpageSize, needSize)
|
||||
}
|
||||
|
||||
return List, nil
|
||||
}
|
||||
|
||||
func (P *WechatDataProvider) WeChatGetMessageDate(userName string) (*WeChatMessageDate, error) {
|
||||
messageData := &WeChatMessageDate{}
|
||||
messageData.Date = make([]string, 0)
|
||||
@ -661,7 +801,7 @@ func (P *WechatDataProvider) wechatMessageExtraHandle(msg *WeChatMessage) {
|
||||
switch ext.Field1 {
|
||||
case 1:
|
||||
if msg.IsChatRoom {
|
||||
msg.Talker = ext.Field2
|
||||
msg.UserInfo.UserName = ext.Field2
|
||||
}
|
||||
case 3:
|
||||
if len(ext.Field2) > 0 && (msg.Type == Wechat_Message_Type_Picture || msg.Type == Wechat_Message_Type_Video || msg.Type == Wechat_Message_Type_Misc) {
|
||||
@ -784,6 +924,8 @@ func (P *WechatDataProvider) wechatMessageGetUserInfo(msg *WeChatMessage) {
|
||||
who := msg.Talker
|
||||
if msg.IsSender == 1 {
|
||||
who = P.SelfInfo.UserName
|
||||
} else if msg.IsChatRoom {
|
||||
who = msg.UserInfo.UserName
|
||||
}
|
||||
|
||||
pinfo, err := P.WechatGetUserInfoByNameOnCache(who)
|
||||
@ -963,7 +1105,13 @@ func (P *WechatDataProvider) WechatGetUserInfoByNameOnCache(name string) (*WeCha
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
pinfo, err := P.WechatGetUserInfoByName(name)
|
||||
var pinfo *WeChatUserInfo
|
||||
var err error
|
||||
if strings.HasSuffix(name, "@openim") {
|
||||
pinfo, err = P.WechatGetOpenIMMUserInfoByName(name)
|
||||
} else {
|
||||
pinfo, err = P.WechatGetUserInfoByName(name)
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("WechatGetUserInfoByName %s failed: %v\n", name, err)
|
||||
return nil, err
|
||||
@ -1067,3 +1215,12 @@ func WechatGetAccountInfo(resPath, prefixRes, accountName string) (*WeChatAccoun
|
||||
// log.Println(info)
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func revokemsg_parse(content string) string {
|
||||
if strings.HasPrefix(content, "<revokemsg>") && strings.HasSuffix(content, "</revokemsg>") {
|
||||
trimmed := strings.TrimSuffix(strings.TrimPrefix(content, "<revokemsg>"), "</revokemsg>")
|
||||
return trimmed
|
||||
}
|
||||
|
||||
return content
|
||||
}
|
||||
|
BIN
res/result2.png
Normal file
BIN
res/result2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 772 KiB |
Loading…
Reference in New Issue
Block a user