From 5883ade9d881015902ec001fce5b0d5178f9f897 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 28 Jun 2024 23:13:52 +0300 Subject: [PATCH] v2: add support for changing group name/avatar/topic from Matrix --- go.mod | 2 +- go.sum | 4 +- pkg/connector/client.go | 3 ++ pkg/connector/handlematrix.go | 78 ++++++++++++++++++++++++++++++++++- 4 files changed, 82 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index b4f8e160..16d31e0a 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 golang.org/x/net v0.26.0 google.golang.org/protobuf v1.34.2 - maunium.net/go/mautrix v0.19.0-beta.1.0.20240628154312-d7251a4c6950 + maunium.net/go/mautrix v0.19.0-beta.1.0.20240628200158-86ac5c340b35 nhooyr.io/websocket v1.8.11 ) diff --git a/go.sum b/go.sum index 8ae9f4b8..6a6b6f9f 100644 --- a/go.sum +++ b/go.sum @@ -93,7 +93,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.0-beta.1.0.20240628154312-d7251a4c6950 h1:A43PQ5ltou4KhcCMxZz1gb3QXrhOjVKweYDW5YQ/Gok= -maunium.net/go/mautrix v0.19.0-beta.1.0.20240628154312-d7251a4c6950/go.mod h1:eu/C1dTewrW7yiFNiCKGm4zuWJANyt7zPjaY5g3f3r4= +maunium.net/go/mautrix v0.19.0-beta.1.0.20240628200158-86ac5c340b35 h1:ghI1MLQc4JS0ov31rpjuHrCwqVP7b+4wZfwXsD/5i0k= +maunium.net/go/mautrix v0.19.0-beta.1.0.20240628200158-86ac5c340b35/go.mod h1:eu/C1dTewrW7yiFNiCKGm4zuWJANyt7zPjaY5g3f3r4= 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 285e2076..0b92901a 100644 --- a/pkg/connector/client.go +++ b/pkg/connector/client.go @@ -53,6 +53,9 @@ var ( _ bridgev2.IdentifierResolvingNetworkAPI = (*SignalClient)(nil) _ bridgev2.GroupCreatingNetworkAPI = (*SignalClient)(nil) _ bridgev2.ContactListingNetworkAPI = (*SignalClient)(nil) + _ bridgev2.RoomNameHandlingNetworkAPI = (*SignalClient)(nil) + _ bridgev2.RoomAvatarHandlingNetworkAPI = (*SignalClient)(nil) + _ bridgev2.RoomTopicHandlingNetworkAPI = (*SignalClient)(nil) ) var pushCfg = &bridgev2.PushConfig{ diff --git a/pkg/connector/handlematrix.go b/pkg/connector/handlematrix.go index a3203ccc..41b5ecd0 100644 --- a/pkg/connector/handlematrix.go +++ b/pkg/connector/handlematrix.go @@ -18,6 +18,7 @@ package connector import ( "context" + "crypto/sha256" "errors" "fmt" "time" @@ -286,8 +287,81 @@ func (s *SignalClient) HandleMatrixTyping(ctx context.Context, typing *bridgev2. if !userID.IsEmpty() && userID.Type == libsignalgo.ServiceIDTypeACI { typingMessage := signalmeow.TypingMessage(typing.IsTyping) result := s.Client.SendMessage(ctx, userID, typingMessage) - fmt.Println(result) - // TODO check result + if !result.WasSuccessful { + return result.Error + } } return nil } + +func (s *SignalClient) handleMatrixRoomMeta(ctx context.Context, portal *bridgev2.Portal, gc *signalmeow.GroupChange, postUpdatePortal func()) (bool, error) { + _, groupID, err := parsePortalID(portal.ID) + if err != nil || groupID == "" { + return false, err + } + rev, ok := database.GetNumberFromMap[uint32](portal.Metadata.Extra, "revision") + if !ok { + return false, fmt.Errorf("missing revision in portal metadata") + } + gc.Revision = rev + 1 + revision, err := s.Client.UpdateGroup(ctx, gc, groupID) + if err != nil { + return false, err + } + if gc.ModifyTitle != nil { + portal.Name = *gc.ModifyTitle + portal.NameSet = true + } + if gc.ModifyDescription != nil { + portal.Topic = *gc.ModifyDescription + portal.TopicSet = true + } + if gc.ModifyAvatar != nil { + portal.AvatarID = makeAvatarPathID(*gc.ModifyAvatar) + portal.AvatarSet = true + } + if postUpdatePortal != nil { + postUpdatePortal() + } + portal.Metadata.Extra["revision"] = revision + return true, nil +} + +func (s *SignalClient) HandleMatrixRoomName(ctx context.Context, msg *bridgev2.MatrixRoomName) (bool, error) { + return s.handleMatrixRoomMeta(ctx, msg.Portal, &signalmeow.GroupChange{ + ModifyTitle: &msg.Content.Name, + }, nil) +} + +func (s *SignalClient) HandleMatrixRoomAvatar(ctx context.Context, msg *bridgev2.MatrixRoomAvatar) (bool, error) { + _, groupID, err := parsePortalID(msg.Portal.ID) + if err != nil || groupID == "" { + return false, err + } + var avatarPath string + var avatarHash [32]byte + if msg.Content.URL != "" { + data, err := s.Main.Bridge.Bot.DownloadMedia(ctx, msg.Content.URL, nil) + if err != nil { + return false, fmt.Errorf("failed to download avatar: %w", err) + } + avatarHash = sha256.Sum256(data) + avatarPathPtr, err := s.Client.UploadGroupAvatar(ctx, data, groupID) + if err != nil { + return false, fmt.Errorf("failed to reupload avatar: %w", err) + } + avatarPath = *avatarPathPtr + } + return s.handleMatrixRoomMeta(ctx, msg.Portal, &signalmeow.GroupChange{ + ModifyAvatar: &avatarPath, + }, func() { + msg.Portal.AvatarMXC = msg.Content.URL + msg.Portal.AvatarHash = avatarHash + }) +} + +func (s *SignalClient) HandleMatrixRoomTopic(ctx context.Context, msg *bridgev2.MatrixRoomTopic) (bool, error) { + return s.handleMatrixRoomMeta(ctx, msg.Portal, &signalmeow.GroupChange{ + ModifyDescription: &msg.Content.Topic, + }, nil) +}