using Telegram.Bot; using Telegram.Bot.Polling; using Telegram.Bot.Requests; using Telegram.Bot.Types; namespace Telegrator.Polling { /// /// Reactive implementation of for polling updates from Telegram. /// Provides custom update receiving logic with error handling and configuration options. /// /// The Telegram bot client for making API requests. /// Optional receiver options for configuring update polling behavior. public class ReactiveUpdateReceiver(ITelegramBotClient client, ReceiverOptions? options) : IUpdateReceiver { /// /// Gets the receiver options for configuring update polling behavior. /// public readonly ReceiverOptions? Options = options; /// /// Gets the Telegram bot client for making API requests. /// public readonly ITelegramBotClient Client = client; /// /// Receives updates from Telegram using long polling. /// Handles update processing, error handling, and cancellation. /// /// The update handler to process received updates. /// The cancellation token to stop receiving updates. /// A task representing the asynchronous update receiving operation. public async Task ReceiveAsync(IUpdateHandler updateHandler, CancellationToken cancellationToken) { cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken).Token; GetUpdatesRequest request = new GetUpdatesRequest() { AllowedUpdates = Options?.AllowedUpdates ?? [], Limit = Options?.Limit.GetValueOrDefault(100), Offset = Options?.Offset }; if (Options?.DropPendingUpdates ?? false) { try { Update[] array = await Client.GetUpdates(-1, 1, 0, [], cancellationToken).ConfigureAwait(false); request.Offset = array.Length != 0 ? array[^1].Id + 1 : 0; } catch (OperationCanceledException) { return; } } while (!cancellationToken.IsCancellationRequested) { try { request.Timeout = (int)Client.Timeout.TotalSeconds; foreach (Update update in await Client.SendRequest(request, cancellationToken).ConfigureAwait(false)) { try { request.Offset = update.Id + 1; await updateHandler.HandleUpdateAsync(Client, update, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } catch (Exception exception2) { await updateHandler.HandleErrorAsync(Client, exception2, HandleErrorSource.HandleUpdateError, cancellationToken).ConfigureAwait(false); } } } catch (OperationCanceledException) { return; } catch (Exception exception) { await updateHandler.HandleErrorAsync(Client, exception, HandleErrorSource.PollingError, cancellationToken).ConfigureAwait(false); } } } } }