Add sync command

This commit is contained in:
Tulir Asokan 2021-11-08 20:57:04 +02:00
parent 9262f4c410
commit 01c1648c07
2 changed files with 77 additions and 4 deletions

View file

@ -26,6 +26,7 @@ import (
"strings" "strings"
"github.com/skip2/go-qrcode" "github.com/skip2/go-qrcode"
"go.mau.fi/whatsmeow/appstate"
"maunium.net/go/maulogger/v2" "maunium.net/go/maulogger/v2"
@ -150,6 +151,8 @@ func (handler *CommandHandler) CommandMux(ce *CommandEvent) {
handler.CommandUnsetRelay(ce) handler.CommandUnsetRelay(ce)
case "login-matrix": case "login-matrix":
handler.CommandLoginMatrix(ce) handler.CommandLoginMatrix(ce)
case "sync":
handler.CommandSync(ce)
case "list": case "list":
handler.CommandList(ce) handler.CommandList(ce)
case "open": case "open":
@ -705,6 +708,7 @@ func (handler *CommandHandler) CommandHelp(ce *CommandEvent) {
cmdPrefix + cmdLogoutMatrixHelp, cmdPrefix + cmdLogoutMatrixHelp,
cmdPrefix + cmdToggleHelp, cmdPrefix + cmdToggleHelp,
cmdPrefix + cmdListHelp, cmdPrefix + cmdListHelp,
cmdPrefix + cmdSyncHelp,
cmdPrefix + cmdOpenHelp, cmdPrefix + cmdOpenHelp,
cmdPrefix + cmdPMHelp, cmdPrefix + cmdPMHelp,
cmdPrefix + cmdInviteLinkHelp, cmdPrefix + cmdInviteLinkHelp,
@ -987,6 +991,48 @@ func (handler *CommandHandler) CommandPM(ce *CommandEvent) {
ce.Reply("Created portal room with +%s and invited you to it.", puppet.JID.User) ce.Reply("Created portal room with +%s and invited you to it.", puppet.JID.User)
} }
const cmdSyncHelp = `sync <appstate/contacts/groups> [--create-portals] - Synchronize data from WhatsApp.`
func (handler *CommandHandler) CommandSync(ce *CommandEvent) {
if len(ce.Args) == 0 {
ce.Reply("**Usage:** `sync <appstate/contacts/groups> [--create-portals]`")
return
}
args := strings.ToLower(strings.Join(ce.Args, " "))
contacts := strings.Contains(args, "contacts")
appState := strings.Contains(args, "appstate")
groups := strings.Contains(args, "groups")
createPortals := strings.Contains(args, "--create-portals")
if appState {
for _, name := range appstate.AllPatchNames {
err := ce.User.Client.FetchAppState(name, true, false)
if err != nil {
ce.Reply("Error syncing app state %s", name)
} else if name == appstate.WAPatchCriticalUnblockLow {
ce.Reply("Synced app state %s, contact sync running in background", name)
} else {
ce.Reply("Synced app state %s", name)
}
}
} else if contacts {
err := ce.User.ResyncContacts()
if err != nil {
ce.Reply("Error resyncing contacts: %v", err)
} else {
ce.Reply("Resynced contacts")
}
}
if groups {
err := ce.User.ResyncGroups(createPortals)
if err != nil {
ce.Reply("Error resyncing groups: %v", err)
} else {
ce.Reply("Resynced groups")
}
}
}
const cmdLoginMatrixHelp = `login-matrix <_access token_> - Replace your WhatsApp account's Matrix puppet with your real Matrix account.` const cmdLoginMatrixHelp = `login-matrix <_access token_> - Replace your WhatsApp account's Matrix puppet with your real Matrix account.`
func (handler *CommandHandler) CommandLoginMatrix(ce *CommandEvent) { func (handler *CommandHandler) CommandLoginMatrix(ce *CommandEvent) {

35
user.go
View file

@ -387,7 +387,12 @@ func (user *User) HandleEvent(event interface{}) {
user.log.Warnln("Failed to send presence after app state sync:", err) user.log.Warnln("Failed to send presence after app state sync:", err)
} }
} else if v.Name == appstate.WAPatchCriticalUnblockLow { } else if v.Name == appstate.WAPatchCriticalUnblockLow {
go user.resyncPuppets() go func() {
err := user.ResyncContacts()
if err != nil {
user.log.Errorln("Failed to resync puppets: %v", err)
}
}()
} }
case *events.PushNameSetting: case *events.PushNameSetting:
// Send presence available when connecting and when the pushname is changed. // Send presence available when connecting and when the pushname is changed.
@ -629,16 +634,38 @@ func (user *User) syncPuppet(jid types.JID, reason string) {
user.bridge.GetPuppetByJID(jid).SyncContact(user, false, reason) user.bridge.GetPuppetByJID(jid).SyncContact(user, false, reason)
} }
func (user *User) resyncPuppets() { func (user *User) ResyncContacts() error {
contacts, err := user.Client.Store.Contacts.GetAllContacts() contacts, err := user.Client.Store.Contacts.GetAllContacts()
if err != nil { if err != nil {
user.log.Errorln("Failed to get all contacts to sync puppets:", err) return fmt.Errorf("failed to get cached contacts: %w", err)
return
} }
user.log.Infofln("Resyncing displaynames with %d contacts", len(contacts))
for jid, contact := range contacts { for jid, contact := range contacts {
puppet := user.bridge.GetPuppetByJID(jid) puppet := user.bridge.GetPuppetByJID(jid)
puppet.Sync(user, contact) puppet.Sync(user, contact)
} }
return nil
}
func (user *User) ResyncGroups(createPortals bool) error {
groups, err := user.Client.GetJoinedGroups()
if err != nil {
return fmt.Errorf("failed to get group list from server: %w", err)
}
for _, group := range groups {
portal := user.GetPortalByJID(group.JID)
if len(portal.MXID) == 0 {
if createPortals {
err = portal.CreateMatrixRoom(user, group, true)
if err != nil {
return fmt.Errorf("failed to create room for %s: %w", group.JID, err)
}
}
} else {
portal.UpdateMatrixRoom(user, group)
}
}
return nil
} }
const WATypingTimeout = 15 * time.Second const WATypingTimeout = 15 * time.Second