Skip to content

Commit

Permalink
handle Membership
Browse files Browse the repository at this point in the history
  • Loading branch information
maltee1 committed Aug 8, 2024
1 parent 24ca68a commit 12b153e
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 32 deletions.
17 changes: 7 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,8 @@ require (
github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9
github.com/google/uuid v1.6.0
github.com/gorilla/mux v1.8.0
github.com/lib/pq v1.10.9
github.com/mattn/go-pointer v0.0.1
github.com/mattn/go-sqlite3 v1.14.22
github.com/prometheus/client_golang v1.19.1
github.com/rs/zerolog v1.33.0
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.20240802175451-b430ebbffc98
Expand All @@ -24,30 +20,31 @@ require (
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
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/check.v1 v1.0.0-20201130134442-10cb98267c6c // 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
)

//replace maunium.net/go/mautrix => ../mautrix-go
//replace go.mau.fi/util => ../../Go/go-util
replace maunium.net/go/mautrix => github.com/maltee1/mautrix-go v0.0.0-20240808193435-264b3853ebfc
21 changes: 7 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
Expand All @@ -20,12 +16,17 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/maltee1/mautrix-go v0.0.0-20240808193435-264b3853ebfc h1:Ct/HVKLCGXt3yvj+JbG8ccXJgI/kNr/ZoTsNQL6xRR8=
github.com/maltee1/mautrix-go v0.0.0-20240808193435-264b3853ebfc/go.mod h1:ZWyxoQxRTBxzWIMs0kQCVogZIY0clTu33h102veCT/Q=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
Expand All @@ -35,17 +36,11 @@ github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o
github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
Expand Down Expand Up @@ -95,7 +90,5 @@ 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.20240806214251-e0f58dccf432 h1:Gz1nMg/s4B0VZD4e31wfaghR5cSk2NQVuQkxdCBuI7o=
maunium.net/go/mautrix v0.19.1-0.20240806214251-e0f58dccf432/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=
4 changes: 3 additions & 1 deletion pkg/connector/groupinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,9 @@ func (s *SignalClient) catchUpGroup(ctx context.Context, portal *bridgev2.Portal
for _, gc := range groupChanges {
log.Debug().Uint32("current_rev", gc.GroupChange.Revision).Msg("Processing group change")
chatInfoChange := s.groupChangeToChatInfoChange(ctx, gc.GroupChange.Revision, gc.GroupChange)
portal.ProcessChatInfoChange(ctx, s.makeEventSender(gc.GroupChange.SourceACI), s.UserLogin, chatInfoChange, time.UnixMilli(int64(ts)))
if gc.GroupChange.SourceServiceID.Type == libsignalgo.ServiceIDTypeACI {
portal.ProcessChatInfoChange(ctx, s.makeEventSender(gc.GroupChange.SourceServiceID.UUID), s.UserLogin, chatInfoChange, time.UnixMilli(int64(ts)))
}
if gc.GroupChange.Revision == toRevision {
break
}
Expand Down
106 changes: 106 additions & 0 deletions pkg/connector/handlematrix.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ import (

"github.com/google/uuid"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"go.mau.fi/util/variationselector"
"google.golang.org/protobuf/proto"
"maunium.net/go/mautrix/bridgev2"
"maunium.net/go/mautrix/bridgev2/database"
"maunium.net/go/mautrix/bridgev2/networkid"
"maunium.net/go/mautrix/event"

"go.mau.fi/mautrix-signal/pkg/libsignalgo"
"go.mau.fi/mautrix-signal/pkg/signalid"
Expand Down Expand Up @@ -344,3 +346,107 @@ func (s *SignalClient) HandleMatrixRoomTopic(ctx context.Context, msg *bridgev2.
ModifyDescription: &msg.Content.Topic,
}, nil)
}

func (s *SignalClient) HandleMatrixMembership(ctx context.Context, msg *bridgev2.MatrixMembershipChange) (bool, error) {
var targetIntent bridgev2.MatrixAPI
var targetSignalID uuid.UUID
var err error
if msg.TargetGhost != nil {
targetIntent = msg.TargetGhost.Intent
targetSignalID, err = signalid.ParseUserID(msg.TargetGhost.ID)
if err != nil {
return false, fmt.Errorf("failed to parse target ghost signal id: %w", err)
}
} else if msg.TargetUserLogin != nil {
targetSignalID, err = signalid.ParseUserLoginID(msg.TargetUserLogin.ID)
if err != nil {
return false, fmt.Errorf("failed to parse target user signal id: %w", err)
}
targetIntent = msg.TargetUserLogin.User.DoublePuppet(ctx)
if targetIntent == nil {
ghost, err := s.Main.Bridge.GetGhostByID(ctx, networkid.UserID(msg.TargetUserLogin.ID))
if err != nil {
return false, fmt.Errorf("failed to get ghost for user: %w", err)
}
targetIntent = ghost.Intent
}
}
gc := &signalmeow.GroupChange{}
role := signalmeow.GroupMember_DEFAULT
toMembership := msg.Type.GetTo()
if toMembership == event.MembershipBan {
gc.AddBannedMembers = []*signalmeow.BannedMember{{
ServiceID: libsignalgo.NewACIServiceID(targetSignalID),
Timestamp: uint64(time.Now().UnixMilli()),
}}
}
if toMembership == event.MembershipInvite || msg.Type == bridgev2.AcceptKnock {
levels, err := msg.Portal.Bridge.Matrix.GetPowerLevels(ctx, msg.Portal.MXID)
if err != nil {
log.Err(err).Msg("Couldn't get power levels")
if levels.GetUserLevel(targetIntent.GetMXID()) >= 50 {
role = signalmeow.GroupMember_ADMINISTRATOR
}
}
}
switch msg.Type {
case bridgev2.AcceptInvite:
gc.PromotePendingMembers = []*signalmeow.PromotePendingMember{&signalmeow.PromotePendingMember{
ACI: targetSignalID,
}}
case bridgev2.RevokeInvite, bridgev2.RejectInvite, bridgev2.BanInvited:
deletePendingMember := libsignalgo.NewACIServiceID(targetSignalID)
gc.DeletePendingMembers = []*libsignalgo.ServiceID{&deletePendingMember}
case bridgev2.Leave, bridgev2.Kick:
gc.DeleteMembers = []*uuid.UUID{&targetSignalID}
case bridgev2.Invite:
gc.AddMembers = []*signalmeow.AddMember{{
GroupMember: signalmeow.GroupMember{
ACI: targetSignalID,
Role: role,
},
}}
// TODO: joining and knocking requires a way to obtain the invite link
// because the joining/knocking member doesn't have the GroupMasterKey yet
// case bridgev2.Join:
// gc.AddMembers = []*signalmeow.AddMember{{
// GroupMember: signalmeow.GroupMember{
// ACI: targetSignalID,
// Role: role,
// },
// JoinFromInviteLink: true,
// }}
// case bridgev2.Knock:
// gc.AddRequestingMembers = []*signalmeow.RequestingMember{{
// ACI: targetSignalID,
// Timestamp: uint64(time.Now().UnixMilli()),
// }}
case bridgev2.AcceptKnock:
gc.PromoteRequestingMembers = []*signalmeow.RoleMember{{
ACI: targetSignalID,
Role: role,
}}
case bridgev2.RetractKnock, bridgev2.RejectKnock, bridgev2.BanKnocked:
gc.DeleteRequestingMembers = []*uuid.UUID{&targetSignalID}
case bridgev2.Unban:
unbanUser := libsignalgo.NewACIServiceID(targetSignalID)
gc.DeleteBannedMembers = []*libsignalgo.ServiceID{&unbanUser}
}
_, groupID, err := signalid.ParsePortalID(msg.Portal.ID)
if err != nil || groupID == "" {
return false, err
}
gc.Revision = msg.Portal.Metadata.(*signalid.PortalMetadata).Revision + 1
revision, err := s.Client.UpdateGroup(ctx, gc, groupID)
if err != nil {
return false, err
}
if msg.Type == bridgev2.Invite {
err = targetIntent.EnsureJoined(ctx, msg.Portal.MXID)
if err != nil {
return false, err
}
}
msg.Portal.Metadata.(*signalid.PortalMetadata).Revision = revision
return true, nil
}
15 changes: 15 additions & 0 deletions pkg/signalid/ids.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,25 @@ func ParseUserID(userID networkid.UserID) (uuid.UUID, error) {
}
}

func ParseUserLoginID(userLoginID networkid.UserLoginID) (uuid.UUID, error) {
serviceID, err := ParseUserLoginIDAsServiceID(userLoginID)
if err != nil {
return uuid.Nil, err
} else if serviceID.Type != libsignalgo.ServiceIDTypeACI {
return uuid.Nil, fmt.Errorf("invalid user ID: expected ACI type")
} else {
return serviceID.UUID, nil
}
}

func ParseUserIDAsServiceID(userID networkid.UserID) (libsignalgo.ServiceID, error) {
return libsignalgo.ServiceIDFromString(string(userID))
}

func ParseUserLoginIDAsServiceID(userLoginID networkid.UserLoginID) (libsignalgo.ServiceID, error) {
return libsignalgo.ServiceIDFromString(string(userLoginID))
}

func ParsePortalID(portalID networkid.PortalID) (userID libsignalgo.ServiceID, groupID types.GroupIdentifier, err error) {
if len(portalID) == 44 {
groupID = types.GroupIdentifier(portalID)
Expand Down
14 changes: 7 additions & 7 deletions pkg/signalmeow/groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ type RequestingMember struct {
Timestamp uint64
}

type PromotePendingMembers struct {
type PromotePendingMember struct {
ACI uuid.UUID
ProfileKey libsignalgo.ProfileKey
}
Expand All @@ -178,15 +178,15 @@ type BannedMember struct {
type GroupChange struct {
groupMasterKey types.SerializedGroupMasterKey

SourceACI uuid.UUID
SourceServiceID libsignalgo.ServiceID
Revision uint32
AddMembers []*AddMember
DeleteMembers []*uuid.UUID
ModifyMemberRoles []*RoleMember
ModifyMemberProfileKeys []*ProfileKeyMember
AddPendingMembers []*PendingMember
DeletePendingMembers []*libsignalgo.ServiceID
PromotePendingMembers []*GroupMember
PromotePendingMembers []*PromotePendingMember
ModifyTitle *string
ModifyAvatar *string
ModifyDisappearingMessagesDuration *uint32
Expand Down Expand Up @@ -862,9 +862,9 @@ func (cli *Client) decryptGroupChange(ctx context.Context, encryptedGroupChange
return nil, fmt.Errorf("wrong serviceid kind: expected aci, got pni")
}
decryptedGroupChange := &GroupChange{
groupMasterKey: groupMasterKey,
Revision: encryptedActions.Revision,
SourceACI: sourceServiceID.UUID,
groupMasterKey: groupMasterKey,
Revision: encryptedActions.Revision,
SourceServiceID: sourceServiceID,
}

if encryptedActions.ModifyTitle != nil {
Expand Down Expand Up @@ -992,7 +992,7 @@ func (cli *Client) decryptGroupChange(ctx context.Context, encryptedGroupChange
if err != nil {
return nil, err
}
decryptedGroupChange.PromotePendingMembers = append(decryptedGroupChange.PromotePendingMembers, &GroupMember{
decryptedGroupChange.PromotePendingMembers = append(decryptedGroupChange.PromotePendingMembers, &PromotePendingMember{
ACI: *aci,
ProfileKey: *profileKey,
})
Expand Down

0 comments on commit 12b153e

Please sign in to comment.