diff --git a/EXAMPLES.md b/EXAMPLES.md
index 57b461d..8198f8f 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -187,7 +187,7 @@ Notes:
## Monitor all Telegram events happening for the user
-This is done through the `client.OnUpdate` callback event.
+This is done through the `client.OnUpdates` callback event.
Your event handler implementation can either return `Task.CompletedTask` or be an `async Task` method.
See [Examples/Program_ListenUpdates.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ListenUpdates.cs?ts=4#L23).
@@ -195,7 +195,7 @@ See [Examples/Program_ListenUpdates.cs](https://github.com/wiz0u/WTelegramClient
## Monitor new messages being posted in chats in real-time
-You have to handle `client.OnUpdate` events containing an `UpdateNewMessage`.
+You have to handle `client.OnUpdates` events containing an `UpdateNewMessage`.
See the `HandleMessage` method in [Examples/Program_ListenUpdates.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ListenUpdates.cs?ts=4#L23).
@@ -453,7 +453,7 @@ finally
## Collect Users/Chats description structures and access hash
Many API calls return a structure with a `users` and a `chats` field at the root of the structure.
-This is also the case for updates passed to `client.OnUpdate`.
+This is also the case for updates passed to `client.OnUpdates`.
These two dictionaries give details *(including access hash)* about the various users/chats that will be typically referenced in subobjects deeper in the structure,
typically in the form of a `Peer` object or a `user_id`/`chat_id` field.
@@ -473,7 +473,7 @@ private Dictionary _chats = new();
var dialogs = await client.Messages_GetAllDialogs();
dialogs.CollectUsersChats(_users, _chats);
-private async Task OnUpdate(UpdatesBase updates)
+private async Task OnUpdates(UpdatesBase updates)
{
updates.CollectUsersChats(_users, _chats);
...
diff --git a/Examples/Program_DownloadSavedMedia.cs b/Examples/Program_DownloadSavedMedia.cs
index 186ddbb..11e2271 100644
--- a/Examples/Program_DownloadSavedMedia.cs
+++ b/Examples/Program_DownloadSavedMedia.cs
@@ -1,7 +1,5 @@
using System;
-using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Threading.Tasks;
using TL;
@@ -15,10 +13,10 @@ namespace WTelegramClientTest
Console.WriteLine("The program will download photos/medias from messages you send/forward to yourself (Saved Messages)");
using var client = new WTelegram.Client(Environment.GetEnvironmentVariable);
var user = await client.LoginUserIfNeeded();
- client.OnUpdate += Client_OnUpdate;
+ client.OnUpdates += Client_OnUpdates;
Console.ReadKey();
- async Task Client_OnUpdate(UpdatesBase updates)
+ async Task Client_OnUpdates(UpdatesBase updates)
{
foreach (var update in updates.UpdateList)
{
diff --git a/Examples/Program_GetAllChats.cs b/Examples/Program_GetAllChats.cs
index 02fc287..8d1c442 100644
--- a/Examples/Program_GetAllChats.cs
+++ b/Examples/Program_GetAllChats.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using System.Threading.Tasks;
using TL;
diff --git a/Examples/Program_Heroku.cs b/Examples/Program_Heroku.cs
index 482b830..f1baa5a 100644
--- a/Examples/Program_Heroku.cs
+++ b/Examples/Program_Heroku.cs
@@ -30,7 +30,7 @@ namespace WTelegramClientTest
Client = new WTelegram.Client(store.Length == 0 ? null : Environment.GetEnvironmentVariable, store);
using (Client)
{
- Client.OnUpdate += Client_OnUpdate;
+ Client.OnUpdates += Client_OnUpdates;
My = await Client.LoginUserIfNeeded();
Console.WriteLine($"We are logged-in as {My.username ?? My.first_name + " " + My.last_name} (id {My.id})");
var dialogs = await Client.Messages_GetAllDialogs();
@@ -39,7 +39,7 @@ namespace WTelegramClientTest
}
}
- private static async Task Client_OnUpdate(UpdatesBase updates)
+ private static async Task Client_OnUpdates(UpdatesBase updates)
{
updates.CollectUsersChats(Users, Chats);
foreach (var update in updates.UpdateList)
diff --git a/Examples/Program_ListenUpdates.cs b/Examples/Program_ListenUpdates.cs
index ff0f502..fd2180e 100644
--- a/Examples/Program_ListenUpdates.cs
+++ b/Examples/Program_ListenUpdates.cs
@@ -20,7 +20,7 @@ namespace WTelegramClientTest
Client = new WTelegram.Client(Environment.GetEnvironmentVariable);
using (Client)
{
- Client.OnUpdate += Client_OnUpdate;
+ Client.OnUpdates += Client_OnUpdates;
My = await Client.LoginUserIfNeeded();
Users[My.id] = My;
// Note: on login, Telegram may sends a bunch of updates/messages that happened in the past and were not acknowledged
@@ -33,7 +33,7 @@ namespace WTelegramClientTest
}
// if not using async/await, we could just return Task.CompletedTask
- private static async Task Client_OnUpdate(UpdatesBase updates)
+ private static async Task Client_OnUpdates(UpdatesBase updates)
{
updates.CollectUsersChats(Users, Chats);
if (updates is UpdateShortMessage usm && !Users.ContainsKey(usm.user_id))
diff --git a/Examples/Program_ReactorError.cs b/Examples/Program_ReactorError.cs
index 5a8a0a8..ce0e629 100644
--- a/Examples/Program_ReactorError.cs
+++ b/Examples/Program_ReactorError.cs
@@ -1,6 +1,5 @@
using System;
using System.Threading.Tasks;
-using Telegram.Bot.Types;
using TL;
namespace WTelegramClientTest
@@ -28,7 +27,7 @@ namespace WTelegramClientTest
private static async Task CreateAndConnect()
{
Client = new WTelegram.Client(Environment.GetEnvironmentVariable);
- Client.OnUpdate += Client_OnUpdate;
+ Client.OnUpdates += Client_OnUpdates;
Client.OnOther += Client_OnOther;
var my = await Client.LoginUserIfNeeded();
Console.WriteLine($"We are logged-in as " + my);
@@ -61,7 +60,7 @@ namespace WTelegramClientTest
Console.WriteLine("Other: " + arg.GetType().Name);
}
- private static Task Client_OnUpdate(UpdatesBase updates)
+ private static Task Client_OnUpdates(UpdatesBase updates)
{
foreach (var update in updates.UpdateList)
Console.WriteLine(update.GetType().Name);
diff --git a/Examples/Program_SecretChats.cs b/Examples/Program_SecretChats.cs
index 2d02d0d..bebd5ac 100644
--- a/Examples/Program_SecretChats.cs
+++ b/Examples/Program_SecretChats.cs
@@ -25,7 +25,7 @@ namespace WTelegramClientTest
AppDomain.CurrentDomain.ProcessExit += (s, e) => { Secrets.Dispose(); Client.Dispose(); };
SelectActiveChat();
- Client.OnUpdate += Client_OnUpdate;
+ Client.OnUpdates += Client_OnUpdates;
var myself = await Client.LoginUserIfNeeded();
Users[myself.id] = myself;
Console.WriteLine($"We are logged-in as {myself}");
@@ -76,7 +76,7 @@ Type a command, or a message to send to the active secret chat:");
} while (true);
}
- private static async Task Client_OnUpdate(UpdatesBase updates)
+ private static async Task Client_OnUpdates(UpdatesBase updates)
{
updates.CollectUsersChats(Users, Chats);
foreach (var update in updates.UpdateList)
diff --git a/FAQ.md b/FAQ.md
index 84d0df4..60e7377 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -143,7 +143,7 @@ Here are some advices from [another similar library](https://github.com/gotd/td/
Some additional advices from me:
-5. Avoid repetitive polling or repetitive sequence of actions/requests: Save the initial results of your queries, and update those results when you're informed of a change through `OnUpdate` events.
+5. Avoid repetitive polling or repetitive sequence of actions/requests: Save the initial results of your queries, and update those results when you're informed of a change through `OnUpdates` events.
6. Don't buy fake user accounts/sessions and don't extract api_id/hash/authkey/sessions from official clients, this is [specifically forbidden by API TOS](https://core.telegram.org/api/terms#2-transparency). You must use your own api_id and create your own sessions associated with it.
7. If a phone number is brand new, it will be closely monitored by Telegram for abuse, and it can even already be considered a bad user due to bad behavior from the previous owner of that phone number (which may happen often with VoIP or other easy-to-buy-online numbers, so expect fast ban)
8. You may want to use your new phone number account with an official Telegram client and act like a normal user for some time (some weeks/months), before using it for automation with WTelegramClient.
@@ -261,7 +261,7 @@ The following choices were made while implementing Secret Chats in WTelegramClie
If for some reason, we received them in incorrect order, messages are kept in memory until the requested missing messages are obtained.
If those missing messages are never obtained during the session, incoming messages might get stuck and lost.
- SecretChats file data is only valid for the current user, so make sure to pick the right file *(or a new file name)* if you change logged-in user.
-- If you want to accept incoming Secret Chats request only from specific user, you must check it in OnUpdate before:
+- If you want to accept incoming Secret Chats request only from specific user, you must check it in OnUpdates before:
`await Secrets.HandleUpdate(ue, ue.chat is EncryptedChatRequested ecr && ecr.admin_id == EXPECTED_USER_ID);`
- As recommended, new encryption keys are negotiated every 100 sent/received messages or after one week.
If remote client doesn't complete this negotiation before reaching 200 messages, the Secret Chat is aborted.
diff --git a/README.md b/README.md
index 155f37f..fec7352 100644
--- a/README.md
+++ b/README.md
@@ -164,7 +164,7 @@ See [FAQ #4](https://wiz0u.github.io/WTelegramClient/FAQ#access-hash) to learn m
# Other things to know
-The Client class also offers `OnUpdate` and `OnOther` events that are triggered when Telegram servers sends Updates (like new messages or status) or other notifications, independently of your API requests.
+The Client class also offers `OnUpdates` and `OnOther` events that are triggered when Telegram servers sends Updates (like new messages or status) or other notifications, independently of your API requests.
See [Examples/Program_ListenUpdates.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ListenUpdates.cs?ts=4#L23) and [Examples/Program_ReactorError.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ReactorError.cs?ts=4#L32)
An invalid API request can result in a `RpcException` being raised, reflecting the [error code and status text](https://revgram.github.io/errors.html) of the problem.
diff --git a/src/Client.cs b/src/Client.cs
index af57f0b..b94b6b8 100644
--- a/src/Client.cs
+++ b/src/Client.cs
@@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
-using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Sockets;
@@ -25,11 +24,13 @@ namespace WTelegram
{
/// This event will be called when unsollicited updates/messages are sent by Telegram servers
/// Make your handler , or return or
See Examples/Program_ListenUpdate.cs for how to use this
- public event Func OnUpdate;
+ public event Func OnUpdates;
+ [Obsolete("This event was renamed OnUpdates (plural)")]
+ public event Func OnUpdate { add { OnUpdates += value; } remove { OnUpdates -= value; } }
/// This event is called for other types of notifications (login states, reactor errors, ...)
public event Func OnOther;
/// Use this handler to intercept Updates that resulted from your own API calls
- public event Func OnOwnUpdate;
+ public event Func OnOwnUpdates;
/// Used to create a TcpClient connected to the given address/port, or throw an exception on failure
public TcpFactory TcpHandler { get; set; } = DefaultTcpHandler;
public delegate Task TcpFactory(string host, int port);
@@ -355,13 +356,13 @@ namespace WTelegram
if (IsMainDC)
{
var updatesState = await this.Updates_GetState(); // this call reenables incoming Updates
- RaiseUpdate(updatesState);
+ RaiseUpdates(updatesState);
}
}
catch
{
if (IsMainDC)
- RaiseUpdate(reactorError);
+ RaiseUpdates(reactorError);
lock (_pendingRpcs) // abort all pending requests
{
foreach (var rpc in _pendingRpcs.Values)
@@ -583,11 +584,11 @@ namespace WTelegram
else
{
Helpers.Log(1, $" → {result?.GetType().Name,-37} #{(short)msgId.GetHashCode():X4}");
- if (OnOwnUpdate != null)
+ if (OnOwnUpdates != null)
if (result is UpdatesBase updates)
- RaiseOwnUpdate(updates);
+ RaiseOwnUpdates(updates);
else if (result is Messages_AffectedMessages affected)
- RaiseOwnUpdate(new UpdateShort { update = new UpdateAffectedMessages { affected = affected }, date = MsgIdToStamp(_lastRecvMsgId) });
+ RaiseOwnUpdates(new UpdateShort { update = new UpdateAffectedMessages { affected = affected }, date = MsgIdToStamp(_lastRecvMsgId) });
}
rpc.tcs.SetResult(result);
@@ -611,8 +612,8 @@ namespace WTelegram
else
{
result = reader.ReadTLObject(ctorNb);
- if (OnOwnUpdate != null && result is UpdatesBase updates)
- RaiseOwnUpdate(updates);
+ if (OnOwnUpdates != null && result is UpdatesBase updates)
+ RaiseOwnUpdates(updates);
}
var typeName = result?.GetType().Name;
@@ -673,7 +674,7 @@ namespace WTelegram
break;
case Pong pong:
SetResult(pong.msg_id, pong);
- RaiseUpdate(pong);
+ RaiseUpdates(pong);
break;
case FutureSalts futureSalts:
SetResult(futureSalts.req_msg_id, futureSalts);
@@ -733,10 +734,10 @@ namespace WTelegram
rpc.tcs.SetException(new WTException($"BadMsgNotification {badMsgNotification.error_code}"));
}
else
- RaiseUpdate(badMsgNotification);
+ RaiseUpdates(badMsgNotification);
break;
default:
- RaiseUpdate(obj);
+ RaiseUpdates(obj);
break;
}
@@ -746,32 +747,32 @@ namespace WTelegram
if (rpc != null)
rpc.tcs.SetResult(result);
else
- RaiseUpdate(obj);
+ RaiseUpdates(obj);
}
}
- private async void RaiseUpdate(IObject obj)
+ private async void RaiseUpdates(IObject obj)
{
try
{
- var task = obj is UpdatesBase updates ? OnUpdate?.Invoke(updates) : OnOther?.Invoke(obj);
+ var task = obj is UpdatesBase updates ? OnUpdates?.Invoke(updates) : OnOther?.Invoke(obj);
if (task != null) await task;
}
catch (Exception ex)
{
- Helpers.Log(4, $"{nameof(OnUpdate)}({obj?.GetType().Name}) raised {ex}");
+ Helpers.Log(4, $"{nameof(OnUpdates)}({obj?.GetType().Name}) raised {ex}");
}
}
- private async void RaiseOwnUpdate(UpdatesBase updates)
+ private async void RaiseOwnUpdates(UpdatesBase updates)
{
try
{
- await OnOwnUpdate(updates);
+ await OnOwnUpdates(updates);
}
catch (Exception ex)
{
- Helpers.Log(4, $"{nameof(OnOwnUpdate)}({updates.GetType().Name}) raised {ex}");
+ Helpers.Log(4, $"{nameof(OnOwnUpdates)}({updates.GetType().Name}) raised {ex}");
}
}
@@ -1050,7 +1051,7 @@ namespace WTelegram
if (self.id == long.Parse(botToken.Split(':')[0]))
{
_session.UserId = _dcSession.UserId = self.id;
- RaiseUpdate(self);
+ RaiseUpdates(self);
return User = self;
}
Helpers.Log(3, $"Current logged user {self.id} mismatched bot_token. Logging out and in...");
@@ -1089,7 +1090,7 @@ namespace WTelegram
self.phone == string.Concat((phone_number = Config("phone_number")).Where(char.IsDigit)))
{
_session.UserId = _dcSession.UserId = self.id;
- RaiseUpdate(self);
+ RaiseUpdates(self);
return User = self;
}
var mismatch = $"Current logged user {self.id} mismatched user_id or phone_number";
@@ -1124,7 +1125,7 @@ namespace WTelegram
{
phone_code_hash = setupSentCode.phone_code_hash;
Helpers.Log(3, "A login email is required");
- RaiseUpdate(sentCodeBase);
+ RaiseUpdates(sentCodeBase);
var email = _config("email");
if (string.IsNullOrEmpty(email))
sentCodeBase = await this.Auth_ResendCode(phone_number, phone_code_hash);
@@ -1135,7 +1136,7 @@ namespace WTelegram
{
var sentEmail = await this.Account_SendVerifyEmailCode(purpose, email);
Helpers.Log(3, "An email verification code has been sent to " + sentEmail.email_pattern);
- RaiseUpdate(sentEmail);
+ RaiseUpdates(sentEmail);
}
Account_EmailVerified verified = null;
for (int retry = 1; verified == null; retry++)
@@ -1166,7 +1167,7 @@ namespace WTelegram
phone_code_hash = sentCode.phone_code_hash;
var timeout = DateTime.UtcNow + TimeSpan.FromSeconds(sentCode.timeout);
Helpers.Log(3, $"A verification code has been sent via {sentCode.type.GetType().Name[17..]}");
- RaiseUpdate(sentCode);
+ RaiseUpdates(sentCode);
if (sentCode.type is Auth_SentCodeTypeFirebaseSms firebaseSms)
{
var token = await ConfigAsync("firebase");
@@ -1210,7 +1211,7 @@ namespace WTelegram
try
{
var accountPassword = await this.Account_GetPassword();
- RaiseUpdate(accountPassword);
+ RaiseUpdates(accountPassword);
var checkPasswordSRP = await Check2FA(accountPassword, () => ConfigAsync("password"));
authorization = await this.Auth_CheckPassword(checkPasswordSRP);
}
@@ -1230,7 +1231,7 @@ namespace WTelegram
if (authorization is Auth_AuthorizationSignUpRequired signUpRequired)
{
var waitUntil = DateTime.UtcNow.AddSeconds(3);
- RaiseUpdate(signUpRequired); // give caller the possibility to read and accept TOS
+ RaiseUpdates(signUpRequired); // give caller the possibility to read and accept TOS
var first_name = Config("first_name");
var last_name = Config("last_name");
var wait = waitUntil - DateTime.UtcNow;
@@ -1257,7 +1258,7 @@ namespace WTelegram
throw new WTException("Failed to get Authorization: " + authorization.GetType().Name);
_session.UserId = _dcSession.UserId = self.id;
lock (_session) _session.Save();
- RaiseUpdate(self);
+ RaiseUpdates(self);
return User = self;
}
diff --git a/src/SecretChats.cs b/src/SecretChats.cs
index c7b78cf..5773c8c 100644
--- a/src/SecretChats.cs
+++ b/src/SecretChats.cs
@@ -21,7 +21,7 @@ namespace WTelegram
int RemoteLayer { get; }
}
- [TLDef(0xFEFEFEFE)]
+ [TLDef(0xFEFEFEFE)] [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles")]
internal sealed partial class SecretChat : IObject, ISecretChat
{
[Flags] public enum Flags : uint { requestChat = 1, renewKey = 2, acceptKey = 4, originator = 8, commitKey = 16 }
@@ -170,7 +170,7 @@ namespace WTelegram
return chat_id;
}
- /// Processes the you received from Telegram ().
+ /// Processes the you received from Telegram ().
/// If update.chat is , you might want to first make sure you want to accept this secret chat initiated by user
/// Incoming requests for secret chats are automatically: accepted (), rejected () or ignored ()
/// if the update was handled successfully
diff --git a/src/TL.cs b/src/TL.cs
index 2eee871..e526e40 100644
--- a/src/TL.cs
+++ b/src/TL.cs
@@ -396,7 +396,7 @@ namespace TL
public static implicit operator byte[](Int256 int256) => int256.raw;
}
- public sealed partial class UpdateAffectedMessages : Update // auto-generated for OnOwnUpdate in case of such API call result
+ public sealed partial class UpdateAffectedMessages : Update // auto-generated for OnOwnUpdates in case of such API call result
{
public Messages_AffectedMessages affected;
public override (long, int, int) GetMBox() => (0, affected.pts, affected.pts_count);