From e8c3b39ee708ae255f4429d11dbe34c19fbe4627 Mon Sep 17 00:00:00 2001 From: David Jirovec Date: Wed, 5 Aug 2026 17:44:26 +0200 Subject: [PATCH] chatinfo,updates: sync archived dialogs as low priority Signed-off-by: David Jirovec --- pkg/connector/chatinfo.go | 23 +++++++++++- pkg/connector/chatinfo_test.go | 65 +++++++++++++++++++++++++++++++++ pkg/connector/handletelegram.go | 36 ++++++++++++++++++ 3 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 pkg/connector/chatinfo_test.go diff --git a/pkg/connector/chatinfo.go b/pkg/connector/chatinfo.go index 356e6265..4e64ce72 100644 --- a/pkg/connector/chatinfo.go +++ b/pkg/connector/chatinfo.go @@ -325,9 +325,14 @@ type userLocalDialog interface { GetPinned() bool } +type folderedDialog interface { + GetFolderID() (int, bool) +} + var ( _ userLocalDialog = (*tg.Dialog)(nil) _ userLocalDialog = (*tg.DialogCommunity)(nil) + _ folderedDialog = (*tg.Dialog)(nil) ) func (tc *TelegramClient) fillUserLocalMeta(info *bridgev2.ChatInfo, dialog userLocalDialog) { @@ -338,9 +343,23 @@ func (tc *TelegramClient) fillUserLocalMeta(info *bridgev2.ChatInfo, dialog user } else { info.UserLocal.MutedUntil = &bridgev2.Unmuted } - if dialog.GetPinned() { - info.UserLocal.Tag = ptr.Ptr(event.RoomTagFavourite) + folderID := 0 + if dialog, ok := dialog.(folderedDialog); ok { + folderID, _ = dialog.GetFolderID() + } + tag := getUserLocalTag(dialog.GetPinned(), folderID) + info.UserLocal.Tag = &tag +} + +const telegramArchiveFolderID = 1 + +func getUserLocalTag(pinned bool, folderID int) event.RoomTag { + if pinned { + return event.RoomTagFavourite + } else if folderID == telegramArchiveFolderID { + return event.RoomTagLowPriority } + return "" } type realFullChat interface { diff --git a/pkg/connector/chatinfo_test.go b/pkg/connector/chatinfo_test.go new file mode 100644 index 00000000..f9840afc --- /dev/null +++ b/pkg/connector/chatinfo_test.go @@ -0,0 +1,65 @@ +// mautrix-telegram - A Matrix-Telegram puppeting bridge. +// Copyright (C) 2026 David Jirovec +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package connector + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "maunium.net/go/mautrix/event" +) + +func TestGetUserLocalTag(t *testing.T) { + tests := []struct { + name string + pinned bool + folderID int + expected event.RoomTag + }{ + { + name: "regular dialog", + expected: "", + }, + { + name: "pinned dialog", + pinned: true, + expected: event.RoomTagFavourite, + }, + { + name: "archived dialog", + folderID: telegramArchiveFolderID, + expected: event.RoomTagLowPriority, + }, + { + name: "pinned archived dialog", + pinned: true, + folderID: telegramArchiveFolderID, + expected: event.RoomTagFavourite, + }, + { + name: "unsupported folder", + folderID: 2, + expected: "", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.expected, getUserLocalTag(test.pinned, test.folderID)) + }) + } +} diff --git a/pkg/connector/handletelegram.go b/pkg/connector/handletelegram.go index d7159e3a..7a7fdd69 100644 --- a/pkg/connector/handletelegram.go +++ b/pkg/connector/handletelegram.go @@ -994,6 +994,8 @@ func (tc *TelegramClient) onUpdate(ctx context.Context, e tg.Entities, upd tg.Up return tc.onNotifySettings(ctx, e, update) case *tg.UpdatePinnedDialogs: return tc.onPinnedDialogs(ctx, e, update) + case *tg.UpdateFolderPeers: + return tc.onFolderPeers(ctx, update) case *tg.UpdateChatDefaultBannedRights: return tc.onChatDefaultBannedRights(ctx, e, update) case *tg.UpdatePeerBlocked: @@ -1473,6 +1475,40 @@ func (tc *TelegramClient) onNotifySettings(ctx context.Context, e tg.Entities, u return resultToError(res) } +func (tc *TelegramClient) onFolderPeers(ctx context.Context, update *tg.UpdateFolderPeers) error { + for _, folderPeer := range update.FolderPeers { + portalKey := tc.makePortalKeyFromPeer(folderPeer.Peer, 0) + tag := getUserLocalTag( + slices.Contains(tc.metadata.PinnedDialogs, portalKey.ID), + folderPeer.FolderID, + ) + + res := tc.main.Bridge.QueueRemoteEvent(tc.userLogin, &simplevent.ChatInfoChange{ + ChatInfoChange: &bridgev2.ChatInfoChange{ + ChatInfo: &bridgev2.ChatInfo{ + UserLocal: &bridgev2.UserLocalPortalInfo{ + Tag: &tag, + }, + }, + }, + EventMeta: simplevent.EventMeta{ + Type: bridgev2.RemoteEventChatInfoChange, + PortalKey: portalKey, + LogContext: func(c zerolog.Context) zerolog.Context { + return c. + Str("tg_event", "updateFolderPeers"). + Int("folder_id", folderPeer.FolderID). + Stringer("tag", tag) + }, + }, + }) + if err := resultToError(res); err != nil { + return err + } + } + return nil +} + func (tc *TelegramClient) onPinnedDialogs(ctx context.Context, e tg.Entities, msg *tg.UpdatePinnedDialogs) error { needsUnpinning := map[networkid.PortalKey]struct{}{} for _, portalID := range tc.metadata.PinnedDialogs {