forked from MirrorHub/mautrix-whatsapp
Add support for automatic double puppeting from other servers
This commit is contained in:
parent
348b7bfe7b
commit
de9977b7d2
5 changed files with 71 additions and 38 deletions
|
@ -46,11 +46,15 @@ type BridgeConfig struct {
|
|||
UserAvatarSync bool `yaml:"user_avatar_sync"`
|
||||
BridgeMatrixLeave bool `yaml:"bridge_matrix_leave"`
|
||||
|
||||
SyncWithCustomPuppets bool `yaml:"sync_with_custom_puppets"`
|
||||
SyncDirectChatList bool `yaml:"sync_direct_chat_list"`
|
||||
DefaultBridgeReceipts bool `yaml:"default_bridge_receipts"`
|
||||
DefaultBridgePresence bool `yaml:"default_bridge_presence"`
|
||||
LoginSharedSecret string `yaml:"login_shared_secret"`
|
||||
SyncWithCustomPuppets bool `yaml:"sync_with_custom_puppets"`
|
||||
SyncDirectChatList bool `yaml:"sync_direct_chat_list"`
|
||||
DefaultBridgeReceipts bool `yaml:"default_bridge_receipts"`
|
||||
DefaultBridgePresence bool `yaml:"default_bridge_presence"`
|
||||
|
||||
DoublePuppetServerMap map[string]string `yaml:"double_puppet_server_map"`
|
||||
DoublePuppetAllowDiscovery bool `yaml:"double_puppet_allow_discovery"`
|
||||
LoginSharedSecretMap map[string]string `yaml:"login_shared_secret_map"`
|
||||
LegacyLoginSharedSecret string `yaml:"login_shared_secret"`
|
||||
|
||||
PrivateChatPortalMeta bool `yaml:"private_chat_portal_meta"`
|
||||
BridgeNotices bool `yaml:"bridge_notices"`
|
||||
|
@ -92,8 +96,6 @@ type BridgeConfig struct {
|
|||
|
||||
Relay RelaybotConfig `yaml:"relay"`
|
||||
|
||||
DoublePuppetServerMap map[string]string `yaml:"double_puppet_server_map"`
|
||||
|
||||
usernameTemplate *template.Template `yaml:"-"`
|
||||
displaynameTemplate *template.Template `yaml:"-"`
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"os"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"maunium.net/go/mautrix/id"
|
||||
|
||||
"maunium.net/go/mautrix/appservice"
|
||||
|
@ -80,15 +81,10 @@ type Config struct {
|
|||
Logging appservice.LogConfig `yaml:"logging"`
|
||||
}
|
||||
|
||||
func (config *Config) CanDoublePuppet(userID id.UserID) bool {
|
||||
if len(config.Bridge.LoginSharedSecret) == 0 {
|
||||
// Automatic login not enabled
|
||||
return false
|
||||
} else if _, homeserver, _ := userID.Parse(); homeserver != config.Homeserver.Domain {
|
||||
// user is on another homeserver
|
||||
return false
|
||||
}
|
||||
return true
|
||||
func (config *Config) CanAutoDoublePuppet(userID id.UserID) bool {
|
||||
_, homeserver, _ := userID.Parse()
|
||||
_, hasSecret := config.Bridge.LoginSharedSecretMap[homeserver]
|
||||
return hasSecret
|
||||
}
|
||||
|
||||
func Load(path string) (*Config, error) {
|
||||
|
@ -103,6 +99,14 @@ func Load(path string) (*Config, error) {
|
|||
return nil, fmt.Errorf("failed to unmarshal example config: %w", err)
|
||||
}
|
||||
err = yaml.Unmarshal(data, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(config.Bridge.LegacyLoginSharedSecret) > 0 {
|
||||
config.Bridge.LoginSharedSecretMap[config.Homeserver.Domain] = config.Bridge.LegacyLoginSharedSecret
|
||||
}
|
||||
|
||||
return config, err
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go.mau.fi/whatsmeow/types"
|
||||
|
@ -64,10 +65,15 @@ func (puppet *Puppet) SwitchCustomMXID(accessToken string, mxid id.UserID) error
|
|||
}
|
||||
|
||||
func (puppet *Puppet) loginWithSharedSecret(mxid id.UserID) (string, error) {
|
||||
_, homeserver, _ := mxid.Parse()
|
||||
puppet.log.Debugfln("Logging into %s with shared secret", mxid)
|
||||
mac := hmac.New(sha512.New, []byte(puppet.bridge.Config.Bridge.LoginSharedSecret))
|
||||
mac := hmac.New(sha512.New, []byte(puppet.bridge.Config.Bridge.LoginSharedSecretMap[homeserver]))
|
||||
mac.Write([]byte(mxid))
|
||||
resp, err := puppet.bridge.AS.BotClient().Login(&mautrix.ReqLogin{
|
||||
client, err := puppet.bridge.newDoublePuppetClient(mxid, "")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create mautrix client to log in: %v", err)
|
||||
}
|
||||
resp, err := client.Login(&mautrix.ReqLogin{
|
||||
Type: mautrix.AuthTypePassword,
|
||||
Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: string(mxid)},
|
||||
Password: hex.EncodeToString(mac.Sum(nil)),
|
||||
|
@ -80,26 +86,44 @@ func (puppet *Puppet) loginWithSharedSecret(mxid id.UserID) (string, error) {
|
|||
return resp.AccessToken, nil
|
||||
}
|
||||
|
||||
func (bridge *Bridge) newDoublePuppetClient(mxid id.UserID, accessToken string) (*mautrix.Client, error) {
|
||||
_, homeserver, err := mxid.Parse()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
homeserverURL, found := bridge.Config.Bridge.DoublePuppetServerMap[homeserver]
|
||||
if !found {
|
||||
if homeserver == bridge.AS.HomeserverDomain {
|
||||
homeserverURL = bridge.AS.HomeserverURL
|
||||
} else if bridge.Config.Bridge.DoublePuppetAllowDiscovery {
|
||||
resp, err := mautrix.DiscoverClientAPI(homeserver)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find homeserver URL for %s: %v", homeserver, err)
|
||||
}
|
||||
homeserverURL = resp.Homeserver.BaseURL
|
||||
bridge.Log.Debugfln("Discovered URL %s for %s to enable double puppeting for %s", homeserverURL, homeserver, mxid)
|
||||
} else {
|
||||
return nil, fmt.Errorf("double puppeting from %s is not allowed", homeserver)
|
||||
}
|
||||
}
|
||||
client, err := mautrix.NewClient(homeserverURL, mxid, accessToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.Logger = bridge.AS.Log.Sub(mxid.String())
|
||||
client.Client = bridge.AS.HTTPClient
|
||||
client.DefaultHTTPRetries = bridge.AS.DefaultHTTPRetries
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (puppet *Puppet) newCustomIntent() (*appservice.IntentAPI, error) {
|
||||
if len(puppet.CustomMXID) == 0 {
|
||||
return nil, ErrNoCustomMXID
|
||||
}
|
||||
_, homeserver, err := puppet.CustomMXID.Parse()
|
||||
client, err := puppet.bridge.newDoublePuppetClient(puppet.CustomMXID, puppet.AccessToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
homeserverUrl, found := puppet.bridge.Config.Bridge.DoublePuppetServerMap[homeserver]
|
||||
if !found {
|
||||
puppet.log.Debugfln("Homeserver not found in double puppet server map. Using local homeserver")
|
||||
homeserverUrl = puppet.bridge.AS.HomeserverURL
|
||||
}
|
||||
client, err := mautrix.NewClient(homeserverUrl, puppet.CustomMXID, puppet.AccessToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.Logger = puppet.bridge.AS.Log.Sub(string(puppet.CustomMXID))
|
||||
client.Client = puppet.bridge.AS.HTTPClient
|
||||
client.DefaultHTTPRetries = puppet.bridge.AS.DefaultHTTPRetries
|
||||
client.Syncer = puppet
|
||||
client.Store = puppet
|
||||
|
||||
|
@ -264,7 +288,7 @@ func (puppet *Puppet) handleTypingEvent(portal *Portal, evt *event.Event) {
|
|||
}
|
||||
|
||||
func (puppet *Puppet) tryRelogin(cause error, action string) bool {
|
||||
if !puppet.bridge.Config.CanDoublePuppet(puppet.CustomMXID) {
|
||||
if !puppet.bridge.Config.CanAutoDoublePuppet(puppet.CustomMXID) {
|
||||
return false
|
||||
}
|
||||
puppet.log.Debugfln("Trying to relogin after '%v' while %s", cause, action)
|
||||
|
|
|
@ -124,12 +124,18 @@ bridge:
|
|||
# Existing users won't be affected when these are changed.
|
||||
default_bridge_receipts: true
|
||||
default_bridge_presence: true
|
||||
# Shared secret for https://github.com/devture/matrix-synapse-shared-secret-auth
|
||||
# Servers to always allow double puppeting from
|
||||
double_puppet_server_map:
|
||||
example.com: https://example.com
|
||||
# Allow using double puppeting from any server with a valid client .well-known file.
|
||||
double_puppet_allow_discovery: false
|
||||
# Shared secrets for https://github.com/devture/matrix-synapse-shared-secret-auth
|
||||
#
|
||||
# If set, double puppeting will be enabled automatically for local users
|
||||
# instead of users having to find an access token and run `login-matrix`
|
||||
# manually.
|
||||
login_shared_secret: null
|
||||
login_shared_secret_map:
|
||||
example.com: foobar
|
||||
|
||||
# Should the bridge explicitly set the avatar and room name for private chat portal rooms?
|
||||
private_chat_portal_meta: false
|
||||
|
@ -216,9 +222,6 @@ bridge:
|
|||
"example.com": user
|
||||
"@admin:example.com": admin
|
||||
|
||||
double_puppet_server_map:
|
||||
"matrix.org": https://matrix.org
|
||||
|
||||
relay:
|
||||
# Whether relay mode should be allowed. If allowed, `!wa set-relay` can be used to turn any
|
||||
# authenticated user into a relaybot for that chat.
|
||||
|
|
2
user.go
2
user.go
|
@ -299,7 +299,7 @@ func (user *User) IsLoggedIn() bool {
|
|||
}
|
||||
|
||||
func (user *User) tryAutomaticDoublePuppeting() {
|
||||
if !user.bridge.Config.CanDoublePuppet(user.MXID) {
|
||||
if !user.bridge.Config.CanAutoDoublePuppet(user.MXID) {
|
||||
return
|
||||
}
|
||||
user.log.Debugln("Checking if double puppeting needs to be enabled")
|
||||
|
|
Loading…
Reference in a new issue