mirror of
https://github.com/wiz0u/WTelegramClient.git
synced 2025-12-06 06:52:01 +01:00
Handle BadMsgNotification 32/33 by renewing session
This commit is contained in:
parent
bafe3c56bd
commit
e1132f653b
6
FAQ.md
6
FAQ.md
|
|
@ -32,9 +32,9 @@ This might require adding a reference *(and `using`)* to the Microsoft.VisualBas
|
|||
|
||||
#### 4. I get the error `CHAT_ID_INVALID` or `CHANNEL_INVALID`
|
||||
|
||||
First, you should distinguish between Chat, Channel and Group/Supergroup: See Terminology in [ReadMe](README.md#Terminology-in-Telegram-Client-API)
|
||||
Most chat groups are in fact not a simple `Chat` but rather a (super)group (= a `Channel` without the `broadcast` flag)
|
||||
Some TL methods only applies to simple Chat, and some only applies to Channels.
|
||||
First, you should distinguish between Chat, Channel and Group/Supergroup: See Terminology in [ReadMe](README.md#Terminology-in-Telegram-Client-API).
|
||||
Common chat groups are usually not a simple `Chat` but rather a supergroup: a `Channel` without the `broadcast` flag
|
||||
Some TL methods only applies to simple `Chat`, and some only applies to `Channel`.
|
||||
|
||||
A simple `Chat` can be queried using their `chat_id` only.
|
||||
But a `Channel` must be queried using an `InputChannel` or `InputPeerChannel` object that specifies the `channel_id` as well as an `access_hash` that proves you are allowed to access it.
|
||||
|
|
|
|||
|
|
@ -106,9 +106,9 @@ await client.SendMessageAsync(target, "Hello, World");
|
|||
# Terminology in Telegram Client API
|
||||
|
||||
In the API, Telegram uses some terms/classnames that can be confusing as they differ from the terms shown to end-users:
|
||||
- `Channel` : A (large) chat group *(sometimes called supergroup)* or a broadcast channel (the `broadcast` flag differenciate those)
|
||||
- `Chat` : A private simple chat group with few people (it may be migrated to a supergroup/channel when it doesn't fit anymore)
|
||||
- Chats : In plural, it means either `Chat` or `Channel`
|
||||
- `Channel` : A (large or public) chat group *(sometimes called supergroup)* or a broadcast channel (the `broadcast` flag differenciate those)
|
||||
- `Chat` : A private simple chat group with less than 200 members (it may be migrated to a supergroup `Channel` with a new ID when it gets bigger or public, in which case the old `Chat` will still exist but be `deactivated`)
|
||||
- chats : In plural or general meaning, it means either `Chat` or `Channel`
|
||||
- `Peer` : Either a `Chat`, `Channel` or a private chat with a `User`
|
||||
- Dialog : The current status of a chat with a `Peer` *(draft, last message, unread count, pinned...)*
|
||||
- DC (DataCenter) : There are a few datacenters depending on where in the world the user (or an uploaded media file) is from.
|
||||
|
|
|
|||
|
|
@ -837,19 +837,6 @@ namespace WTelegram
|
|||
if (msgCopy?.orig_message?.body != null)
|
||||
await HandleMessageAsync(msgCopy.orig_message.body);
|
||||
break;
|
||||
case BadServerSalt badServerSalt:
|
||||
_dcSession.Salt = badServerSalt.new_server_salt;
|
||||
if (badServerSalt.bad_msg_id == _dcSession.LastSentMsgId)
|
||||
{
|
||||
var newMsgId = await SendAsync(_lastSentMsg, true);
|
||||
lock (_pendingRequests)
|
||||
if (_pendingRequests.TryGetValue(badServerSalt.bad_msg_id, out var t))
|
||||
{
|
||||
_pendingRequests.Remove(badServerSalt.bad_msg_id);
|
||||
_pendingRequests[newMsgId] = t;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TL.Methods.Ping ping:
|
||||
_ = SendAsync(new Pong { msg_id = _lastRecvMsgId, ping_id = ping.ping_id }, false);
|
||||
break;
|
||||
|
|
@ -864,17 +851,48 @@ namespace WTelegram
|
|||
case MsgsAck msgsAck:
|
||||
break; // we don't do anything with these, for now
|
||||
case BadMsgNotification badMsgNotification:
|
||||
{
|
||||
await _sendSemaphore.WaitAsync();
|
||||
bool retryLast = badMsgNotification.bad_msg_id == _dcSession.LastSentMsgId;
|
||||
var lastSentMsg = _lastSentMsg;
|
||||
_sendSemaphore.Release();
|
||||
Helpers.Log(4, $"BadMsgNotification {badMsgNotification.error_code} for msg #{(short)badMsgNotification.bad_msg_id.GetHashCode():X4}");
|
||||
var tcs = PullPendingRequest(badMsgNotification.bad_msg_id).tcs;
|
||||
if (tcs != null)
|
||||
switch (badMsgNotification.error_code)
|
||||
{
|
||||
case 32: // msg_seqno too low (the server has already received a message with a lower msg_id but with either a higher or an equal and odd seqno)
|
||||
case 33: // msg_seqno too high (similarly, there is a message with a higher msg_id but with either a lower or an equal and odd seqno)
|
||||
if (_dcSession.Seqno <= 1)
|
||||
retryLast = false;
|
||||
else
|
||||
{
|
||||
Reset(false, false);
|
||||
_dcSession.Renew();
|
||||
await ConnectAsync();
|
||||
}
|
||||
break;
|
||||
case 48: // incorrect server salt (in this case, the bad_server_salt response is received with the correct salt, and the message is to be re-sent with it)
|
||||
_dcSession.Salt = ((BadServerSalt)badMsgNotification).new_server_salt;
|
||||
break;
|
||||
default:
|
||||
retryLast = false;
|
||||
break;
|
||||
}
|
||||
if (retryLast)
|
||||
{
|
||||
var newMsgId = await SendAsync(lastSentMsg, true);
|
||||
lock (_pendingRequests)
|
||||
if (_pendingRequests.TryGetValue(badMsgNotification.bad_msg_id, out var t))
|
||||
{
|
||||
_pendingRequests.Remove(badMsgNotification.bad_msg_id);
|
||||
_pendingRequests[newMsgId] = t;
|
||||
}
|
||||
}
|
||||
else if (PullPendingRequest(badMsgNotification.bad_msg_id).tcs is TaskCompletionSource<object> tcs)
|
||||
{
|
||||
if (_bareRequest == badMsgNotification.bad_msg_id) _bareRequest = 0;
|
||||
tcs.SetException(new ApplicationException($"BadMsgNotification {badMsgNotification.error_code}"));
|
||||
}
|
||||
else
|
||||
OnUpdate(obj);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (_bareRequest != 0)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace WTelegram
|
|||
public static Action<int, string> Log { get; set; } = DefaultLogger;
|
||||
|
||||
/// <summary>For serializing indented Json with fields included</summary>
|
||||
public static readonly JsonSerializerOptions JsonOptions = new() { IncludeFields = true, WriteIndented = true };
|
||||
public static readonly JsonSerializerOptions JsonOptions = new() { IncludeFields = true, WriteIndented = true, IgnoreReadOnlyProperties = true };
|
||||
|
||||
public static V GetOrCreate<K, V>(this Dictionary<K, V> dictionary, K key) where V : new()
|
||||
=> dictionary.TryGetValue(key, out V value) ? value : dictionary[key] = new V();
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ namespace WTelegram
|
|||
internal Client Client;
|
||||
internal int DcID => DataCenter?.id ?? 0;
|
||||
internal IPEndPoint EndPoint => DataCenter == null ? null : new(IPAddress.Parse(DataCenter.ip_address), DataCenter.port);
|
||||
internal void Renew() { Helpers.Log(3, $"Renewing session on DC {DcID}..."); Id = Helpers.RandomLong(); Seqno = 0; LastSentMsgId = 0; }
|
||||
}
|
||||
|
||||
public DateTime SessionStart => _sessionStart;
|
||||
|
|
|
|||
Loading…
Reference in a new issue