fix: resolve live LID messages before storage
This commit is contained in:
parent
78794f9757
commit
fca5b96138
@ -38,6 +38,7 @@
|
||||
- Send: persist retry-message plaintext so linked devices can decrypt retried messages. (#186 — thanks @SimDamDev)
|
||||
- Store: use the XDG state directory on Linux by default, while keeping existing `~/.wacli` stores working. (#172, #164 — thanks @txhno)
|
||||
- Sync: guard lazy WhatsApp client initialization against concurrent `OpenWA` calls. (#62 — thanks @thakoreh)
|
||||
- Sync: resolve live `@lid` chat and sender JIDs to phone-number JIDs before storing messages. (#196 — thanks @mahidconseil)
|
||||
- Sync: warn when encrypted reaction messages cannot be decrypted instead of dropping the failure silently. (#192 — thanks @matrixise and @dinakars777)
|
||||
- Sync: keep `sync --once` idle timing focused on message/history events so connection chatter cannot hang exit. (#119 — thanks @jyothepro)
|
||||
- Sync: start `sync --once` idle timing after the `Connected` event. (#171 — thanks @fuleinist)
|
||||
|
||||
@ -27,6 +27,7 @@ type WAClient interface {
|
||||
ReconnectWithBackoff(ctx context.Context, minDelay, maxDelay time.Duration) error
|
||||
|
||||
ResolveChatName(ctx context.Context, chat types.JID, pushName string) string
|
||||
ResolveLIDToPN(ctx context.Context, jid types.JID) types.JID
|
||||
GetContact(ctx context.Context, jid types.JID) (types.ContactInfo, error)
|
||||
GetAllContacts(ctx context.Context) (map[types.JID]types.ContactInfo, error)
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@ type fakeWA struct {
|
||||
|
||||
contacts map[types.JID]types.ContactInfo
|
||||
groups map[types.JID]*types.GroupInfo
|
||||
lids map[types.JID]types.JID
|
||||
|
||||
onDemandHistory func(lastKnown types.MessageInfo, count int) *events.HistorySync
|
||||
}
|
||||
@ -40,6 +41,7 @@ func newFakeWA() *fakeWA {
|
||||
handlers: map[uint32]func(interface{}){},
|
||||
contacts: map[types.JID]types.ContactInfo{},
|
||||
groups: map[types.JID]*types.GroupInfo{},
|
||||
lids: map[types.JID]types.JID{},
|
||||
nextHandlerID: 1,
|
||||
}
|
||||
}
|
||||
@ -125,6 +127,16 @@ func (f *fakeWA) ResolveChatName(ctx context.Context, chat types.JID, pushName s
|
||||
return chat.String()
|
||||
}
|
||||
|
||||
func (f *fakeWA) ResolveLIDToPN(ctx context.Context, jid types.JID) types.JID {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if pn, ok := f.lids[jid.ToNonAD()]; ok {
|
||||
pn.Device = jid.Device
|
||||
return pn
|
||||
}
|
||||
return jid
|
||||
}
|
||||
|
||||
func (f *fakeWA) GetContact(ctx context.Context, jid types.JID) (types.ContactInfo, error) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
package app
|
||||
|
||||
import "go.mau.fi/whatsmeow/types"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.mau.fi/whatsmeow/types"
|
||||
)
|
||||
|
||||
func canonicalJID(jid types.JID) types.JID {
|
||||
if jid.Server == types.DefaultUserServer {
|
||||
@ -12,3 +16,7 @@ func canonicalJID(jid types.JID) types.JID {
|
||||
func canonicalJIDString(jid types.JID) string {
|
||||
return canonicalJID(jid).String()
|
||||
}
|
||||
|
||||
func (a *App) canonicalStoreJID(ctx context.Context, jid types.JID) types.JID {
|
||||
return canonicalJID(a.wa.ResolveLIDToPN(ctx, jid))
|
||||
}
|
||||
|
||||
@ -114,6 +114,7 @@ func chatKind(chat types.JID) string {
|
||||
}
|
||||
|
||||
func (a *App) storeParsedMessage(ctx context.Context, pm wa.ParsedMessage) error {
|
||||
pm.Chat = a.canonicalStoreJID(ctx, pm.Chat)
|
||||
chatJID := canonicalJIDString(pm.Chat)
|
||||
chatName := a.wa.ResolveChatName(ctx, pm.Chat, pm.PushName)
|
||||
if err := a.db.UpsertChat(chatJID, chatKind(pm.Chat), chatName, pm.Timestamp); err != nil {
|
||||
@ -144,7 +145,7 @@ func (a *App) storeParsedMessage(ctx context.Context, pm wa.ParsedMessage) error
|
||||
senderJID := pm.SenderJID
|
||||
if pm.SenderJID != "" {
|
||||
if jid, err := types.ParseJID(pm.SenderJID); err == nil {
|
||||
contactJID := canonicalJID(jid)
|
||||
contactJID := a.canonicalStoreJID(ctx, jid)
|
||||
senderJID = contactJID.String()
|
||||
if info, err := a.wa.GetContact(ctx, contactJID); err == nil {
|
||||
if name := wa.BestContactName(info); name != "" {
|
||||
|
||||
@ -172,6 +172,45 @@ func TestStoreParsedMessageNormalizesDefaultUserADJIDs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreParsedMessageResolvesLIDChatAndSender(t *testing.T) {
|
||||
a := newTestApp(t)
|
||||
f := newFakeWA()
|
||||
a.wa = f
|
||||
|
||||
lid := types.JID{User: "999123456789", Server: types.HiddenUserServer}
|
||||
pn := types.JID{User: "15551234567", Server: types.DefaultUserServer}
|
||||
f.lids[lid.ToNonAD()] = pn
|
||||
f.contacts[pn.ToNonAD()] = types.ContactInfo{Found: true, FullName: "Alice"}
|
||||
|
||||
err := a.storeParsedMessage(context.Background(), wa.ParsedMessage{
|
||||
Chat: lid,
|
||||
ID: "m-lid",
|
||||
SenderJID: lid.String(),
|
||||
Timestamp: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
Text: "hello",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("storeParsedMessage: %v", err)
|
||||
}
|
||||
|
||||
msg, err := a.db.GetMessage(pn.String(), "m-lid")
|
||||
if err != nil {
|
||||
t.Fatalf("GetMessage resolved chat: %v", err)
|
||||
}
|
||||
if msg.ChatJID != pn.String() {
|
||||
t.Fatalf("ChatJID = %q, want %q", msg.ChatJID, pn.String())
|
||||
}
|
||||
if msg.SenderJID != pn.String() {
|
||||
t.Fatalf("SenderJID = %q, want %q", msg.SenderJID, pn.String())
|
||||
}
|
||||
if msg.ChatName != "Alice" {
|
||||
t.Fatalf("ChatName = %q, want Alice", msg.ChatName)
|
||||
}
|
||||
if _, err := a.db.GetMessage(lid.String(), "m-lid"); err == nil {
|
||||
t.Fatalf("message was also stored under unresolved LID chat")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSyncStoresDisplayText(t *testing.T) {
|
||||
a := newTestApp(t)
|
||||
f := newFakeWA()
|
||||
|
||||
@ -289,6 +289,23 @@ func (c *Client) GetAllContacts(ctx context.Context) (map[types.JID]types.Contac
|
||||
return cli.Store.Contacts.GetAllContacts(ctx)
|
||||
}
|
||||
|
||||
func (c *Client) ResolveLIDToPN(ctx context.Context, jid types.JID) types.JID {
|
||||
if jid.Server != types.HiddenUserServer {
|
||||
return jid
|
||||
}
|
||||
c.mu.Lock()
|
||||
cli := c.client
|
||||
c.mu.Unlock()
|
||||
if cli == nil || cli.Store == nil || cli.Store.LIDs == nil {
|
||||
return jid
|
||||
}
|
||||
pn, err := cli.Store.LIDs.GetPNForLID(ctx, jid.ToNonAD())
|
||||
if err != nil || pn.IsEmpty() {
|
||||
return jid
|
||||
}
|
||||
return pn
|
||||
}
|
||||
|
||||
func BestContactName(info types.ContactInfo) string {
|
||||
if !info.Found {
|
||||
return ""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user