fix(search): search content excludes pic links

This commit is contained in:
Symb0x76
2025-10-10 12:52:15 +08:00
parent 687ee63aa6
commit 99442d8eb7
3 changed files with 150 additions and 10 deletions
+6
View File
@@ -247,6 +247,12 @@ func (c *Context) SetAutoDecrypt(enabled bool) {
c.UpdateConfig()
}
func (c *Context) SetWeChatInstances(instances []*wechat.Account) {
c.mu.Lock()
defer c.mu.Unlock()
c.WeChatInstances = instances
}
// 更新配置
func (c *Context) UpdateConfig() {
+103 -4
View File
@@ -5,6 +5,8 @@ import (
"fmt"
"os"
"strings"
"sync"
"time"
"github.com/rs/zerolog/log"
"github.com/sjzar/chatlog/internal/chatlog/conf"
@@ -18,6 +20,8 @@ import (
"github.com/sjzar/chatlog/pkg/util/dat2img"
)
const initialDecryptPollInterval = 5 * time.Second
// Manager 管理聊天日志应用
type Manager struct {
ctx *ctx.Context
@@ -31,6 +35,10 @@ type Manager struct {
// Terminal UI
app *App
initialDecryptOnce sync.Once
initialDecryptMu sync.Mutex
initialDecryptLastErr string
}
func New() *Manager {
@@ -51,11 +59,14 @@ func (m *Manager) Run(configPath string) error {
m.http = http.NewService(m.ctx, m.db)
m.ctx.WeChatInstances = m.wechat.GetWeChatInstances()
if len(m.ctx.WeChatInstances) >= 1 {
m.ctx.SwitchCurrent(m.ctx.WeChatInstances[0])
instances := m.wechat.GetWeChatInstances()
m.ctx.SetWeChatInstances(instances)
if len(instances) >= 1 {
m.ctx.SwitchCurrent(instances[0])
}
m.startInitialDecryptWatcher()
if m.ctx.HTTPEnabled {
// 启动HTTP服务
if err := m.StartService(); err != nil {
@@ -68,6 +79,94 @@ func (m *Manager) Run(configPath string) error {
return nil
}
func (m *Manager) startInitialDecryptWatcher() {
m.initialDecryptOnce.Do(func() {
go m.initialDecryptLoop()
})
}
func (m *Manager) initialDecryptLoop() {
if m.tryInitialDecryptOnce() {
return
}
ticker := time.NewTicker(initialDecryptPollInterval)
defer ticker.Stop()
for range ticker.C {
if m.tryInitialDecryptOnce() {
return
}
}
}
func (m *Manager) tryInitialDecryptOnce() bool {
if m.ctx == nil || m.wechat == nil {
return false
}
instances := m.wechat.GetWeChatInstances()
if len(instances) == 0 {
return false
}
m.ctx.SetWeChatInstances(instances)
target := m.selectAccountForAutoDecrypt(instances)
if target == nil {
target = instances[0]
}
if m.ctx.Current == nil || m.ctx.Current.Name != target.Name || m.ctx.Current.PID != target.PID {
m.ctx.SwitchCurrent(target)
} else {
m.ctx.Refresh()
}
if err := m.DecryptDBFiles(); err != nil {
m.recordInitialDecryptError(err)
return false
}
log.Info().Str("account", target.Name).Msg("自动解密完成")
return true
}
func (m *Manager) selectAccountForAutoDecrypt(instances []*iwechat.Account) *iwechat.Account {
if m.ctx.Current != nil {
for _, inst := range instances {
if inst.Name == m.ctx.Current.Name {
return inst
}
}
}
if m.ctx.Account != "" {
for _, inst := range instances {
if inst.Name == m.ctx.Account {
return inst
}
}
}
return nil
}
func (m *Manager) recordInitialDecryptError(err error) {
if err == nil {
return
}
msg := err.Error()
m.initialDecryptMu.Lock()
defer m.initialDecryptMu.Unlock()
if msg == m.initialDecryptLastErr {
return
}
m.initialDecryptLastErr = msg
log.Warn().Err(err).Msg("自动解密失败,将继续重试")
}
func (m *Manager) Switch(info *iwechat.Account, history string) error {
if m.ctx.AutoDecrypt {
if err := m.StopAutoDecrypt(); err != nil {
@@ -250,7 +349,7 @@ func (m *Manager) CommandKey(configPath string, pid int, force bool, showXorKey
m.wechat = wechat.NewService(m.ctx)
m.ctx.WeChatInstances = m.wechat.GetWeChatInstances()
m.ctx.SetWeChatInstances(m.wechat.GetWeChatInstances())
if len(m.ctx.WeChatInstances) == 0 {
return "", fmt.Errorf("wechat process not found")
}
+41 -6
View File
@@ -384,12 +384,22 @@ func (m *Message) PlainTextContent() string {
if voice, ok := m.Contents["voice"]; ok {
// 可选时长字段(可能来源于不同表:voicelength/voiceduration/length 秒)
var durStr string
if d, ok2 := m.Contents["voicelength"]; ok2 { durStr = fmt.Sprint(d) }
if d, ok2 := m.Contents["voiceduration"]; ok2 { durStr = fmt.Sprint(d) }
if d, ok2 := m.Contents["length"]; ok2 && durStr=="" { durStr = fmt.Sprint(d) }
if d, ok2 := m.Contents["voicelength"]; ok2 {
durStr = fmt.Sprint(d)
}
if d, ok2 := m.Contents["voiceduration"]; ok2 {
durStr = fmt.Sprint(d)
}
if d, ok2 := m.Contents["length"]; ok2 && durStr == "" {
durStr = fmt.Sprint(d)
}
if durStr != "" {
// 规范成整数秒显示
if strings.Contains(durStr, ".") { if f,err:=strconv.ParseFloat(durStr,64); err==nil { durStr = fmt.Sprint(int(f+0.5)) } }
if strings.Contains(durStr, ".") {
if f, err := strconv.ParseFloat(durStr, 64); err == nil {
durStr = fmt.Sprint(int(f + 0.5))
}
}
// >=60s 转换为 XmYYs 形式
if secInt, err := strconv.Atoi(durStr); err == nil {
if secInt >= 60 {
@@ -423,7 +433,7 @@ func (m *Message) PlainTextContent() string {
keylist = append(keylist, path)
}
}
return fmt.Sprintf("![视频](http://%s/video/%s)", host, strings.Join(keylist, ","))
return fmt.Sprintf("![视频](http://%s/video/%s)", host, strings.Join(keylist, ","))
case MessageTypeAnimation:
if m.Contents["cdnurl"] != nil {
if cdnURL, ok := m.Contents["cdnurl"].(string); ok {
@@ -444,7 +454,32 @@ func (m *Message) PlainTextContent() string {
case MessageTypeShare:
switch m.SubType {
case MessageSubTypeText:
return fmt.Sprintf("[链接|%s](%s)", m.Contents["title"], m.Contents["desc"])
title := fmt.Sprint(m.Contents["title"])
desc := fmt.Sprint(m.Contents["desc"])
url := fmt.Sprint(m.Contents["url"])
if title == "<nil>" {
title = "链接"
}
if desc == "<nil>" {
desc = ""
}
if url == "<nil>" {
url = ""
}
if url == "" && strings.HasPrefix(desc, "http") {
url = desc
}
if url != "" {
text := fmt.Sprintf("[链接|%s](%s)", title, url)
if desc != "" && desc != url {
text = text + "\n" + desc
}
return text
}
if desc != "" {
return fmt.Sprintf("[链接|%s]\n%s", title, desc)
}
return fmt.Sprintf("[链接|%s]", title)
case MessageSubTypeLink, MessageSubTypeLink2:
return fmt.Sprintf("[链接|%s](%s)", m.Contents["title"], m.Contents["url"])
case MessageSubTypeFile: