瀏覽代碼

Add sync command

Tulir Asokan 3 年之前
父節點
當前提交
01c1648c07
共有 2 個文件被更改,包括 77 次插入4 次删除
  1. 46 0
      commands.go
  2. 31 4
      user.go

+ 46 - 0
commands.go

@@ -26,6 +26,7 @@ import (
 	"strings"
 
 	"github.com/skip2/go-qrcode"
+	"go.mau.fi/whatsmeow/appstate"
 
 	"maunium.net/go/maulogger/v2"
 
@@ -150,6 +151,8 @@ func (handler *CommandHandler) CommandMux(ce *CommandEvent) {
 			handler.CommandUnsetRelay(ce)
 		case "login-matrix":
 			handler.CommandLoginMatrix(ce)
+		case "sync":
+			handler.CommandSync(ce)
 		case "list":
 			handler.CommandList(ce)
 		case "open":
@@ -705,6 +708,7 @@ func (handler *CommandHandler) CommandHelp(ce *CommandEvent) {
 		cmdPrefix + cmdLogoutMatrixHelp,
 		cmdPrefix + cmdToggleHelp,
 		cmdPrefix + cmdListHelp,
+		cmdPrefix + cmdSyncHelp,
 		cmdPrefix + cmdOpenHelp,
 		cmdPrefix + cmdPMHelp,
 		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)
 }
 
+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.`
 
 func (handler *CommandHandler) CommandLoginMatrix(ce *CommandEvent) {

+ 31 - 4
user.go

@@ -387,7 +387,12 @@ func (user *User) HandleEvent(event interface{}) {
 				user.log.Warnln("Failed to send presence after app state sync:", err)
 			}
 		} 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:
 		// 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)
 }
 
-func (user *User) resyncPuppets() {
+func (user *User) ResyncContacts() error {
 	contacts, err := user.Client.Store.Contacts.GetAllContacts()
 	if err != nil {
-		user.log.Errorln("Failed to get all contacts to sync puppets:", err)
-		return
+		return fmt.Errorf("failed to get cached contacts: %w", err)
 	}
+	user.log.Infofln("Resyncing displaynames with %d contacts", len(contacts))
 	for jid, contact := range contacts {
 		puppet := user.bridge.GetPuppetByJID(jid)
 		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