diff --git a/libgm/gmproto/conversations.pb.go b/libgm/gmproto/conversations.pb.go index 3fe418d..79db6f9 100644 --- a/libgm/gmproto/conversations.pb.go +++ b/libgm/gmproto/conversations.pb.go @@ -1754,23 +1754,24 @@ type Conversation struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ConversationID string `protobuf:"bytes,1,opt,name=conversationID,proto3" json:"conversationID,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - LatestMessage *LatestMessage `protobuf:"bytes,4,opt,name=latestMessage,proto3" json:"latestMessage,omitempty"` - LastMessageTimestamp int64 `protobuf:"varint,5,opt,name=lastMessageTimestamp,proto3" json:"lastMessageTimestamp,omitempty"` - Unread bool `protobuf:"varint,6,opt,name=unread,proto3" json:"unread,omitempty"` - IsGroupChat bool `protobuf:"varint,10,opt,name=isGroupChat,proto3" json:"isGroupChat,omitempty"` // not certain - DefaultOutgoingID string `protobuf:"bytes,11,opt,name=defaultOutgoingID,proto3" json:"defaultOutgoingID,omitempty"` - // bool bool1 = 13; - Status ConvUpdateTypes `protobuf:"varint,12,opt,name=status,proto3,enum=conversations.ConvUpdateTypes" json:"status,omitempty"` - AvatarHexColor string `protobuf:"bytes,15,opt,name=avatarHexColor,proto3" json:"avatarHexColor,omitempty"` - LatestMessageID string `protobuf:"bytes,17,opt,name=latestMessageID,proto3" json:"latestMessageID,omitempty"` - Participants []*Participant `protobuf:"bytes,20,rep,name=participants,proto3" json:"participants,omitempty"` - OtherParticipants []string `protobuf:"bytes,21,rep,name=otherParticipants,proto3" json:"otherParticipants,omitempty"` // participant ids excluding me - Type ConversationType `protobuf:"varint,22,opt,name=type,proto3,enum=conversations.ConversationType" json:"type,omitempty"` - SubType bool `protobuf:"varint,24,opt,name=subType,proto3" json:"subType,omitempty"` - UnknownTimestamp int64 `protobuf:"varint,28,opt,name=unknownTimestamp,proto3" json:"unknownTimestamp,omitempty"` // set to lastMessageTimestamp + 1000 when marking as unread? - ThirdType bool `protobuf:"varint,29,opt,name=thirdType,proto3" json:"thirdType,omitempty"` + ConversationID string `protobuf:"bytes,1,opt,name=conversationID,proto3" json:"conversationID,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + LatestMessage *LatestMessage `protobuf:"bytes,4,opt,name=latestMessage,proto3" json:"latestMessage,omitempty"` + LastMessageTimestamp int64 `protobuf:"varint,5,opt,name=lastMessageTimestamp,proto3" json:"lastMessageTimestamp,omitempty"` + Unread bool `protobuf:"varint,6,opt,name=unread,proto3" json:"unread,omitempty"` + IsGroupChat bool `protobuf:"varint,10,opt,name=isGroupChat,proto3" json:"isGroupChat,omitempty"` // not certain + DefaultOutgoingID string `protobuf:"bytes,11,opt,name=defaultOutgoingID,proto3" json:"defaultOutgoingID,omitempty"` + Status ConvUpdateTypes `protobuf:"varint,12,opt,name=status,proto3,enum=conversations.ConvUpdateTypes" json:"status,omitempty"` + ReadOnly bool `protobuf:"varint,13,opt,name=readOnly,proto3" json:"readOnly,omitempty"` + AvatarHexColor string `protobuf:"bytes,15,opt,name=avatarHexColor,proto3" json:"avatarHexColor,omitempty"` + LatestMessageID string `protobuf:"bytes,17,opt,name=latestMessageID,proto3" json:"latestMessageID,omitempty"` + Participants []*Participant `protobuf:"bytes,20,rep,name=participants,proto3" json:"participants,omitempty"` + OtherParticipants []string `protobuf:"bytes,21,rep,name=otherParticipants,proto3" json:"otherParticipants,omitempty"` // participant ids excluding me + Type ConversationType `protobuf:"varint,22,opt,name=type,proto3,enum=conversations.ConversationType" json:"type,omitempty"` + SubType bool `protobuf:"varint,24,opt,name=subType,proto3" json:"subType,omitempty"` + Pinned bool `protobuf:"varint,26,opt,name=pinned,proto3" json:"pinned,omitempty"` + UnknownTimestamp int64 `protobuf:"varint,28,opt,name=unknownTimestamp,proto3" json:"unknownTimestamp,omitempty"` // set to lastMessageTimestamp + 1000 when marking as unread? + ThirdType bool `protobuf:"varint,29,opt,name=thirdType,proto3" json:"thirdType,omitempty"` } func (x *Conversation) Reset() { @@ -1861,6 +1862,13 @@ func (x *Conversation) GetStatus() ConvUpdateTypes { return ConvUpdateTypes_UNKNOWN_CONVTYPE } +func (x *Conversation) GetReadOnly() bool { + if x != nil { + return x.ReadOnly + } + return false +} + func (x *Conversation) GetAvatarHexColor() string { if x != nil { return x.AvatarHexColor @@ -1903,6 +1911,13 @@ func (x *Conversation) GetSubType() bool { return false } +func (x *Conversation) GetPinned() bool { + if x != nil { + return x.Pinned + } + return false +} + func (x *Conversation) GetUnknownTimestamp() int64 { if x != nil { return x.UnknownTimestamp diff --git a/libgm/gmproto/conversations.pb.raw b/libgm/gmproto/conversations.pb.raw index 6edb46f..8587749 100644 Binary files a/libgm/gmproto/conversations.pb.raw and b/libgm/gmproto/conversations.pb.raw differ diff --git a/libgm/gmproto/conversations.proto b/libgm/gmproto/conversations.proto index cec73dc..976270a 100644 --- a/libgm/gmproto/conversations.proto +++ b/libgm/gmproto/conversations.proto @@ -132,14 +132,15 @@ message Conversation { bool isGroupChat = 10; // not certain string defaultOutgoingID = 11; - //bool bool1 = 13; ConvUpdateTypes status = 12; + bool readOnly = 13; string avatarHexColor = 15; string latestMessageID = 17; repeated Participant participants = 20; repeated string otherParticipants = 21; // participant ids excluding me ConversationType type = 22; bool subType = 24; + bool pinned = 26; int64 unknownTimestamp = 28; // set to lastMessageTimestamp + 1000 when marking as unread? bool thirdType = 29; } diff --git a/portal.go b/portal.go index 5ff3d62..aa27afd 100644 --- a/portal.go +++ b/portal.go @@ -800,6 +800,18 @@ func (portal *Portal) UpdateMetadata(user *User, info *gmproto.Conversation) []i if portal.shouldSetDMRoomMetadata() { update = portal.UpdateName(info.Name, false) || update } + pls, err := portal.MainIntent().PowerLevels(portal.MXID) + if err != nil { + portal.zlog.Warn().Err(err).Msg("Failed to get power levels") + } else if portal.updatePowerLevels(info, pls) { + resp, err := portal.MainIntent().SetPowerLevels(portal.MXID, pls) + if err != nil { + portal.zlog.Warn().Err(err).Msg("Failed to update power levels") + } else { + portal.zlog.Debug().Str("event_id", resp.EventID.String()).Msg("Updated power levels") + } + } + // TODO avatar if update { err := portal.Update(context.TODO()) @@ -830,25 +842,46 @@ func (portal *Portal) UpdateMatrixRoom(user *User, groupInfo *gmproto.Conversati func (portal *Portal) GetBasePowerLevels() *event.PowerLevelsEventContent { anyone := 0 nope := 99 - invite := 50 return &event.PowerLevelsEventContent{ UsersDefault: anyone, EventsDefault: anyone, RedactPtr: &anyone, StateDefaultPtr: &nope, BanPtr: &nope, - InvitePtr: &invite, + KickPtr: &nope, + InvitePtr: &nope, Users: map[id.UserID]int{ portal.MainIntent().UserID: 100, + portal.bridge.Bot.UserID: 100, }, Events: map[string]int{ event.StateRoomName.Type: anyone, event.StateRoomAvatar.Type: anyone, - event.EventReaction.Type: anyone, // TODO only allow reactions in RCS rooms }, } } +func (portal *Portal) updatePowerLevels(conv *gmproto.Conversation, pl *event.PowerLevelsEventContent) bool { + expectedEventsDefault := 0 + if conv.GetReadOnly() { + expectedEventsDefault = 99 + } + + expectedReaction := 99 + if conv.GetType() == gmproto.ConversationType_RCS { + expectedReaction = 0 + } + + changed := false + if pl.EventsDefault != expectedEventsDefault { + pl.EventsDefault = expectedEventsDefault + changed = true + } + changed = pl.EnsureEventLevel(event.EventReaction, expectedReaction) || changed + changed = pl.EnsureUserLevel(portal.bridge.Bot.UserID, 100) || changed + return changed +} + func (portal *Portal) getBridgeInfoStateKey() string { return fmt.Sprintf("fi.mau.gmessages://gmessages/%s", portal.ID) } @@ -928,11 +961,12 @@ func (portal *Portal) CreateMatrixRoom(user *User, conv *gmproto.Conversation) e bridgeInfoStateKey, bridgeInfo := portal.getBridgeInfo() + pl := portal.GetBasePowerLevels() + portal.updatePowerLevels(conv, pl) + initialState := []*event.Event{{ - Type: event.StatePowerLevels, - Content: event.Content{ - Parsed: portal.GetBasePowerLevels(), - }, + Type: event.StatePowerLevels, + Content: event.Content{Parsed: pl}, }, { Type: event.StateBridge, Content: event.Content{Parsed: bridgeInfo},