resync: resync portals upon viewing if they haven't been synced in the last 24h (#124)

This commit is contained in:
Adam Van Ymeren
2025-09-25 12:34:41 -07:00
committed by GitHub
parent a280c3a4b9
commit a38c3e5d00
4 changed files with 61 additions and 16 deletions
+25 -12
View File
@@ -91,14 +91,21 @@ func adminRightsToPowerLevel(rights tg.ChatAdminRights) *int {
return otherPowerLevel
}
func (t *TelegramClient) getDMChatInfo(userID int64) *bridgev2.ChatInfo {
func (t *TelegramClient) getDMChatInfo(ctx context.Context, userID int64) (*bridgev2.ChatInfo, error) {
ghost, err := t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(userID))
if err != nil {
return nil, err
}
chatInfo := bridgev2.ChatInfo{
Type: ptr.Ptr(database.RoomTypeDM),
Members: &bridgev2.ChatMemberList{
IsFull: true,
MemberMap: map[networkid.UserID]bridgev2.ChatMember{},
IsFull: true,
MemberMap: map[networkid.UserID]bridgev2.ChatMember{},
PowerLevels: t.getDMPowerLevels(ghost),
},
CanBackfill: true,
CanBackfill: true,
ExtraUpdates: updatePortalLastSyncAt,
}
chatInfo.Members.MemberMap[ids.MakeUserID(userID)] = bridgev2.ChatMember{EventSender: t.senderForUserID(userID)}
chatInfo.Members.MemberMap[t.userID] = bridgev2.ChatMember{EventSender: t.mySender()}
@@ -112,7 +119,7 @@ func (t *TelegramClient) getDMChatInfo(userID int64) *bridgev2.ChatInfo {
chatInfo.Name = ptr.Ptr("Telegram Saved Messages")
chatInfo.Topic = ptr.Ptr("Your Telegram cloud storage chat")
}
return &chatInfo
return &chatInfo, nil
}
func (t *TelegramClient) getGroupChatInfo(fullChat *tg.MessagesChatFull, chatID int64) (*bridgev2.ChatInfo, bool, error) {
@@ -142,15 +149,14 @@ func (t *TelegramClient) getGroupChatInfo(fullChat *tg.MessagesChatFull, chatID
CanBackfill: true,
ExtraUpdates: func(ctx context.Context, p *bridgev2.Portal) bool {
meta := p.Metadata.(*PortalMetadata)
changed := meta.SetIsSuperGroup(isMegagroup)
_ = updatePortalLastSyncAt(ctx, p)
_ = meta.SetIsSuperGroup(isMegagroup)
if reactions, ok := fullChat.FullChat.GetAvailableReactions(); ok {
switch typedReactions := reactions.(type) {
case *tg.ChatReactionsAll:
changed = meta.AllowedReactions != nil
meta.AllowedReactions = nil
case *tg.ChatReactionsNone:
changed = meta.AllowedReactions == nil || len(meta.AllowedReactions) > 0
meta.AllowedReactions = []string{}
case *tg.ChatReactionsSome:
allowedReactions := make([]string, 0, len(typedReactions.Reactions))
@@ -162,13 +168,12 @@ func (t *TelegramClient) getGroupChatInfo(fullChat *tg.MessagesChatFull, chatID
}
slices.Sort(allowedReactions)
if !slices.Equal(meta.AllowedReactions, allowedReactions) {
changed = true
meta.AllowedReactions = allowedReactions
}
}
}
return changed
return true
},
}
@@ -243,7 +248,7 @@ func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Porta
switch peerType {
case ids.PeerTypeUser:
return t.getDMChatInfo(id), nil
return t.getDMChatInfo(ctx, id)
case ids.PeerTypeChat:
fullChat, err := APICallWithUpdates(ctx, t, func() (*tg.MessagesChatFull, error) {
return t.client.API().MessagesGetFullChat(ctx, id)
@@ -261,6 +266,7 @@ func (t *TelegramClient) GetChatInfo(ctx context.Context, portal *bridgev2.Porta
return nil, fmt.Errorf("full chat is %T not *tg.ChatFull", fullChat.FullChat)
}
chatInfo.Avatar = t.avatarFromPhoto(ctx, peerType, id, chatFull.ChatPhoto)
chatInfo.Members.PowerLevels = t.getGroupChatPowerLevels(ctx, fullChat.GetChats()[0])
if chatFull.Participants.TypeID() == tg.ChatParticipantsForbiddenTypeID {
chatInfo.Members.IsFull = false
@@ -497,8 +503,12 @@ func (t *TelegramClient) getPowerLevelOverridesFromBannedRights(entity tg.ChatCl
plo.Events[event.StateRoomName] = *changeInfoPowerLevel
plo.Events[event.StateRoomAvatar] = *changeInfoPowerLevel
plo.Events[event.StateTopic] = *changeInfoPowerLevel
// TODO is this the correct level?
plo.Events[event.StateBeeperDisappearingTimer] = *changeInfoPowerLevel
} else {
plo.Events[event.StateRoomName] = 0
plo.Events[event.StateRoomAvatar] = 0
plo.Events[event.StateTopic] = 0
plo.Events[event.StateBeeperDisappearingTimer] = 0
}
if dbr.PinMessages {
@@ -509,6 +519,9 @@ func (t *TelegramClient) getPowerLevelOverridesFromBannedRights(entity tg.ChatCl
if dbr.SendStickers {
plo.Events[event.EventSticker] = *postMessagesPowerLevel
} else {
plo.Events[event.EventSticker] = 0
}
return &plo
}
+19
View File
@@ -42,6 +42,7 @@ import (
"maunium.net/go/mautrix/bridgev2"
"maunium.net/go/mautrix/bridgev2/database"
"maunium.net/go/mautrix/bridgev2/networkid"
"maunium.net/go/mautrix/bridgev2/simplevent"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
@@ -65,6 +66,7 @@ var (
_ bridgev2.DisappearTimerChangingNetworkAPI = (*TelegramClient)(nil)
_ bridgev2.MuteHandlingNetworkAPI = (*TelegramClient)(nil)
_ bridgev2.TagHandlingNetworkAPI = (*TelegramClient)(nil)
_ bridgev2.ChatViewingNetworkAPI = (*TelegramClient)(nil)
)
func getMediaFilename(content *event.MessageEventContent) (filename string) {
@@ -85,6 +87,23 @@ func getMediaFilename(content *event.MessageEventContent) (filename string) {
return filename
}
func (t *TelegramClient) HandleMatrixViewingChat(ctx context.Context, msg *bridgev2.MatrixViewingChat) error {
if msg.Portal == nil {
return nil
}
meta := msg.Portal.Metadata.(*PortalMetadata)
if meta.LastSync.Add(24 * time.Hour).Before(time.Now()) {
t.userLogin.QueueRemoteEvent(&simplevent.ChatResync{
EventMeta: simplevent.EventMeta{
Type: bridgev2.RemoteEventChatResync,
PortalKey: msg.Portal.PortalKey,
},
GetChatInfoFunc: t.GetChatInfo,
})
}
return nil
}
func (t *TelegramClient) transferMediaToTelegram(ctx context.Context, content *event.MessageEventContent, sticker bool) (tg.InputMediaClass, error) {
var upload tg.InputFileClass
var forceDocument bool
+13 -3
View File
@@ -19,10 +19,13 @@ package connector
import (
"context"
"maunium.net/go/mautrix/bridgev2"
"maunium.net/go/mautrix/bridgev2/database"
"maunium.net/go/mautrix/bridgev2/networkid"
"maunium.net/go/mautrix/id"
"go.mau.fi/util/jsontime"
"go.mau.fi/mautrix-telegram/pkg/gotd/crypto"
"go.mau.fi/mautrix-telegram/pkg/gotd/session"
)
@@ -47,9 +50,10 @@ type GhostMetadata struct {
}
type PortalMetadata struct {
IsSuperGroup bool `json:"is_supergroup,omitempty"`
ReadUpTo int `json:"read_up_to,omitempty"`
AllowedReactions []string `json:"allowed_reactions"`
IsSuperGroup bool `json:"is_supergroup,omitempty"`
ReadUpTo int `json:"read_up_to,omitempty"`
AllowedReactions []string `json:"allowed_reactions"`
LastSync jsontime.Unix `json:"last_sync,omitempty"`
}
func (pm *PortalMetadata) SetIsSuperGroup(isSupergroup bool) (changed bool) {
@@ -118,3 +122,9 @@ func (s *UserLoginSession) Save(ctx context.Context, data *session.Data) error {
// TODO save UserLogin to database?
return nil
}
func updatePortalLastSyncAt(_ context.Context, portal *bridgev2.Portal) bool {
meta := portal.Metadata.(*PortalMetadata)
meta.LastSync = jsontime.UnixNow()
return true
}
+4 -1
View File
@@ -134,7 +134,10 @@ func (t *TelegramClient) handleDialogs(ctx context.Context, dialogs tg.ModifiedM
log.Debug().Int64("user_id", peer.UserID).Msg("Not syncing portal because user is deleted")
continue
}
chatInfo = t.getDMChatInfo(peer.UserID)
chatInfo, err = t.getDMChatInfo(ctx, peer.UserID)
if err != nil {
return fmt.Errorf("failed to get dm info for %d: %w", peer.UserID, err)
}
case *tg.PeerChat:
chat := chats[peer.ChatID]
if chat.TypeID() == tg.ChatForbiddenTypeID {