فهرست منبع

Sync broadcast list recipients too

Tulir Asokan 4 سال پیش
والد
کامیت
ac2ca08007
4فایلهای تغییر یافته به همراه75 افزوده شده و 43 حذف شده
  1. 1 1
      custompuppet.go
  2. 1 1
      go.mod
  3. 2 0
      go.sum
  4. 71 41
      portal.go

+ 1 - 1
custompuppet.go

@@ -164,7 +164,7 @@ func (puppet *Puppet) ProcessResponse(resp *mautrix.RespSync, _ string) error {
 	}
 	for roomID, events := range resp.Rooms.Join {
 		portal := puppet.bridge.GetPortalByMXID(roomID)
-		if portal == nil {
+		if portal == nil || portal.IsBroadcastList() {
 			continue
 		}
 		for _, evt := range events.Ephemeral.Events {

+ 1 - 1
go.mod

@@ -16,4 +16,4 @@ require (
 	maunium.net/go/mautrix v0.8.3
 )
 
-replace github.com/Rhymen/go-whatsapp => github.com/tulir/go-whatsapp v0.3.22-0.20210221121735-6d3eaaa7bdc5
+replace github.com/Rhymen/go-whatsapp => github.com/tulir/go-whatsapp v0.3.22-0.20210221124355-8c89650e6a9e

+ 2 - 0
go.sum

@@ -337,6 +337,8 @@ github.com/tulir/go-whatsapp v0.3.22-0.20210221000549-ec31478c7b94 h1:G4YvxLMW80
 github.com/tulir/go-whatsapp v0.3.22-0.20210221000549-ec31478c7b94/go.mod h1:rwwuTh1bKqhgrRvOBAr8hDqtuz8Cc1Quqw/0BeXb+/E=
 github.com/tulir/go-whatsapp v0.3.22-0.20210221121735-6d3eaaa7bdc5 h1:4Y5xQdpuLEt4DQavhnP/Ium1zpwIE+LeOFwVyiW4qoY=
 github.com/tulir/go-whatsapp v0.3.22-0.20210221121735-6d3eaaa7bdc5/go.mod h1:rwwuTh1bKqhgrRvOBAr8hDqtuz8Cc1Quqw/0BeXb+/E=
+github.com/tulir/go-whatsapp v0.3.22-0.20210221124355-8c89650e6a9e h1:jQGaSyVl7gx44KYH1UY9JnhoLAqTEKysIhLjQJZZKVY=
+github.com/tulir/go-whatsapp v0.3.22-0.20210221124355-8c89650e6a9e/go.mod h1:rwwuTh1bKqhgrRvOBAr8hDqtuz8Cc1Quqw/0BeXb+/E=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=

+ 71 - 41
portal.go

@@ -359,6 +359,43 @@ func (portal *Portal) finishHandling(source *User, message *waProto.WebMessageIn
 	portal.log.Debugln("Handled message", message.GetKey().GetId(), "->", mxid)
 }
 
+func (portal *Portal) kickExtraUsers(participantMap map[whatsapp.JID]bool) {
+	members, err := portal.MainIntent().JoinedMembers(portal.MXID)
+	if err != nil {
+		portal.log.Warnln("Failed to get member list:", err)
+	} else {
+		for member := range members.Joined {
+			jid, ok := portal.bridge.ParsePuppetMXID(member)
+			if ok {
+				_, shouldBePresent := participantMap[jid]
+				if !shouldBePresent {
+					_, err := portal.MainIntent().KickUser(portal.MXID, &mautrix.ReqKickUser{
+						UserID: member,
+						Reason: "User had left this WhatsApp chat",
+					})
+					if err != nil {
+						portal.log.Warnfln("Failed to kick user %s who had left: %v", member, err)
+					}
+				}
+			}
+		}
+	}
+}
+
+func (portal *Portal) SyncBroadcastRecipients(metadata *whatsapp.BroadcastListInfo) {
+	participantMap := make(map[whatsapp.JID]bool)
+	for _, recipient := range metadata.Recipients {
+		participantMap[recipient.JID] = true
+
+		puppet := portal.bridge.GetPuppetByJID(recipient.JID)
+		err := puppet.DefaultIntent().EnsureJoined(portal.MXID)
+		if err != nil {
+			portal.log.Warnfln("Failed to make puppet of %s join %s: %v", recipient.JID, portal.MXID, err)
+		}
+	}
+	portal.kickExtraUsers(participantMap)
+}
+
 func (portal *Portal) SyncParticipants(metadata *whatsapp.GroupInfo) {
 	changed := false
 	levels, err := portal.MainIntent().PowerLevels(portal.MXID)
@@ -366,7 +403,7 @@ func (portal *Portal) SyncParticipants(metadata *whatsapp.GroupInfo) {
 		levels = portal.GetBasePowerLevels()
 		changed = true
 	}
-	participantMap := make(map[string]bool)
+	participantMap := make(map[whatsapp.JID]bool)
 	for _, participant := range metadata.Participants {
 		participantMap[participant.JID] = true
 		user := portal.bridge.GetUserByJID(participant.JID)
@@ -395,26 +432,7 @@ func (portal *Portal) SyncParticipants(metadata *whatsapp.GroupInfo) {
 			portal.log.Errorln("Failed to change power levels:", err)
 		}
 	}
-	members, err := portal.MainIntent().JoinedMembers(portal.MXID)
-	if err != nil {
-		portal.log.Warnln("Failed to get member list:", err)
-	} else {
-		for member := range members.Joined {
-			jid, ok := portal.bridge.ParsePuppetMXID(member)
-			if ok {
-				_, shouldBePresent := participantMap[jid]
-				if !shouldBePresent {
-					_, err := portal.MainIntent().KickUser(portal.MXID, &mautrix.ReqKickUser{
-						UserID: member,
-						Reason: "User had left this WhatsApp chat",
-					})
-					if err != nil {
-						portal.log.Warnfln("Failed to kick user %s who had left: %v", member, err)
-					}
-				}
-			}
-		}
-	}
+	portal.kickExtraUsers(participantMap)
 }
 
 func (portal *Portal) UpdateAvatar(user *User, avatar *whatsapp.ProfilePicInfo, updateInfo bool) bool {
@@ -469,7 +487,7 @@ func (portal *Portal) UpdateAvatar(user *User, avatar *whatsapp.ProfilePicInfo,
 }
 
 func (portal *Portal) UpdateName(name string, setBy whatsapp.JID, intent *appservice.IntentAPI, updateInfo bool) bool {
-	if name == "" && portal.IsBroadcastRoom() {
+	if name == "" && portal.IsBroadcastList() {
 		name = UnnamedBroadcastName
 	}
 	if portal.Name != name {
@@ -522,12 +540,12 @@ func (portal *Portal) UpdateTopic(topic string, setBy whatsapp.JID, intent *apps
 func (portal *Portal) UpdateMetadata(user *User) bool {
 	if portal.IsPrivateChat() {
 		return false
-	} else if portal.IsStatusBroadcastRoom() {
+	} else if portal.IsStatusBroadcastList() {
 		update := false
 		update = portal.UpdateName(StatusBroadcastName, "", nil, false) || update
 		update = portal.UpdateTopic(StatusBroadcastTopic, "", nil, false) || update
 		return update
-	} else if portal.IsBroadcastRoom() {
+	} else if portal.IsBroadcastList() {
 		update := false
 		contact, _ := user.Conn.Store.Contacts[portal.Key.JID]
 		update = portal.UpdateName(contact.Name, "", nil, false) || update
@@ -612,7 +630,7 @@ func (portal *Portal) Sync(user *User, contact whatsapp.Contact) {
 
 	update := false
 	update = portal.UpdateMetadata(user) || update
-	if !portal.IsPrivateChat() && !portal.IsBroadcastRoom() && portal.Avatar == "" {
+	if !portal.IsPrivateChat() && !portal.IsBroadcastList() && portal.Avatar == "" {
 		update = portal.UpdateAvatar(user, nil, false) || update
 	}
 	if update {
@@ -988,6 +1006,7 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
 	portal.log.Infoln("Creating Matrix room. Info source:", user.MXID)
 
 	var metadata *whatsapp.GroupInfo
+	var broadcastMetadata *whatsapp.BroadcastListInfo
 	if portal.IsPrivateChat() {
 		puppet := portal.bridge.GetPuppetByJID(portal.Key.JID)
 		if portal.bridge.Config.Bridge.PrivateChatPortalMeta {
@@ -998,14 +1017,19 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
 			portal.Name = ""
 		}
 		portal.Topic = "WhatsApp private chat"
-	} else if portal.IsStatusBroadcastRoom() {
+	} else if portal.IsStatusBroadcastList() {
 		portal.Name = "WhatsApp Status Broadcast"
 		portal.Topic = "WhatsApp status updates from your contacts"
-	} else if portal.IsBroadcastRoom() {
-		contact, ok := user.Conn.Store.Contacts[portal.Key.JID]
-		if ok {
-			portal.Name = contact.Name
+	} else if portal.IsBroadcastList() {
+		var err error
+		broadcastMetadata, err = user.Conn.GetBroadcastMetadata(portal.Key.JID)
+		if err == nil && broadcastMetadata.Status == 0 {
+			portal.Name = broadcastMetadata.Name
 		} else {
+			contact, _ := user.Conn.Store.Contacts[portal.Key.JID]
+			portal.Name = contact.Name
+		}
+		if len(portal.Name) == 0 {
 			portal.Name = UnnamedBroadcastName
 		}
 		portal.Topic = BroadcastTopic
@@ -1097,6 +1121,9 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
 			_ = customPuppet.CustomIntent().EnsureJoined(portal.MXID)
 		}
 	}
+	if broadcastMetadata != nil {
+		portal.SyncBroadcastRecipients(broadcastMetadata)
+	}
 	user.addPortalToCommunity(portal)
 	if portal.IsPrivateChat() {
 		puppet := user.bridge.GetPuppetByJID(portal.Key.JID)
@@ -1126,7 +1153,7 @@ func (portal *Portal) IsPrivateChat() bool {
 	return *portal.isPrivate
 }
 
-func (portal *Portal) IsBroadcastRoom() bool {
+func (portal *Portal) IsBroadcastList() bool {
 	if portal.isBroadcast == nil {
 		val := strings.HasSuffix(portal.Key.JID, whatsapp.BroadcastSuffix)
 		portal.isBroadcast = &val
@@ -1134,7 +1161,7 @@ func (portal *Portal) IsBroadcastRoom() bool {
 	return *portal.isBroadcast
 }
 
-func (portal *Portal) IsStatusBroadcastRoom() bool {
+func (portal *Portal) IsStatusBroadcastList() bool {
 	return portal.Key.JID == "status@broadcast"
 }
 
@@ -1310,8 +1337,9 @@ func (portal *Portal) HandleTextMessage(source *User, message whatsapp.TextMessa
 }
 
 func (portal *Portal) HandleStubMessage(source *User, message whatsapp.StubMessage, isBackfill bool) {
-	if portal.bridge.Config.Bridge.ChatMetaSync {
+	if portal.bridge.Config.Bridge.ChatMetaSync && (!portal.IsBroadcastList() || isBackfill) {
 		// Chat meta sync is enabled, so we use chat update commands and full-syncs instead of message history
+		// However, broadcast lists don't have update commands, so we handle these if it's not a backfill
 		return
 	}
 	intent := portal.startHandling(source, message.Info)
@@ -1341,9 +1369,9 @@ func (portal *Portal) HandleStubMessage(source *User, message whatsapp.StubMessa
 		eventID = portal.RestrictMessageSending(message.FirstParam == "on")
 	case waProto.WebMessageInfo_GROUP_CHANGE_RESTRICT:
 		eventID = portal.RestrictMetadataChanges(message.FirstParam == "on")
-	case waProto.WebMessageInfo_GROUP_PARTICIPANT_ADD, waProto.WebMessageInfo_GROUP_PARTICIPANT_INVITE:
+	case waProto.WebMessageInfo_GROUP_PARTICIPANT_ADD, waProto.WebMessageInfo_GROUP_PARTICIPANT_INVITE, waProto.WebMessageInfo_BROADCAST_ADD:
 		portal.HandleWhatsAppInvite(senderJID, intent, message.Params)
-	case waProto.WebMessageInfo_GROUP_PARTICIPANT_REMOVE, waProto.WebMessageInfo_GROUP_PARTICIPANT_LEAVE:
+	case waProto.WebMessageInfo_GROUP_PARTICIPANT_REMOVE, waProto.WebMessageInfo_GROUP_PARTICIPANT_LEAVE, waProto.WebMessageInfo_BROADCAST_REMOVE:
 		portal.HandleWhatsAppKick(source, senderJID, message.Params)
 	case waProto.WebMessageInfo_GROUP_PARTICIPANT_PROMOTE:
 		eventID = portal.ChangeAdminStatus(message.Params, true)
@@ -1525,13 +1553,15 @@ func (portal *Portal) HandleWhatsAppKick(source *User, senderJID string, jids []
 		puppet := portal.bridge.GetPuppetByJID(jid)
 		portal.removeUser(puppet.JID == sender.JID, senderIntent, puppet.MXID, puppet.DefaultIntent())
 
-		user := portal.bridge.GetUserByJID(jid)
-		if user != nil {
-			var customIntent *appservice.IntentAPI
-			if puppet.CustomMXID == user.MXID {
-				customIntent = puppet.CustomIntent()
+		if !portal.IsBroadcastList() {
+			user := portal.bridge.GetUserByJID(jid)
+			if user != nil {
+				var customIntent *appservice.IntentAPI
+				if puppet.CustomMXID == user.MXID {
+					customIntent = puppet.CustomIntent()
+				}
+				portal.removeUser(puppet.JID == sender.JID, senderIntent, user.MXID, customIntent)
 			}
-			portal.removeUser(puppet.JID == sender.JID, senderIntent, user.MXID, customIntent)
 		}
 	}
 }