diff options
Diffstat (limited to 'vendor/go.mau.fi/whatsmeow/appstate.go')
-rw-r--r-- | vendor/go.mau.fi/whatsmeow/appstate.go | 152 |
1 files changed, 118 insertions, 34 deletions
diff --git a/vendor/go.mau.fi/whatsmeow/appstate.go b/vendor/go.mau.fi/whatsmeow/appstate.go index 7493a030..3c128db6 100644 --- a/vendor/go.mau.fi/whatsmeow/appstate.go +++ b/vendor/go.mau.fi/whatsmeow/appstate.go @@ -74,7 +74,7 @@ func (cli *Client) FetchAppState(name appstate.WAPatchName, fullSync, onlyIfNotS } } for _, mutation := range mutations { - cli.dispatchAppState(mutation, !fullSync || cli.EmitAppStateEventsOnFullSync) + cli.dispatchAppState(mutation, fullSync, cli.EmitAppStateEventsOnFullSync) } } if fullSync { @@ -105,7 +105,10 @@ func (cli *Client) filterContacts(mutations []appstate.Mutation) ([]appstate.Mut return filteredMutations, contacts } -func (cli *Client) dispatchAppState(mutation appstate.Mutation, dispatchEvts bool) { +func (cli *Client) dispatchAppState(mutation appstate.Mutation, fullSync bool, emitOnFullSync bool) { + + dispatchEvts := !fullSync || emitOnFullSync + if mutation.Operation != waProto.SyncdMutation_SET { return } @@ -118,87 +121,108 @@ func (cli *Client) dispatchAppState(mutation appstate.Mutation, dispatchEvts boo if len(mutation.Index) > 1 { jid, _ = types.ParseJID(mutation.Index[1]) } - ts := time.Unix(mutation.Action.GetTimestamp(), 0) + ts := time.UnixMilli(mutation.Action.GetTimestamp()) var storeUpdateError error var eventToDispatch interface{} switch mutation.Index[0] { - case "mute": + case appstate.IndexMute: act := mutation.Action.GetMuteAction() - eventToDispatch = &events.Mute{JID: jid, Timestamp: ts, Action: act} + eventToDispatch = &events.Mute{JID: jid, Timestamp: ts, Action: act, FromFullSync: fullSync} var mutedUntil time.Time if act.GetMuted() { - mutedUntil = time.Unix(act.GetMuteEndTimestamp(), 0) + mutedUntil = time.UnixMilli(act.GetMuteEndTimestamp()) } if cli.Store.ChatSettings != nil { storeUpdateError = cli.Store.ChatSettings.PutMutedUntil(jid, mutedUntil) } - case "pin_v1": + case appstate.IndexPin: act := mutation.Action.GetPinAction() - eventToDispatch = &events.Pin{JID: jid, Timestamp: ts, Action: act} + eventToDispatch = &events.Pin{JID: jid, Timestamp: ts, Action: act, FromFullSync: fullSync} if cli.Store.ChatSettings != nil { storeUpdateError = cli.Store.ChatSettings.PutPinned(jid, act.GetPinned()) } - case "archive": + case appstate.IndexArchive: act := mutation.Action.GetArchiveChatAction() - eventToDispatch = &events.Archive{JID: jid, Timestamp: ts, Action: act} + eventToDispatch = &events.Archive{JID: jid, Timestamp: ts, Action: act, FromFullSync: fullSync} if cli.Store.ChatSettings != nil { storeUpdateError = cli.Store.ChatSettings.PutArchived(jid, act.GetArchived()) } - case "contact": + case appstate.IndexContact: act := mutation.Action.GetContactAction() - eventToDispatch = &events.Contact{JID: jid, Timestamp: ts, Action: act} + eventToDispatch = &events.Contact{JID: jid, Timestamp: ts, Action: act, FromFullSync: fullSync} if cli.Store.Contacts != nil { storeUpdateError = cli.Store.Contacts.PutContactName(jid, act.GetFirstName(), act.GetFullName()) } - case "deleteChat": + case appstate.IndexClearChat: + act := mutation.Action.GetClearChatAction() + eventToDispatch = &events.ClearChat{JID: jid, Timestamp: ts, Action: act, FromFullSync: fullSync} + case appstate.IndexDeleteChat: act := mutation.Action.GetDeleteChatAction() - eventToDispatch = &events.DeleteChat{JID: jid, Timestamp: ts, Action: act} - case "star": + eventToDispatch = &events.DeleteChat{JID: jid, Timestamp: ts, Action: act, FromFullSync: fullSync} + case appstate.IndexStar: if len(mutation.Index) < 5 { return } evt := events.Star{ - ChatJID: jid, - MessageID: mutation.Index[2], - Timestamp: ts, - Action: mutation.Action.GetStarAction(), - IsFromMe: mutation.Index[3] == "1", + ChatJID: jid, + MessageID: mutation.Index[2], + Timestamp: ts, + Action: mutation.Action.GetStarAction(), + IsFromMe: mutation.Index[3] == "1", + FromFullSync: fullSync, } if mutation.Index[4] != "0" { evt.SenderJID, _ = types.ParseJID(mutation.Index[4]) } eventToDispatch = &evt - case "deleteMessageForMe": + case appstate.IndexDeleteMessageForMe: if len(mutation.Index) < 5 { return } evt := events.DeleteForMe{ - ChatJID: jid, - MessageID: mutation.Index[2], - Timestamp: ts, - Action: mutation.Action.GetDeleteMessageForMeAction(), - IsFromMe: mutation.Index[3] == "1", + ChatJID: jid, + MessageID: mutation.Index[2], + Timestamp: ts, + Action: mutation.Action.GetDeleteMessageForMeAction(), + IsFromMe: mutation.Index[3] == "1", + FromFullSync: fullSync, } if mutation.Index[4] != "0" { evt.SenderJID, _ = types.ParseJID(mutation.Index[4]) } eventToDispatch = &evt - case "markChatAsRead": + case appstate.IndexMarkChatAsRead: eventToDispatch = &events.MarkChatAsRead{ - JID: jid, - Timestamp: ts, - Action: mutation.Action.GetMarkChatAsReadAction(), + JID: jid, + Timestamp: ts, + Action: mutation.Action.GetMarkChatAsReadAction(), + FromFullSync: fullSync, + } + case appstate.IndexSettingPushName: + eventToDispatch = &events.PushNameSetting{ + Timestamp: ts, + Action: mutation.Action.GetPushNameSetting(), + FromFullSync: fullSync, } - case "setting_pushName": - eventToDispatch = &events.PushNameSetting{Timestamp: ts, Action: mutation.Action.GetPushNameSetting()} cli.Store.PushName = mutation.Action.GetPushNameSetting().GetName() err := cli.Store.Save() if err != nil { cli.Log.Errorf("Failed to save device store after updating push name: %v", err) } - case "setting_unarchiveChats": - eventToDispatch = &events.UnarchiveChatsSetting{Timestamp: ts, Action: mutation.Action.GetUnarchiveChatsSetting()} + case appstate.IndexSettingUnarchiveChats: + eventToDispatch = &events.UnarchiveChatsSetting{ + Timestamp: ts, + Action: mutation.Action.GetUnarchiveChatsSetting(), + FromFullSync: fullSync, + } + case appstate.IndexUserStatusMute: + eventToDispatch = &events.UserStatusMute{ + JID: jid, + Timestamp: ts, + Action: mutation.Action.GetUserStatusMuteAction(), + FromFullSync: fullSync, + } } if storeUpdateError != nil { cli.Log.Errorf("Failed to update device store after app state mutation: %v", storeUpdateError) @@ -280,3 +304,63 @@ func (cli *Client) requestAppStateKeys(ctx context.Context, rawKeyIDs [][]byte) cli.Log.Warnf("Failed to send app state key request: %v", err) } } + +// SendAppState sends the given app state patch, then resyncs that app state type from the server +// to update local caches and send events for the updates. +// +// You can use the Build methods in the appstate package to build the parameter for this method, e.g. +// +// cli.SendAppState(appstate.BuildMute(targetJID, true, 24 * time.Hour)) +func (cli *Client) SendAppState(patch appstate.PatchInfo) error { + version, hash, err := cli.Store.AppState.GetAppStateVersion(string(patch.Type)) + if err != nil { + return err + } + // TODO create new key instead of reusing the primary client's keys + latestKeyID, err := cli.Store.AppStateKeys.GetLatestAppStateSyncKeyID() + if err != nil { + return fmt.Errorf("failed to get latest app state key ID: %w", err) + } else if latestKeyID == nil { + return fmt.Errorf("no app state keys found, creating app state keys is not yet supported") + } + + state := appstate.HashState{Version: version, Hash: hash} + + encodedPatch, err := cli.appStateProc.EncodePatch(latestKeyID, state, patch) + if err != nil { + return err + } + + resp, err := cli.sendIQ(infoQuery{ + Namespace: "w:sync:app:state", + Type: iqSet, + To: types.ServerJID, + Content: []waBinary.Node{{ + Tag: "sync", + Content: []waBinary.Node{{ + Tag: "collection", + Attrs: waBinary.Attrs{ + "name": string(patch.Type), + "version": version, + "return_snapshot": false, + }, + Content: []waBinary.Node{{ + Tag: "patch", + Content: encodedPatch, + }}, + }}, + }}, + }) + if err != nil { + return err + } + + respCollection := resp.GetChildByTag("sync", "collection") + respCollectionAttr := respCollection.AttrGetter() + if respCollectionAttr.OptionalString("type") == "error" { + // TODO parse error properly + return fmt.Errorf("%w: %s", ErrAppStateUpdate, respCollection.XMLString()) + } + + return cli.FetchAppState(patch.Type, false, false) +} |