diff --git a/EXAMPLES.md b/EXAMPLES.md
index e4c6ccb..cf38563 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -312,14 +312,15 @@ finally
### Monitor all Telegram events happening for the user
-This is done through the `client.Update` callback event.
+This is done through the `client.OnUpdate` callback event.
+Your event handler implementation can either return `Task.CompletedTask` or be an `async Task` method.
See [Examples/Program_ListenUpdates.cs](Examples/Program_ListenUpdates.cs).
### Monitor new messages being posted in chats
-You have to handle `client.Update` events containing an `UpdateNewMessage`.
+You have to handle `client.OnUpdate` events containing an `UpdateNewMessage`.
See the `DisplayMessage` method in [Examples/Program_ListenUpdates.cs](Examples/Program_ListenUpdates.cs).
@@ -336,7 +337,7 @@ See [Examples/Program_DownloadSavedMedia.cs](Examples/Program_DownloadSavedMedia
### Collect Access Hash and save them for later use
-You can automate the collection of `access_hash` for the various resources obtained in response to API calls or Update events,
+You can automate the collection of `access_hash` for the various resources obtained in response to API calls or Updates,
so that you don't have to remember them by yourself or ask the API about them each time.
This is done by activating the experimental `client.CollectAccessHash` system.
diff --git a/Examples/Program_DownloadSavedMedia.cs b/Examples/Program_DownloadSavedMedia.cs
index 9ca7905..d8ca67d 100644
--- a/Examples/Program_DownloadSavedMedia.cs
+++ b/Examples/Program_DownloadSavedMedia.cs
@@ -15,10 +15,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.Update += Client_Update;
+ client.OnUpdate += Client_OnUpdate;
Console.ReadKey();
- async void Client_Update(IObject arg)
+ async Task Client_OnUpdate(IObject arg)
{
if (arg is not Updates { updates: var updates } upd) return;
foreach (var update in updates)
diff --git a/Examples/Program_Heroku.cs b/Examples/Program_Heroku.cs
index 31890cb..2eef6c3 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.Update += Client_Update;
+ Client.OnUpdate += Client_OnUpdate;
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 void Client_Update(IObject arg)
+ private static async Task Client_OnUpdate(IObject arg)
{
if (arg is not UpdatesBase updates) return;
updates.CollectUsersChats(Users, Chats);
diff --git a/Examples/Program_ListenUpdates.cs b/Examples/Program_ListenUpdates.cs
index 673754c..34567fb 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.Update += Client_Update;
+ Client.OnUpdate += Client_OnUpdate;
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
@@ -32,9 +32,10 @@ namespace WTelegramClientTest
}
}
- private static void Client_Update(IObject arg)
+ // in this example, we're not using async/await, so we just return Task.CompletedTask
+ private static Task Client_OnUpdate(IObject arg)
{
- if (arg is not UpdatesBase updates) return;
+ if (arg is not UpdatesBase updates) return Task.CompletedTask;
updates.CollectUsersChats(Users, Chats);
foreach (var update in updates.UpdateList)
switch (update)
@@ -52,6 +53,7 @@ namespace WTelegramClientTest
case UpdateUserPhoto uup: Console.WriteLine($"{User(uup.user_id)} has changed profile photo"); break;
default: Console.WriteLine(update.GetType().Name); break; // there are much more update types than the above cases
}
+ return Task.CompletedTask;
}
private static void DisplayMessage(MessageBase messageBase, bool edit = false)
diff --git a/FAQ.md b/FAQ.md
index ed096f1..6a08d53 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -134,7 +134,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 `Update` 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 `OnUpdate` events.
6. 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 happens often with VoIP or other easy-to-buy-online numbers, so expect fast ban)
7. 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.
8. When creating a new API ID/Hash, I recommend you use your own phone number with long history of normal Telegram usage, rather than a brand new phone number with short history.
@@ -191,7 +191,7 @@ If Telegram servers decide to shutdown this secondary connection, it's not an is
This should be transparent and pending API calls should automatically be resent upon reconnection.
You can choose to increase `MaxAutoReconnects` if it happens too often because your Internet connection is unstable.
-3) If you reach `MaxAutoReconnects` disconnections, then the **Update** event handler will receive a `ReactorError` object to notify you of the problem,
+3) If you reach `MaxAutoReconnects` disconnections, then the **OnUpdate** event handler will receive a `ReactorError` object to notify you of the problem.
and pending API calls throw the network IOException.
In this case, the recommended action would be to dispose the client and recreate one
diff --git a/README.md b/README.md
index 591d69a..1ff7205 100644
--- a/README.md
+++ b/README.md
@@ -130,7 +130,7 @@ In the API, Telegram uses some terms/classnames that can be confusing as they di
# Other things to know
-The Client class also offers an `Update` event that is triggered when Telegram servers sends Updates (like new messages or status), independently of your API requests. See [Examples/Program_ListenUpdates.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ListenUpdates.cs)
+The Client class also offers an `OnUpdate` event that is triggered when Telegram servers sends Updates (like new messages or status), independently of your API requests. See [Examples/Program_ListenUpdates.cs](https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ListenUpdates.cs)
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.Helpers.cs b/src/Client.Helpers.cs
index cf57217..7d4ea98 100644
--- a/src/Client.Helpers.cs
+++ b/src/Client.Helpers.cs
@@ -189,7 +189,7 @@ namespace WTelegram
else
updates = await this.Messages_SendMedia(peer, media, text, random_id, entities: entities,
reply_to_msg_id: reply_to_msg_id == 0 ? null : reply_to_msg_id, schedule_date: schedule_date == default ? null : schedule_date);
- OnUpdate(updates);
+ RaiseUpdate(updates);
int msgId = -1;
foreach (var update in updates.UpdateList)
{
@@ -282,7 +282,7 @@ namespace WTelegram
if (entities != null) lastMedia.flags = InputSingleMedia.Flags.has_entities;
var updates = await this.Messages_SendMultiMedia(peer, multiMedia, reply_to_msg_id: reply_to_msg_id, schedule_date: schedule_date);
- OnUpdate(updates);
+ RaiseUpdate(updates);
var msgIds = new int[medias.Length];
var result = new Message[medias.Length];
foreach (var update in updates.UpdateList)
diff --git a/src/Client.cs b/src/Client.cs
index f8cc64c..d4dd9fb 100644
--- a/src/Client.cs
+++ b/src/Client.cs
@@ -25,8 +25,8 @@ namespace WTelegram
public partial class Client : IDisposable
{
/// This event will be called when unsollicited updates/messages are sent by Telegram servers
- /// See Examples/Program_ListenUpdate.cs for how to use this
- public event Action Update;
+ /// Make your handler , or return
See Examples/Program_ListenUpdate.cs for how to use this
+ public event Func OnUpdate;
/// 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);
@@ -150,7 +150,7 @@ namespace WTelegram
public static void LoadPublicKey(string pem) => Encryption.LoadPublicKey(pem);
/// Builds a structure that is used to validate a 2FA password
- /// Password validation configuration. You can obtain this though an Update event as part of the login process
+ /// Password validation configuration. You can obtain this via Account_GetPassword or through OnUpdate as part of the login process
/// The password to validate
public static Task InputCheckPassword(Account_Password accountPassword, string password)
=> Check2FA(accountPassword, () => Task.FromResult(password));
@@ -321,7 +321,7 @@ namespace WTelegram
if (IsMainDC)
{
var updatesState = await this.Updates_GetState(); // this call reenables incoming Updates
- OnUpdate(updatesState);
+ RaiseUpdate(updatesState);
}
}
else
@@ -329,7 +329,7 @@ namespace WTelegram
}
catch
{
- OnUpdate(reactorError);
+ RaiseUpdate(reactorError);
lock (_pendingRpcs) // abort all pending requests
{
foreach (var rpc in _pendingRpcs.Values)
@@ -633,7 +633,7 @@ namespace WTelegram
rpc.tcs.SetException(new ApplicationException($"BadMsgNotification {badMsgNotification.error_code}"));
}
else
- OnUpdate(obj);
+ RaiseUpdate(obj);
break;
default:
if (_bareRpc != null)
@@ -648,7 +648,7 @@ namespace WTelegram
else
Helpers.Log(4, $"Received a {obj.GetType()} incompatible with expected bare {rpc?.type}");
}
- OnUpdate(obj);
+ RaiseUpdate(obj);
break;
}
@@ -658,19 +658,19 @@ namespace WTelegram
if (rpc != null)
rpc.tcs.SetResult(result);
else
- OnUpdate(obj);
+ RaiseUpdate(obj);
}
}
- private void OnUpdate(IObject obj)
+ private async void RaiseUpdate(IObject obj)
{
try
{
- Update?.Invoke(obj);
+ await OnUpdate?.Invoke(obj);
}
catch (Exception ex)
{
- Helpers.Log(4, $"{nameof(Update)} callback on {obj.GetType().Name} raised {ex}");
+ Helpers.Log(4, $"{nameof(OnUpdate)}({obj?.GetType().Name}) raised {ex}");
}
}
@@ -943,7 +943,7 @@ namespace WTelegram
{
resent:
var timeout = DateTime.UtcNow + TimeSpan.FromSeconds(sentCode.timeout);
- OnUpdate(sentCode);
+ RaiseUpdate(sentCode);
Helpers.Log(3, $"A verification code has been sent via {sentCode.type.GetType().Name[17..]}");
for (int retry = 1; authorization == null; retry++)
try
@@ -973,7 +973,7 @@ namespace WTelegram
try
{
var accountPassword = await this.Account_GetPassword();
- OnUpdate(accountPassword);
+ RaiseUpdate(accountPassword);
var checkPasswordSRP = await Check2FA(accountPassword, () => ConfigAsync("password"));
authorization = await this.Auth_CheckPassword(checkPasswordSRP);
}
@@ -992,7 +992,7 @@ namespace WTelegram
if (authorization is Auth_AuthorizationSignUpRequired signUpRequired)
{
var waitUntil = DateTime.UtcNow.AddSeconds(3);
- OnUpdate(signUpRequired); // give caller the possibility to read and accept TOS
+ RaiseUpdate(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;