Skip to content
This repository was archived by the owner on Dec 5, 2021. It is now read-only.
This repository was archived by the owner on Dec 5, 2021. It is now read-only.

Get updates for unread channel messages without polling (so flood exception might be prevented) #661

Description

@paulbir

How do I get updates for new channel messages without bumping flood limits?
First I tried this:

            while (true)
            {
                Task.Delay(500).Wait();
                TLState state = client.SendRequestAsync<TLState>(new TLRequestGetState()).Result;
                //if (state.UnreadCount <= 0) continue;

                TLRequestGetDifference req = new TLRequestGetDifference { Date = state.Date, Pts = state.Pts, Qts = state.Qts, Sequence = state.Seq + 1 };
                TLDifference diff = client.SendRequestAsync<TLAbsDifference>(req).Result as TLDifference;

                if (diff != null)
                {
                    foreach (TLUpdateNewChannelMessage upd in diff.OtherUpdates.OfType<TLUpdateNewChannelMessage>())
                        Console.WriteLine(((TLMessage)upd.Message).Message);

                    foreach (TLChannel ch in diff.Chats.OfType<TLChannel>().Where(x => !x.Left))
                    {
                        TLInputChannel ich = new TLInputChannel { ChannelId = ch.Id, AccessHash = ch.AccessHash ?? 0 };
                        TLRequestReadHistory readed = new TLRequestReadHistory { Channel = ich, MaxId = -1 };
                        client.SendRequestAsync<bool>(readed).Wait();
                    }
                }
            }

But state.UnreadCount > 0 only for unread messages from PeerUsers. And even if state.UnreadCount > 0, client.SendRequestAsync<TLAbsDifference> always returns TLDifferenceEmpty.

Also I tried:

            while (true)
            {
                Task.Delay(2000).Wait();
                var dialogs = client.GetUserDialogsAsync().Result as TLDialogs;
                if (dialogs == null) continue;

                foreach (TLDialog dialog in dialogs.Dialogs.Where(lambdaDialog => lambdaDialog.Peer is TLPeerChannel && lambdaDialog.UnreadCount > 0))
                {
                    TLPeerChannel peer = (TLPeerChannel)dialog.Peer;
                    TLChannel channel = dialogs.Chats.OfType<TLChannel>().First(lambdaChannel => lambdaChannel.Id == peer.ChannelId);
                    TLInputPeerChannel target = new TLInputPeerChannel { ChannelId = channel.Id, AccessHash = channel.AccessHash ?? 0 };

                    TLChannelMessages hist = (TLChannelMessages)client.GetHistoryAsync(target, 0, -1, dialog.UnreadCount).Result;

                    var users = hist.Users.OfType<TLUser>().ToList();
                    foreach (TLMessage message in hist.Messages.OfType<TLMessage>())
                    {
                        TLUser sentUser = users.Single(lambdaUser => lambdaUser.Id == message.FromId);
                        Console.WriteLine($"{sentUser.FirstName} {sentUser.LastName} {sentUser.Username}: {message.Message}");
                    }

                    TLInputChannel channelToMarkRead = new TLInputChannel { ChannelId = target.ChannelId, AccessHash = target.AccessHash };
                    int firstUnreadMessageId = ((TLMessage)hist.Messages.First()).Id;
                    TLRequestReadHistory markHistoryAsReadRequest = new TLRequestReadHistory
                    {
                        Channel = channelToMarkRead,
                        MaxId = -1,
                        ConfirmReceived = true,
                        Dirty = true,
                        MessageId = firstUnreadMessageId,
                        Sequence = dialog.UnreadCount
                    };

                    bool isMarked = client.SendRequestAsync<bool>(markHistoryAsReadRequest).Result;
                }
            }

It shows me unread messages, but has two problems.

  1. It causes Flood prevention exception after several iterations if there are no new messages.
  2. It causes InvalidCastException on second iteration if there are new messages.
    Here what happens:
  • I call client.SendRequestAsync<bool>(markHistoryAsReadRequest) to mark messages as read.
  • It always returns False, despite messages have been marked as read.
  • On the next iteration I call var dialogs = client.GetUserDialogsAsync().Result as TLDialogs; again.
  • It causes InvalidCastException because SendRequestAsync<TLAbsDialogs> is called inside GetUserDialogsAsync. But it receives TLBoolTrue as a result. And tries to cast it to TLAbsDialogs which fails.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions