Bläddra i källkod

Fix desegregation changes to make the bridge work again

Tulir Asokan 6 år sedan
förälder
incheckning
22cdf519f2
9 ändrade filer med 89 tillägg och 50 borttagningar
  1. 1 1
      commands.go
  2. 6 6
      database/message.go
  3. 3 1
      database/portal.go
  4. 4 1
      database/puppet.go
  5. 33 17
      database/user.go
  6. 2 1
      formatting.go
  7. 4 4
      main.go
  8. 26 14
      portal.go
  9. 10 5
      user.go

+ 1 - 1
commands.go

@@ -56,7 +56,7 @@ func (handler *CommandHandler) Handle(roomID types.MatrixRoomID, user *User, mes
 	args := strings.Split(message, " ")
 	cmd := strings.ToLower(args[0])
 	ce := &CommandEvent{
-		Bot:     handler.bridge.AS.BotIntent(),
+		Bot:     handler.bridge.Bot,
 		Bridge:  handler.bridge,
 		Handler: handler,
 		RoomID:  roomID,

+ 6 - 6
database/message.go

@@ -30,12 +30,12 @@ type MessageQuery struct {
 
 func (mq *MessageQuery) CreateTable() error {
 	_, err := mq.db.Exec(`CREATE TABLE IF NOT EXISTS message (
-		chat_jid      VARCHAR(25) NOT NULL,
-		chat_receiver VARCHAR(25) NOT NULL,
-		jid  VARCHAR(255) NOT NULL,
+		chat_jid      VARCHAR(25),
+		chat_receiver VARCHAR(25),
+		jid  VARCHAR(255),
 		mxid VARCHAR(255) NOT NULL UNIQUE,
 
-		PRIMARY KEY (chat_jid, jid),
+		PRIMARY KEY (chat_jid, chat_receiver, jid),
 		FOREIGN KEY (chat_jid, chat_receiver) REFERENCES portal(jid, receiver)
 	)`)
 	return err
@@ -97,9 +97,9 @@ func (msg *Message) Scan(row Scannable) *Message {
 }
 
 func (msg *Message) Insert() error {
-	_, err := msg.db.Exec("INSERT INTO message VALUES (?, ?, ?)", msg.Chat.JID, msg.Chat.Receiver, msg.JID, msg.MXID)
+	_, err := msg.db.Exec("INSERT INTO message VALUES (?, ?, ?, ?)", msg.Chat.JID, msg.Chat.Receiver, msg.JID, msg.MXID)
 	if err != nil {
-		msg.log.Warnfln("Failed to update %s: %v", msg.Chat, msg.JID, err)
+		msg.log.Warnfln("Failed to insert %s: %v", msg.Chat, msg.JID, err)
 	}
 	return err
 }

+ 3 - 1
database/portal.go

@@ -122,13 +122,15 @@ type Portal struct {
 }
 
 func (portal *Portal) Scan(row Scannable) *Portal {
-	err := row.Scan(&portal.Key.JID, &portal.Key.Receiver, &portal.MXID, &portal.Name, &portal.Topic, &portal.Avatar)
+	var mxid sql.NullString
+	err := row.Scan(&portal.Key.JID, &portal.Key.Receiver, &mxid, &portal.Name, &portal.Topic, &portal.Avatar)
 	if err != nil {
 		if err != sql.ErrNoRows {
 			portal.log.Errorln("Database scan failed:", err)
 		}
 		return nil
 	}
+	portal.MXID = mxid.String
 	return portal
 }
 

+ 4 - 1
database/puppet.go

@@ -74,13 +74,16 @@ type Puppet struct {
 }
 
 func (puppet *Puppet) Scan(row Scannable) *Puppet {
-	err := row.Scan(&puppet.JID, &puppet.Displayname, &puppet.Avatar)
+	var displayname, avatar sql.NullString
+	err := row.Scan(&puppet.JID, &displayname, &avatar)
 	if err != nil {
 		if err != sql.ErrNoRows {
 			puppet.log.Errorln("Database scan failed:", err)
 		}
 		return nil
 	}
+	puppet.Displayname = displayname.String
+	puppet.Avatar = avatar.String
 	return puppet
 }
 

+ 33 - 17
database/user.go

@@ -18,10 +18,12 @@ package database
 
 import (
 	"database/sql"
+	"strings"
 
 	"github.com/Rhymen/go-whatsapp"
 	log "maunium.net/go/maulogger"
 	"maunium.net/go/mautrix-whatsapp/types"
+	"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
 )
 
 type UserQuery struct {
@@ -40,8 +42,7 @@ func (uq *UserQuery) CreateTable() error {
 		client_token VARCHAR(255),
 		server_token VARCHAR(255),
 		enc_key      BLOB,
-		mac_key      BLOB,
-		wid          VARCHAR(255)
+		mac_key      BLOB
 	)`)
 	return err
 }
@@ -74,7 +75,7 @@ func (uq *UserQuery) GetByMXID(userID types.MatrixUserID) *User {
 }
 
 func (uq *UserQuery) GetByJID(userID types.WhatsAppID) *User {
-	row := uq.db.QueryRow("SELECT * FROM user WHERE jid=?", userID)
+	row := uq.db.QueryRow("SELECT * FROM user WHERE jid=?", stripSuffix(userID))
 	if row == nil {
 		return nil
 	}
@@ -92,28 +93,42 @@ type User struct {
 }
 
 func (user *User) Scan(row Scannable) *User {
-	sess := whatsapp.Session{}
-	err := row.Scan(&user.MXID, &user.JID, &user.ManagementRoom, &sess.ClientId, &sess.ClientToken, &sess.ServerToken,
-		&sess.EncKey, &sess.MacKey, &sess.Wid)
+	var managementRoom, clientID, clientToken, serverToken, jid sql.NullString
+	var encKey, macKey []byte
+	err := row.Scan(&user.MXID, &jid, &managementRoom, &clientID, &clientToken, &serverToken, &encKey, &macKey)
 	if err != nil {
 		if err != sql.ErrNoRows {
 			user.log.Errorln("Database scan failed:", err)
 		}
 		return nil
 	}
-	if len(sess.ClientId) > 0 {
-		user.Session = &sess
+	if len(jid.String) > 0 && len(clientID.String) > 0 {
+		user.JID = jid.String + whatsappExt.NewUserSuffix
+		user.Session = &whatsapp.Session{
+			ClientId:    clientID.String,
+			ClientToken: clientToken.String,
+			ServerToken: serverToken.String,
+			EncKey:      encKey,
+			MacKey:      macKey,
+			Wid:         jid.String + whatsappExt.OldUserSuffix,
+		}
 	} else {
 		user.Session = nil
 	}
 	return user
 }
 
-func (user *User) jidPtr() *string {
-	if len(user.JID) > 0 {
-		return &user.JID
+func stripSuffix(jid types.WhatsAppID) string {
+	if len(jid) == 0 {
+		return jid
+	}
+
+	index := strings.IndexRune(jid, '@')
+	if index < 0 {
+		return jid
 	}
-	return nil
+
+	return jid[:index]
 }
 
 func (user *User) sessionUnptr() (sess whatsapp.Session) {
@@ -125,16 +140,17 @@ func (user *User) sessionUnptr() (sess whatsapp.Session) {
 
 func (user *User) Insert() error {
 	sess := user.sessionUnptr()
-	_, err := user.db.Exec("INSERT INTO user VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", user.MXID, user.jidPtr(), user.ManagementRoom,
-		sess.ClientId, sess.ClientToken, sess.ServerToken, sess.EncKey, sess.MacKey, sess.Wid)
+	_, err := user.db.Exec("INSERT INTO user VALUES (?, ?, ?, ?, ?, ?, ?, ?)", user.MXID, stripSuffix(user.JID),
+		user.ManagementRoom,
+		sess.ClientId, sess.ClientToken, sess.ServerToken, sess.EncKey, sess.MacKey)
 	return err
 }
 
 func (user *User) Update() error {
 	sess := user.sessionUnptr()
-	_, err := user.db.Exec("UPDATE user SET jid=?, management_room=?, client_id=?, client_token=?, server_token=?, enc_key=?, mac_key=?, wid=? WHERE mxid=?",
-		user.jidPtr(), user.ManagementRoom,
-		sess.ClientId, sess.ClientToken, sess.ServerToken, sess.EncKey, sess.MacKey, sess.Wid,
+	_, err := user.db.Exec("UPDATE user SET jid=?, management_room=?, client_id=?, client_token=?, server_token=?, enc_key=?, mac_key=? WHERE mxid=?",
+		stripSuffix(user.JID), user.ManagementRoom,
+		sess.ClientId, sess.ClientToken, sess.ServerToken, sess.EncKey, sess.MacKey,
 		user.MXID)
 	return err
 }

+ 2 - 1
formatting.go

@@ -24,6 +24,7 @@ import (
 
 	"maunium.net/go/gomatrix"
 	"maunium.net/go/gomatrix/format"
+	"maunium.net/go/mautrix-whatsapp/types"
 	"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
 )
 
@@ -104,7 +105,7 @@ func NewFormatter(bridge *Bridge) *Formatter {
 	return formatter
 }
 
-func (formatter *Formatter) getMatrixInfoByJID(jid string) (mxid, displayname string) {
+func (formatter *Formatter) getMatrixInfoByJID(jid types.WhatsAppID) (mxid, displayname string) {
 	if user := formatter.bridge.GetUserByJID(jid); user != nil {
 		mxid = user.MXID
 		displayname = user.MXID

+ 4 - 4
main.go

@@ -165,18 +165,18 @@ func (bridge *Bridge) UpdateBotProfile() {
 
 	var err error
 	if botConfig.Avatar == "remove" {
-		err = bridge.AS.BotIntent().SetAvatarURL("")
+		err = bridge.Bot.SetAvatarURL("")
 	} else if len(botConfig.Avatar) > 0 {
-		err = bridge.AS.BotIntent().SetAvatarURL(botConfig.Avatar)
+		err = bridge.Bot.SetAvatarURL(botConfig.Avatar)
 	}
 	if err != nil {
 		bridge.Log.Warnln("Failed to update bot avatar:", err)
 	}
 
 	if botConfig.Displayname == "remove" {
-		err = bridge.AS.BotIntent().SetDisplayName("")
+		err = bridge.Bot.SetDisplayName("")
 	} else if len(botConfig.Avatar) > 0 {
-		err = bridge.AS.BotIntent().SetDisplayName(botConfig.Displayname)
+		err = bridge.Bot.SetDisplayName(botConfig.Displayname)
 	}
 	if err != nil {
 		bridge.Log.Warnln("Failed to update bot displayname:", err)

+ 26 - 14
portal.go

@@ -126,7 +126,7 @@ func (portal *Portal) SyncParticipants(metadata *whatsappExt.GroupInfo) {
 		puppet.Intent().EnsureJoined(portal.MXID)
 
 		user := portal.bridge.GetUserByJID(participant.JID)
-		if !portal.bridge.AS.StateStore.IsInvited(portal.MXID, user.MXID) {
+		if user != nil && !portal.bridge.AS.StateStore.IsInvited(portal.MXID, user.MXID) {
 			portal.MainIntent().InviteUser(portal.MXID, &gomatrix.ReqInviteUser{
 				UserID: user.MXID,
 			})
@@ -144,7 +144,10 @@ func (portal *Portal) SyncParticipants(metadata *whatsappExt.GroupInfo) {
 		}
 	}
 	if changed {
-		portal.MainIntent().SetPowerLevels(portal.MXID, levels)
+		_, err = portal.MainIntent().SetPowerLevels(portal.MXID, levels)
+		if err != nil {
+			portal.log.Errorln("Failed to change power levels:", err)
+		}
 	}
 }
 
@@ -258,10 +261,10 @@ func (portal *Portal) GetBasePowerLevels() *gomatrix.PowerLevels {
 		Users: map[string]int{
 			portal.MainIntent().UserID: 100,
 		},
-		Events: map[gomatrix.EventType]int{
-			gomatrix.StateRoomName:   anyone,
-			gomatrix.StateRoomAvatar: anyone,
-			gomatrix.StateTopic:      anyone,
+		Events: map[string]int{
+			gomatrix.StateRoomName.Type:   anyone,
+			gomatrix.StateRoomAvatar.Type: anyone,
+			gomatrix.StateTopic.Type:      anyone,
 		},
 	}
 }
@@ -286,7 +289,10 @@ func (portal *Portal) ChangeAdminStatus(jids []string, setAdmin bool) {
 		}
 	}
 	if changed {
-		portal.MainIntent().SetPowerLevels(portal.MXID, levels)
+		_, err = portal.MainIntent().SetPowerLevels(portal.MXID, levels)
+		if err != nil {
+			portal.log.Errorln("Failed to change power levels:", err)
+		}
 	}
 }
 
@@ -300,7 +306,10 @@ func (portal *Portal) RestrictMessageSending(restrict bool) {
 	} else {
 		levels.EventsDefault = 0
 	}
-	portal.MainIntent().SetPowerLevels(portal.MXID, levels)
+	_, err = portal.MainIntent().SetPowerLevels(portal.MXID, levels)
+	if err != nil {
+		portal.log.Errorln("Failed to change power levels:", err)
+	}
 }
 
 func (portal *Portal) RestrictMetadataChanges(restrict bool) {
@@ -317,7 +326,10 @@ func (portal *Portal) RestrictMetadataChanges(restrict bool) {
 	changed = levels.EnsureEventLevel(gomatrix.StateRoomAvatar, newLevel) || changed
 	changed = levels.EnsureEventLevel(gomatrix.StateTopic, newLevel) || changed
 	if changed {
-		portal.MainIntent().SetPowerLevels(portal.MXID, levels)
+		_, err = portal.MainIntent().SetPowerLevels(portal.MXID, levels)
+		if err != nil {
+			portal.log.Errorln("Failed to change power levels:", err)
+		}
 	}
 }
 
@@ -367,7 +379,7 @@ func (portal *Portal) MainIntent() *appservice.IntentAPI {
 	if portal.IsPrivateChat() {
 		return portal.bridge.GetPuppetByJID(portal.Key.JID).Intent()
 	}
-	return portal.bridge.AS.BotIntent()
+	return portal.bridge.Bot
 }
 
 func (portal *Portal) IsDuplicate(id types.WhatsAppMessageID) bool {
@@ -386,13 +398,13 @@ func (portal *Portal) MarkHandled(jid types.WhatsAppMessageID, mxid types.Matrix
 	msg.Insert()
 }
 
-func (portal *Portal) GetMessageIntent(info whatsapp.MessageInfo) *appservice.IntentAPI {
+func (portal *Portal) GetMessageIntent(user *User, info whatsapp.MessageInfo) *appservice.IntentAPI {
 	if info.FromMe {
 		if portal.IsPrivateChat() {
 			// TODO handle own messages in private chats properly
 			return nil
 		}
-		return portal.bridge.GetPuppetByJID(portal.Key.Receiver).Intent()
+		return portal.bridge.GetPuppetByJID(user.JID).Intent()
 	} else if portal.IsPrivateChat() {
 		return portal.MainIntent()
 	} else if len(info.SenderJid) == 0 {
@@ -432,7 +444,7 @@ func (portal *Portal) HandleTextMessage(source *User, message whatsapp.TextMessa
 		return
 	}
 
-	intent := portal.GetMessageIntent(message.Info)
+	intent := portal.GetMessageIntent(source, message.Info)
 	if intent == nil {
 		return
 	}
@@ -466,7 +478,7 @@ func (portal *Portal) HandleMediaMessage(source *User, download func() ([]byte,
 		return
 	}
 
-	intent := portal.GetMessageIntent(info)
+	intent := portal.GetMessageIntent(source, info)
 	if intent == nil {
 		return
 	}

+ 10 - 5
user.go

@@ -37,7 +37,6 @@ type User struct {
 
 	Admin       bool
 	Whitelisted bool
-	jid         string
 }
 
 func (bridge *Bridge) GetUserByMXID(userID types.MatrixUserID) *User {
@@ -53,6 +52,9 @@ func (bridge *Bridge) GetUserByMXID(userID types.MatrixUserID) *User {
 		}
 		user = bridge.NewUser(dbUser)
 		bridge.usersByMXID[user.MXID] = user
+		if len(user.JID) > 0 {
+			bridge.usersByJID[user.JID] = user
+		}
 		if len(user.ManagementRoom) > 0 {
 			bridge.managementRooms[user.ManagementRoom] = user
 		}
@@ -66,13 +68,12 @@ func (bridge *Bridge) GetUserByJID(userID types.WhatsAppID) *User {
 	defer bridge.usersLock.Unlock()
 	user, ok := bridge.usersByJID[userID]
 	if !ok {
-		dbUser := bridge.DB.User.GetByMXID(userID)
+		dbUser := bridge.DB.User.GetByJID(userID)
 		if dbUser == nil {
-			dbUser = bridge.DB.User.New()
-			dbUser.MXID = userID
-			dbUser.Insert()
+			return nil
 		}
 		user = bridge.NewUser(dbUser)
+		bridge.usersByMXID[user.MXID] = user
 		bridge.usersByJID[user.JID] = user
 		if len(user.ManagementRoom) > 0 {
 			bridge.managementRooms[user.ManagementRoom] = user
@@ -91,6 +92,9 @@ func (bridge *Bridge) GetAllUsers() []*User {
 		if !ok {
 			user = bridge.NewUser(dbUser)
 			bridge.usersByMXID[user.MXID] = user
+			if len(user.JID) > 0 {
+				bridge.usersByJID[user.JID] = user
+			}
 			if len(user.ManagementRoom) > 0 {
 				bridge.managementRooms[user.ManagementRoom] = user
 			}
@@ -147,6 +151,7 @@ func (user *User) Connect(evenIfNoSession bool) bool {
 		return false
 	}
 	user.Conn = whatsappExt.ExtendConn(conn)
+	user.Conn.SetClientName("Mautrix-WhatsApp bridge", "mx-wa")
 	user.log.Debugln("WhatsApp connection successful")
 	user.Conn.AddHandler(user)
 	return user.RestoreSession()