I am experiencing an issue with the UpdateNewChat
event when using the LoadChats
method in TDLib. Occasionally, I receive updates for chats that I am no longer a member of or have never been a member of. This includes archived chats, deleted chats, and public chats that I previously left. I was also encountering chats that were actually groups connected to channels (in these channels, however, I am a member).
LoadChats
method.UpdateNewChat
, UpdateChatPosition
events.Expected Behavior: Only receive updates for chats that I am currently a member of.
Actual Behavior: Receiving updates for chats that I am not a member of or have left in the past.
Environment:
tdlib.native version: 1.8.29(from nuget)
tdlib version: 1.8.29(from nuget)
Programming language: C# 11
(.NET8)
What exactly does the UpdateNewChat
event send, and how does it work? The documentation mentions that this event should be handled when a chat is loaded or created, but it does not explain where these chats are coming from. I expected to receive only chats that I am currently a member of (even if they are archived). Is this behavior expected, or might there be an issue with how I'm handling this event? Why would this event bring chats that I am no longer a member of?
My Update handler:
internal static class CommonUpdateHandlerMethods
{
public static async void UpdateChatListHanlder(object sender, TdApi.Update e)
{
var client = (TdClient)sender;
switch (e)
{
case TdApi.Update.UpdateNewChat newChat:
{
await UpdateNewChat(client, newChat.Chat.Id);
break;
}
case TdApi.Update.UpdateChatPosition chatPos:
{
if (chatPos.Position.Order == CommonConstants.TdApi.ShouldRemoveChat)//ShouldRemoveChat = 0
{
switch (chatPos.Position.List)
{
case TdApi.ChatList.ChatListArchive:
{
CommonData.ArchiveChatList.Remove(chatPos.ChatId, out _);
break;
}
case TdApi.ChatList.ChatListMain:
{
CommonData.MainChatList.Remove(chatPos.ChatId, out _);
break;
}
}
}
else
{
await UpdateNewChat(client, chatPos.ChatId);
}
break;
}
}
}
private static async Task UpdateNewChat(TdClient client, long newChatId)
{
var chat = await client.GetChatAsync(newChatId);
if (chat.ChatLists.Any(list => list is TdApi.ChatList.ChatListArchive))
{
CommonData.ArchiveChatList.AddOrUpdate(chat.Id, chat, (id, chat) => chat);
}
else if (chat.ChatLists.Any(list => list is TdApi.ChatList.ChatListMain))
{
CommonData.MainChatList.AddOrUpdate(chat.Id, chat, (id, chat) => chat);
}
else
{
CommonData.UnkownChatList.AddOrUpdate(chat.Id, chat, (id, chat) => chat);
}
}
}
CommonData class:
internal static class CommonData
{
public static ConcurrentDictionary<long, TdApi.Chat> MainChatList { get; set; } = [];
public static ConcurrentDictionary<long, TdApi.Chat> ArchiveChatList { get; set; } = [];
public static ConcurrentDictionary<long, TdApi.Chat> UnkownChatList { get; set; } = [];
}
Helper class:
internal static class Helper
{
private static async Task InnerLoadChatsAsync(TdClient client, TdApi.ChatList chatList, int delay)
{
try
{
while (true)
{
await client.LoadChatsAsync(chatList, CommonConstants.DefaultLimit);
Thread.Sleep(delay);
}
}
catch (Exception ex)
{
if (ex is TdException tde && tde.Error.Code == CommonConstants.ErrorCodes.NotFound)//NotFound = 404
return;
else
throw;
}
}
internal static async Task LoadChatsAsync(TdClient client, int delay = CommonConstants.DefaultLoadChatDelay)//DefaultLoadChatDelay = 100
{
await InnerLoadChatsAsync(client, new TdApi.ChatList.ChatListArchive(), delay);
await InnerLoadChatsAsync(client, new TdApi.ChatList.ChatListMain(), delay);
}
}
My tester method:
public static async Task TestLoadChats(TdClient client)
{
await Helper.LoadChatsAsync(client);
Console.WriteLine("CHATM[{0}]", CommonData.MainChatList.Count);
Console.WriteLine("CHATA[{0}]", CommonData.ArchiveChatList.Count);
using var sw = new StreamWriter("finfo.txt");
foreach (var chat in CommonData.UnkownChatList)
{
sw.WriteLine("{0}\n {1}\n {2}\n--------------------------------------", chat.Key, chat.Value.Title, chat.Value.Type.DataType);
}
Console.WriteLine("CHATU[{0}]", CommonData.UnkownChatList.Count);
}
The updateNewChat
message is sent every time a new new chat is discovered. This includes also chats referenced by messages sent by your connections.
TDLib getting started page says that:
[An Application] must maintain a cache of chats received through this update.
After creating a cache of all the discovered chats, you can filter the ones of which you are currently a member by detecting the updateChatAddedToList
messages. Specifically, you are interested in the chats that belong to chatListMain
.
This is an example of this kind of messages:
{
"@type": "updateChatAddedToList",
"chat_id": 1111111,
"chat_list": {
"@type": "chatListMain"
},
"@client_id": 1
}