diff --git a/go.mod b/go.mod index 463bc67e..27964e43 100644 --- a/go.mod +++ b/go.mod @@ -14,12 +14,12 @@ require ( github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/stretchr/testify v1.9.0 github.com/tidwall/gjson v1.17.3 - go.mau.fi/util v0.6.1-0.20240722085753-2d7945696c9b + go.mau.fi/util v0.6.1-0.20240802175451-b430ebbffc98 golang.org/x/crypto v0.25.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/net v0.27.0 google.golang.org/protobuf v1.34.2 - maunium.net/go/mautrix v0.19.1-0.20240801191314-7402f5a70501 + maunium.net/go/mautrix v0.19.1-0.20240804192210-9d6622c29325 nhooyr.io/websocket v1.8.11 ) @@ -43,6 +43,7 @@ require ( github.com/yuin/goldmark v1.7.4 // indirect go.mau.fi/zeroconfig v0.1.3 // indirect golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect maunium.net/go/mauflag v1.0.0 // indirect diff --git a/go.sum b/go.sum index e22a3ca8..054a6beb 100644 --- a/go.sum +++ b/go.sum @@ -67,8 +67,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -go.mau.fi/util v0.6.1-0.20240722085753-2d7945696c9b h1:8s3uTMPZts03evXLqdTJ0WXB0YWZDNSovpd6oFfCFvY= -go.mau.fi/util v0.6.1-0.20240722085753-2d7945696c9b/go.mod h1:ljYdq3sPfpICc3zMU+/mHV/sa4z0nKxc67hSBwnrk8U= +go.mau.fi/util v0.6.1-0.20240802175451-b430ebbffc98 h1:gJ0peWecBm6TtlxKFVIc1KbooXSCHtPfsfb2Eha5A0A= +go.mau.fi/util v0.6.1-0.20240802175451-b430ebbffc98/go.mod h1:S1juuPWGau2GctPY3FR/4ec/MDLhAG2QPhdnUwpzWIo= go.mau.fi/zeroconfig v0.1.3 h1:As9wYDKmktjmNZW5i1vn8zvJlmGKHeVxHVIBMXsm4kM= go.mau.fi/zeroconfig v0.1.3/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= @@ -82,6 +82,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -93,7 +95,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.19.1-0.20240801191314-7402f5a70501 h1:fikXfFmwO3azwAbBS1Js7MLs657xGZrtyAMFPri9TGc= -maunium.net/go/mautrix v0.19.1-0.20240801191314-7402f5a70501/go.mod h1:xP3DCXdPBUe1sPiugLbd5mRh/mJQWfGWyED1S8s9V7c= +maunium.net/go/mautrix v0.19.1-0.20240804192210-9d6622c29325 h1:2Ontl4ZDFytmhCKyp5io4HQD+t9bQOZod0lPwtwiXPA= +maunium.net/go/mautrix v0.19.1-0.20240804192210-9d6622c29325/go.mod h1:ZWyxoQxRTBxzWIMs0kQCVogZIY0clTu33h102veCT/Q= nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0= nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= diff --git a/pkg/connector/client.go b/pkg/connector/client.go index 2293a33e..838c0eea 100644 --- a/pkg/connector/client.go +++ b/pkg/connector/client.go @@ -18,6 +18,7 @@ type SignalClient struct { Main *SignalConnector UserLogin *bridgev2.UserLogin Client *signalmeow.Client + Ghost *bridgev2.Ghost } var signalCaps = &bridgev2.NetworkRoomCapabilities{ @@ -218,6 +219,11 @@ func (s *SignalClient) bridgeStateLoop(statusChan <-chan signalmeow.SignalConnec } func (s *SignalClient) Connect(ctx context.Context) error { + if s.Client == nil { + s.UserLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateBadCredentials, Message: "You're not logged into Signal"}) + return nil + } + s.updateRemoteProfile(ctx, false) s.tryConnect(ctx, 0) return nil } @@ -233,10 +239,6 @@ func (s *SignalClient) Disconnect() { } func (s *SignalClient) tryConnect(ctx context.Context, retryCount int) { - if s.Client == nil { - s.UserLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateBadCredentials, Message: "You're not logged into Signal"}) - return - } ch, err := s.Client.StartReceiveLoops(ctx) if err != nil { zerolog.Ctx(ctx).Err(err).Msg("Failed to start receive loops") diff --git a/pkg/connector/dbmeta.go b/pkg/connector/dbmeta.go index 18de885e..68e21d54 100644 --- a/pkg/connector/dbmeta.go +++ b/pkg/connector/dbmeta.go @@ -29,10 +29,8 @@ func (s *SignalConnector) GetDBMetaTypes() database.MetaTypes { Message: func() any { return &MessageMetadata{} }, - Reaction: nil, - UserLogin: func() any { - return &UserLoginMetadata{} - }, + Reaction: nil, + UserLogin: nil, } } @@ -43,7 +41,3 @@ type PortalMetadata struct { type MessageMetadata struct { ContainsAttachments bool `json:"contains_attachments,omitempty"` } - -type UserLoginMetadata struct { - Phone string `json:"phone"` -} diff --git a/pkg/connector/handlesignal.go b/pkg/connector/handlesignal.go index ba3f6ff0..169338dd 100644 --- a/pkg/connector/handlesignal.go +++ b/pkg/connector/handlesignal.go @@ -19,6 +19,7 @@ package connector import ( "context" "fmt" + "strings" "time" "github.com/google/uuid" @@ -485,19 +486,60 @@ func (s *SignalClient) handleSignalContactList(evt *events.ContactList) { log := s.UserLogin.Log.With().Str("action", "handle contact list").Logger() ctx := log.WithContext(context.TODO()) for _, contact := range evt.Contacts { - if contact.ACI != uuid.Nil { - fullContact, err := s.Client.ContactByACI(ctx, contact.ACI) - if err != nil { - log.Err(err).Msg("Failed to get full contact info from store") - continue - } - fullContact.ContactAvatar = contact.ContactAvatar - ghost, err := s.Main.Bridge.GetGhostByID(ctx, makeUserID(contact.ACI)) - if err != nil { - log.Err(err).Msg("Failed to get ghost to update contact info") - continue - } - ghost.UpdateInfo(ctx, s.contactToUserInfo(contact)) + if contact.ACI == uuid.Nil { + continue + } + fullContact, err := s.Client.ContactByACI(ctx, contact.ACI) + if err != nil { + log.Err(err).Msg("Failed to get full contact info from store") + continue + } + fullContact.ContactAvatar = contact.ContactAvatar + ghost, err := s.Main.Bridge.GetGhostByID(ctx, makeUserID(contact.ACI)) + if err != nil { + log.Err(err).Msg("Failed to get ghost to update contact info") + continue + } + ghost.UpdateInfo(ctx, s.contactToUserInfo(contact)) + if contact.ACI == s.Client.Store.ACI { + s.updateRemoteProfile(ctx, true) + } + } +} + +func (s *SignalClient) updateRemoteProfile(ctx context.Context, resendState bool) { + var err error + if s.Ghost == nil { + s.Ghost, err = s.Main.Bridge.GetGhostByID(ctx, makeUserID(s.Client.Store.ACI)) + if err != nil { + zerolog.Ctx(ctx).Err(err).Msg("Failed to get ghost for remote profile update") + return + } + } + changed := false + if s.UserLogin.RemoteProfile.Name != s.Ghost.Name { + s.UserLogin.RemoteProfile.Name = s.Ghost.Name + changed = true + } + if s.UserLogin.RemoteProfile.Avatar != s.Ghost.AvatarMXC { + s.UserLogin.RemoteProfile.Avatar = s.Ghost.AvatarMXC + changed = true + } + if len(s.Ghost.Identifiers) > 0 && strings.HasPrefix(s.Ghost.Identifiers[0], "tel:") { + phone := strings.TrimPrefix(s.Ghost.Identifiers[0], "tel:") + if s.UserLogin.RemoteProfile.Phone != phone { + s.UserLogin.RemoteProfile.Phone = phone + changed = true + } + } + if changed { + err = s.UserLogin.Save(ctx) + if err != nil { + zerolog.Ctx(ctx).Err(err).Msg("Failed to save updated remote profile") + } + if resendState { + // TODO this has potential race conditions + s.UserLogin.BridgeState.Send(s.UserLogin.BridgeState.GetPrevUnsent()) } } } diff --git a/pkg/connector/login.go b/pkg/connector/login.go index 82ddac51..3acd9267 100644 --- a/pkg/connector/login.go +++ b/pkg/connector/login.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/google/uuid" + "maunium.net/go/mautrix/bridge/status" "maunium.net/go/mautrix/bridgev2" "maunium.net/go/mautrix/bridgev2/database" @@ -159,7 +160,7 @@ func (qr *QRLogin) processingWait(ctx context.Context) (*bridgev2.LoginStep, err ul, err := qr.User.NewLogin(ctx, &database.UserLogin{ ID: newLoginID, RemoteName: qr.ProvData.Number, - Metadata: &UserLoginMetadata{ + RemoteProfile: status.RemoteProfile{ Phone: qr.ProvData.Number, }, }, &bridgev2.NewLoginParams{