mirror of
https://github.com/wiz0u/WTelegramClient.git
synced 2025-12-06 06:52:01 +01:00
Renamed Update event to OnUpdate, returning Task
(to gracefully handle async exceptions)
This commit is contained in:
parent
6977641b2d
commit
668b19e3e8
|
|
@ -312,14 +312,15 @@ finally
|
|||
<a name="updates"></a>
|
||||
### 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).
|
||||
|
||||
<a name="monitor-msg"></a>
|
||||
### 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
|
|||
<a name="collect-access-hash"></a>
|
||||
### 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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
4
FAQ.md
4
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ namespace WTelegram
|
|||
public partial class Client : IDisposable
|
||||
{
|
||||
/// <summary>This event will be called when unsollicited updates/messages are sent by Telegram servers</summary>
|
||||
/// <remarks>See <see href="https://github.com/wiz0u/WTelegramClient/tree/master/Examples/Program_ListenUpdate.cs">Examples/Program_ListenUpdate.cs</see> for how to use this</remarks>
|
||||
public event Action<IObject> Update;
|
||||
/// <remarks>Make your handler <see langword="async"/>, or return <see cref="Task.CompletedTask"></see><br/>See <see href="https://github.com/wiz0u/WTelegramClient/blob/master/Examples/Program_ListenUpdates.cs">Examples/Program_ListenUpdate.cs</see> for how to use this</remarks>
|
||||
public event Func<IObject, Task> OnUpdate;
|
||||
/// <summary>Used to create a TcpClient connected to the given address/port, or throw an exception on failure</summary>
|
||||
public TcpFactory TcpHandler { get; set; } = DefaultTcpHandler;
|
||||
public delegate Task<TcpClient> TcpFactory(string host, int port);
|
||||
|
|
@ -150,7 +150,7 @@ namespace WTelegram
|
|||
public static void LoadPublicKey(string pem) => Encryption.LoadPublicKey(pem);
|
||||
|
||||
/// <summary>Builds a structure that is used to validate a 2FA password</summary>
|
||||
/// <param name="accountPassword">Password validation configuration. You can obtain this though an Update event as part of the login process</param>
|
||||
/// <param name="accountPassword">Password validation configuration. You can obtain this via <c>Account_GetPassword</c> or through OnUpdate as part of the login process</param>
|
||||
/// <param name="password">The password to validate</param>
|
||||
public static Task<InputCheckPasswordSRP> 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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue