chatinfo: ensure own member is always added
This commit is contained in:
+65
-50
@@ -20,6 +20,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"iter"
|
||||||
"slices"
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -106,8 +107,8 @@ func (t *TelegramClient) getDMChatInfo(ctx context.Context, userID int64) (*brid
|
|||||||
CanBackfill: true,
|
CanBackfill: true,
|
||||||
ExtraUpdates: updatePortalLastSyncAt,
|
ExtraUpdates: updatePortalLastSyncAt,
|
||||||
}
|
}
|
||||||
chatInfo.Members.MemberMap[ids.MakeUserID(userID)] = bridgev2.ChatMember{EventSender: t.senderForUserID(userID)}
|
chatInfo.Members.MemberMap.Add(bridgev2.ChatMember{EventSender: t.mySender()})
|
||||||
chatInfo.Members.MemberMap[t.userID] = bridgev2.ChatMember{EventSender: t.mySender()}
|
chatInfo.Members.MemberMap.Add(bridgev2.ChatMember{EventSender: t.senderForUserID(userID)})
|
||||||
if userID == t.telegramUserID {
|
if userID == t.telegramUserID {
|
||||||
chatInfo.Avatar = &bridgev2.Avatar{
|
chatInfo.Avatar = &bridgev2.Avatar{
|
||||||
ID: networkid.AvatarID(t.main.Config.SavedMessagesAvatar),
|
ID: networkid.AvatarID(t.main.Config.SavedMessagesAvatar),
|
||||||
@@ -123,17 +124,20 @@ func (t *TelegramClient) getDMChatInfo(ctx context.Context, userID int64) (*brid
|
|||||||
|
|
||||||
func (t *TelegramClient) getGroupChatInfo(fullChat *tg.MessagesChatFull, chatID int64) (*bridgev2.ChatInfo, bool, error) {
|
func (t *TelegramClient) getGroupChatInfo(fullChat *tg.MessagesChatFull, chatID int64) (*bridgev2.ChatInfo, bool, error) {
|
||||||
var name *string
|
var name *string
|
||||||
var isBroadcastChannel, isMegagroup bool
|
var isBroadcastChannel, isMegagroup, left, found bool
|
||||||
var participantsCount int
|
var participantsCount int
|
||||||
for _, c := range fullChat.GetChats() {
|
for _, c := range fullChat.GetChats() {
|
||||||
if c.GetID() == chatID {
|
if c.GetID() == chatID {
|
||||||
|
found = true
|
||||||
switch chat := c.(type) {
|
switch chat := c.(type) {
|
||||||
case *tg.Chat:
|
case *tg.Chat:
|
||||||
name = &chat.Title
|
name = &chat.Title
|
||||||
|
left = chat.Left
|
||||||
case *tg.Channel:
|
case *tg.Channel:
|
||||||
name = &chat.Title
|
name = &chat.Title
|
||||||
isBroadcastChannel = chat.Broadcast
|
isBroadcastChannel = chat.Broadcast
|
||||||
isMegagroup = chat.Megagroup
|
isMegagroup = chat.Megagroup
|
||||||
|
left = chat.Left
|
||||||
|
|
||||||
if value, ok := chat.GetParticipantsCount(); ok {
|
if value, ok := chat.GetParticipantsCount(); ok {
|
||||||
participantsCount = value
|
participantsCount = value
|
||||||
@@ -142,13 +146,16 @@ func (t *TelegramClient) getGroupChatInfo(fullChat *tg.MessagesChatFull, chatID
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !found {
|
||||||
|
return nil, false, fmt.Errorf("chat ID %d not found in full chat", chatID)
|
||||||
|
}
|
||||||
|
|
||||||
chatInfo := bridgev2.ChatInfo{
|
chatInfo := bridgev2.ChatInfo{
|
||||||
Name: name,
|
Name: name,
|
||||||
Type: ptr.Ptr(database.RoomTypeDefault),
|
Type: ptr.Ptr(database.RoomTypeDefault),
|
||||||
Members: &bridgev2.ChatMemberList{
|
Members: &bridgev2.ChatMemberList{
|
||||||
IsFull: true,
|
IsFull: true,
|
||||||
MemberMap: map[networkid.UserID]bridgev2.ChatMember{},
|
MemberMap: bridgev2.ChatMemberMap{},
|
||||||
|
|
||||||
ExcludeChangesFromTimeline: true,
|
ExcludeChangesFromTimeline: true,
|
||||||
},
|
},
|
||||||
@@ -184,6 +191,9 @@ func (t *TelegramClient) getGroupChatInfo(fullChat *tg.MessagesChatFull, chatID
|
|||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if !left {
|
||||||
|
chatInfo.Members.MemberMap.Add(bridgev2.ChatMember{EventSender: t.mySender()})
|
||||||
|
}
|
||||||
|
|
||||||
if ttl, ok := fullChat.FullChat.GetTTLPeriod(); ok {
|
if ttl, ok := fullChat.FullChat.GetTTLPeriod(); ok {
|
||||||
chatInfo.Disappear = &database.DisappearingSetting{
|
chatInfo.Disappear = &database.DisappearingSetting{
|
||||||
@@ -215,35 +225,43 @@ func (t *TelegramClient) avatarFromPhoto(ctx context.Context, peerType ids.PeerT
|
|||||||
return avatar
|
return avatar
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TelegramClient) filterChannelParticipants(participants []tg.ChannelParticipantClass, limit int) (members []bridgev2.ChatMember) {
|
func (t *TelegramClient) filterChannelParticipants(participants []tg.ChannelParticipantClass, limit int) iter.Seq[bridgev2.ChatMember] {
|
||||||
for _, u := range participants {
|
return func(yield func(bridgev2.ChatMember) bool) {
|
||||||
var userID int64
|
for i, u := range participants {
|
||||||
var powerLevel *int
|
var member bridgev2.ChatMember
|
||||||
switch participant := u.(type) {
|
switch participant := u.(type) {
|
||||||
case *tg.ChannelParticipant:
|
case *tg.ChannelParticipant:
|
||||||
userID = participant.GetUserID()
|
member.EventSender = t.senderForUserID(participant.GetUserID())
|
||||||
case *tg.ChannelParticipantSelf:
|
case *tg.ChannelParticipantSelf:
|
||||||
userID = participant.GetUserID()
|
member.EventSender = t.senderForUserID(participant.GetUserID())
|
||||||
case *tg.ChannelParticipantCreator:
|
case *tg.ChannelParticipantCreator:
|
||||||
userID = participant.GetUserID()
|
member.EventSender = t.senderForUserID(participant.GetUserID())
|
||||||
powerLevel = creatorPowerLevel
|
member.PowerLevel = creatorPowerLevel
|
||||||
case *tg.ChannelParticipantAdmin:
|
case *tg.ChannelParticipantAdmin:
|
||||||
userID = participant.GetUserID()
|
member.EventSender = t.senderForUserID(participant.GetUserID())
|
||||||
powerLevel = adminRightsToPowerLevel(participant.AdminRights)
|
member.PowerLevel = adminRightsToPowerLevel(participant.AdminRights)
|
||||||
default:
|
case *tg.ChannelParticipantBanned:
|
||||||
continue
|
member.Membership = event.MembershipBan
|
||||||
}
|
member.PrevMembership = event.MembershipJoin
|
||||||
|
member.EventSender = t.getPeerSender(participant.GetPeer())
|
||||||
|
member.MemberSender = t.senderForUserID(participant.GetKickedBy())
|
||||||
|
case *tg.ChannelParticipantLeft:
|
||||||
|
member.Membership = event.MembershipLeave
|
||||||
|
member.PrevMembership = event.MembershipJoin
|
||||||
|
member.EventSender = t.getPeerSender(participant.GetPeer())
|
||||||
|
default:
|
||||||
|
// TODO warning log?
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if i >= limit && member.Membership == "" && !member.EventSender.IsFromMe {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
members = append(members, bridgev2.ChatMember{
|
if !yield(member) {
|
||||||
EventSender: t.senderForUserID(userID),
|
return
|
||||||
PowerLevel: powerLevel,
|
}
|
||||||
})
|
|
||||||
|
|
||||||
if len(members) >= limit {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Portal) (*bridgev2.ChatInfo, error) {
|
func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Portal) (*bridgev2.ChatInfo, error) {
|
||||||
@@ -254,6 +272,7 @@ func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Porta
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memberSyncLimit := t.main.Config.MemberList.NormalizedMaxInitialSync()
|
||||||
switch peerType {
|
switch peerType {
|
||||||
case ids.PeerTypeUser:
|
case ids.PeerTypeUser:
|
||||||
return t.getDMChatInfo(ctx, id)
|
return t.getDMChatInfo(ctx, id)
|
||||||
@@ -288,24 +307,22 @@ func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Porta
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range chatParticipants.GetParticipants() {
|
for _, user := range chatParticipants.GetParticipants() {
|
||||||
if user.TypeID() == tg.ChannelParticipantBannedTypeID {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var powerLevel *int
|
var powerLevel *int
|
||||||
switch user.(type) {
|
switch user.(type) {
|
||||||
case *tg.ChatParticipantCreator:
|
case *tg.ChatParticipantCreator:
|
||||||
powerLevel = creatorPowerLevel
|
powerLevel = creatorPowerLevel
|
||||||
case *tg.ChatParticipantAdmin:
|
case *tg.ChatParticipantAdmin:
|
||||||
powerLevel = modPowerLevel
|
powerLevel = modPowerLevel
|
||||||
|
default:
|
||||||
|
powerLevel = ptr.Ptr(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
chatInfo.Members.MemberMap[ids.MakeUserID(user.GetUserID())] = bridgev2.ChatMember{
|
chatInfo.Members.MemberMap.Set(bridgev2.ChatMember{
|
||||||
EventSender: t.senderForUserID(user.GetUserID()),
|
EventSender: t.senderForUserID(user.GetUserID()),
|
||||||
PowerLevel: powerLevel,
|
PowerLevel: powerLevel,
|
||||||
}
|
})
|
||||||
|
|
||||||
if len(chatInfo.Members.MemberMap) >= t.main.Config.MemberList.NormalizedMaxInitialSync() {
|
if len(chatInfo.Members.MemberMap) >= memberSyncLimit {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,11 +365,10 @@ func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Porta
|
|||||||
chatInfo.Members.PowerLevels = t.getGroupChatPowerLevels(ctx, fullChat.GetChats()[0])
|
chatInfo.Members.PowerLevels = t.getGroupChatPowerLevels(ctx, fullChat.GetChats()[0])
|
||||||
if !portal.Metadata.(*PortalMetadata).IsSuperGroup {
|
if !portal.Metadata.(*PortalMetadata).IsSuperGroup {
|
||||||
// Add the channel user
|
// Add the channel user
|
||||||
sender := ids.MakeChannelUserID(id)
|
chatInfo.Members.MemberMap.Set(bridgev2.ChatMember{
|
||||||
chatInfo.Members.MemberMap[sender] = bridgev2.ChatMember{
|
EventSender: bridgev2.EventSender{Sender: ids.MakeChannelUserID(id)},
|
||||||
EventSender: bridgev2.EventSender{Sender: sender},
|
|
||||||
PowerLevel: superadminPowerLevel,
|
PowerLevel: superadminPowerLevel,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just return the current user as a member if we can't view the
|
// Just return the current user as a member if we can't view the
|
||||||
@@ -368,13 +384,12 @@ func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Porta
|
|||||||
return chatInfo, nil
|
return chatInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
limit := t.main.Config.MemberList.NormalizedMaxInitialSync()
|
if memberSyncLimit <= 200 {
|
||||||
if limit <= 200 {
|
|
||||||
participants, err := APICallWithUpdates(ctx, t, func() (*tg.ChannelsChannelParticipants, error) {
|
participants, err := APICallWithUpdates(ctx, t, func() (*tg.ChannelsChannelParticipants, error) {
|
||||||
p, err := t.client.API().ChannelsGetParticipants(ctx, &tg.ChannelsGetParticipantsRequest{
|
p, err := t.client.API().ChannelsGetParticipants(ctx, &tg.ChannelsGetParticipantsRequest{
|
||||||
Channel: inputChannel,
|
Channel: inputChannel,
|
||||||
Filter: &tg.ChannelParticipantsRecent{},
|
Filter: &tg.ChannelParticipantsRecent{},
|
||||||
Limit: limit,
|
Limit: memberSyncLimit,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -389,12 +404,12 @@ func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Porta
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
chatInfo.Members.IsFull = len(participants.Participants) < limit
|
chatInfo.Members.IsFull = len(participants.Participants) < memberSyncLimit
|
||||||
for _, participant := range t.filterChannelParticipants(participants.Participants, limit) {
|
for participant := range t.filterChannelParticipants(participants.Participants, memberSyncLimit) {
|
||||||
chatInfo.Members.MemberMap[participant.Sender] = participant
|
chatInfo.Members.MemberMap.Set(participant)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
remaining := t.main.Config.MemberList.NormalizedMaxInitialSync()
|
remaining := memberSyncLimit
|
||||||
var offset int
|
var offset int
|
||||||
for remaining > 0 {
|
for remaining > 0 {
|
||||||
participants, err := APICallWithUpdates(ctx, t, func() (*tg.ChannelsChannelParticipants, error) {
|
participants, err := APICallWithUpdates(ctx, t, func() (*tg.ChannelsChannelParticipants, error) {
|
||||||
@@ -422,8 +437,8 @@ func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Porta
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, participant := range t.filterChannelParticipants(participants.Participants, limit) {
|
for participant := range t.filterChannelParticipants(participants.Participants, remaining) {
|
||||||
chatInfo.Members.MemberMap[participant.Sender] = participant
|
chatInfo.Members.MemberMap.Set(participant)
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += len(participants.Participants)
|
offset += len(participants.Participants)
|
||||||
|
|||||||
@@ -27,10 +27,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func MakeUserID(userID int64) networkid.UserID {
|
func MakeUserID(userID int64) networkid.UserID {
|
||||||
|
if userID == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
return networkid.UserID(strconv.FormatInt(userID, 10))
|
return networkid.UserID(strconv.FormatInt(userID, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeChannelUserID(channelID int64) networkid.UserID {
|
func MakeChannelUserID(channelID int64) networkid.UserID {
|
||||||
|
if channelID == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
return networkid.UserID("channel-" + strconv.FormatInt(channelID, 10))
|
return networkid.UserID("channel-" + strconv.FormatInt(channelID, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,6 +56,9 @@ func ParseUserLoginID(userID networkid.UserLoginID) (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MakeUserLoginID(userID int64) networkid.UserLoginID {
|
func MakeUserLoginID(userID int64) networkid.UserLoginID {
|
||||||
|
if userID == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
return networkid.UserLoginID(strconv.FormatInt(userID, 10))
|
return networkid.UserLoginID(strconv.FormatInt(userID, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user