diff --git a/ProjectV/Directory.Packages.props b/ProjectV/Directory.Packages.props index 3522b013..f8fe3f0a 100644 --- a/ProjectV/Directory.Packages.props +++ b/ProjectV/Directory.Packages.props @@ -9,10 +9,10 @@ - - - - + + + + @@ -46,15 +46,15 @@ - + - - + + diff --git a/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbConfig.cs b/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbConfig.cs index 63776daa..6b9aaf21 100644 --- a/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbConfig.cs +++ b/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbConfig.cs @@ -13,11 +13,12 @@ public DataMapperTmdbConfig() public TmdbServiceConfigurationInfo Transform(TMDbConfig dataObject) { + var images = dataObject.Images; return new TmdbServiceConfigurationInfo( - baseUrl: dataObject.Images.BaseUrl, - secureBaseUrl: dataObject.Images.SecureBaseUrl, - backdropSizes: dataObject.Images.BackdropSizes, - posterSizes: dataObject.Images.PosterSizes + baseUrl: images?.BaseUrl ?? string.Empty, + secureBaseUrl: images?.SecureBaseUrl ?? string.Empty, + backdropSizes: images?.BackdropSizes ?? [], + posterSizes: images?.PosterSizes ?? [] ); } diff --git a/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbContainer.cs b/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbContainer.cs index 8b6070f6..9c80be48 100644 --- a/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbContainer.cs +++ b/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbContainer.cs @@ -22,7 +22,7 @@ public DataMapperTmdbContainer() public TmdbSearchContainer Transform(SearchContainer dataObject) { - var results = dataObject.Results + var results = (dataObject.Results ?? []) .Select(tmdb => _mapperTmdbMovie.Transform(tmdb)) .ToList(); diff --git a/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbMovie.cs b/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbMovie.cs index bed1d665..c54d864a 100644 --- a/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbMovie.cs +++ b/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/Mappers/DataMapperTmdbMovie.cs @@ -16,15 +16,15 @@ public TmdbMovieInfo Transform(SearchMovie dataObject) { return new TmdbMovieInfo( thingId: dataObject.Id, - title: dataObject.Title, + title: dataObject.Title ?? string.Empty, voteCount: dataObject.VoteCount, voteAverage: dataObject.VoteAverage, - overview: dataObject.Overview, + overview: dataObject.Overview ?? string.Empty, releaseDate: dataObject.ReleaseDate ?? new DateTime(), popularity: dataObject.Popularity, adult: dataObject.Adult, - genreIds: dataObject.GenreIds, - posterPath: dataObject.PosterPath + genreIds: dataObject.GenreIds ?? [], + posterPath: dataObject.PosterPath ?? string.Empty ); } diff --git a/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/TmdbClient.cs b/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/TmdbClient.cs index b7409b61..95d76fe7 100644 --- a/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/TmdbClient.cs +++ b/ProjectV/Libraries/ExternalServices/ProjectV.TmdbService/TmdbClient.cs @@ -59,21 +59,21 @@ public bool ThrowApiExceptions /// public string DefaultLanguage { - get => _tmdbClient.DefaultLanguage; + get => _tmdbClient.DefaultLanguage ?? string.Empty; set => _tmdbClient.DefaultLanguage = value.ThrowIfNull(nameof(value)); } /// public string DefaultCountry { - get => _tmdbClient.DefaultCountry; + get => _tmdbClient.DefaultCountry ?? string.Empty; set => _tmdbClient.DefaultCountry = value.ThrowIfNull(nameof(value)); } public TmdbServiceConfigurationInfo Config => _configMapper.Transform(_tmdbClient.Config); /// - public string ApiKey => _tmdbClient.ApiKey.ThrowIfNull(nameof(ApiKey)); + public string ApiKey => _tmdbClient.ApiKey ?? string.Empty; /// public IWebProxy WebProxy => _tmdbClient.WebProxy.ThrowIfNull(nameof(WebProxy)); @@ -123,7 +123,7 @@ public async Task GetConfigAsync() try { - SearchContainer response = await _tmdbClient.SearchMovieAsync( + SearchContainer? response = await _tmdbClient.SearchMovieAsync( query: query, page: page, includeAdult: includeAdult, @@ -133,6 +133,11 @@ public async Task GetConfigAsync() cancellationToken: cancellationToken ); + if (response is null) + { + return null; + } + return _dataMapper.Transform(response); } catch (Exception ex) diff --git a/ProjectV/WebServices/ProjectV.TelegramBotWebService/Startup.cs b/ProjectV/WebServices/ProjectV.TelegramBotWebService/Startup.cs index 3f7f905c..6876366c 100644 --- a/ProjectV/WebServices/ProjectV.TelegramBotWebService/Startup.cs +++ b/ProjectV/WebServices/ProjectV.TelegramBotWebService/Startup.cs @@ -23,7 +23,6 @@ using ProjectV.TelegramBotWebService.v1.Domain.Bot; using ProjectV.TelegramBotWebService.v1.Domain.Handlers; using ProjectV.TelegramBotWebService.v1.Domain.Polling; -using ProjectV.TelegramBotWebService.v1.Domain.Polling.Factories; using ProjectV.TelegramBotWebService.v1.Domain.Polling.Handlers; using ProjectV.TelegramBotWebService.v1.Domain.Receivers; using ProjectV.TelegramBotWebService.v1.Domain.Service.Setup.Factories; @@ -72,7 +71,6 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); var jwtOptionsSecion = Configuration.GetSection(nameof(JwtOptions)); diff --git a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Bot/BotService.cs b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Bot/BotService.cs index 7fc9e9f9..99bcb690 100644 --- a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Bot/BotService.cs +++ b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Bot/BotService.cs @@ -149,7 +149,7 @@ public async Task SendMessageAsync( string text, ParseMode parseMode = ParseMode.None, ReplyParameters? replyParameters = null, - IReplyMarkup? replyMarkup = null, + ReplyMarkup? replyMarkup = null, LinkPreviewOptions? linkPreviewOptions = null, int? messageThreadId = null, IEnumerable? entities = null, diff --git a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Bot/IBotService.cs b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Bot/IBotService.cs index 7c9de555..99e169b9 100644 --- a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Bot/IBotService.cs +++ b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Bot/IBotService.cs @@ -52,7 +52,7 @@ Task SendMessageAsync( string text, ParseMode parseMode = default, ReplyParameters? replyParameters = default, - IReplyMarkup? replyMarkup = default, + ReplyMarkup? replyMarkup = default, LinkPreviewOptions? linkPreviewOptions = default, int? messageThreadId = default, IEnumerable? entities = default, diff --git a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/BotPolling.cs b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/BotPolling.cs index d7ab7bba..7b7a005e 100644 --- a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/BotPolling.cs +++ b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/BotPolling.cs @@ -6,8 +6,9 @@ using ProjectV.Logging; using ProjectV.TelegramBotWebService.Options; using ProjectV.TelegramBotWebService.v1.Domain.Bot; -using ProjectV.TelegramBotWebService.v1.Domain.Polling.Factories; using ProjectV.TelegramBotWebService.v1.Domain.Polling.Handlers; +using Telegram.Bot; +using Telegram.Bot.Polling; namespace ProjectV.TelegramBotWebService.v1.Domain.Polling { @@ -19,8 +20,6 @@ public sealed class BotPolling : IBotPolling private readonly IBotService _botService; - private readonly IBotPollingReceiverFactory _processorFactory; - private readonly IBotPollingUpdateHandler _updateHandler; private bool DropPendingUpdatesOnDelete => _options.Bot.Webhook.DropPendingUpdatesOnDelete; @@ -29,12 +28,10 @@ public sealed class BotPolling : IBotPolling public BotPolling( IOptions options, IBotService botService, - IBotPollingReceiverFactory processorFactory, IBotPollingUpdateHandler updateHandler) { _options = options.GetCheckedValue(); _botService = botService.ThrowIfNull(nameof(botService)); - _processorFactory = processorFactory.ThrowIfNull(nameof(processorFactory)); _updateHandler = updateHandler.ThrowIfNull(nameof(updateHandler)); } @@ -48,8 +45,20 @@ public async Task StartReceivingUpdatesAsync(CancellationToken cancellationToken _logger.Info("Starting receiving updates from Telegram API via polling."); - var updateReceiver = _processorFactory.Create(_options.Bot.Polling); - await updateReceiver.ReceiveAsync(_updateHandler, cancellationToken); + var pollingOptions = _options.Bot.Polling; + var receiverOptions = new ReceiverOptions + { + Offset = pollingOptions.Offset, + AllowedUpdates = pollingOptions.AllowedUpdates, + Limit = pollingOptions.Limit, + DropPendingUpdates = pollingOptions.DropPendingUpdates, + }; + + await _botService.BotClient.ReceiveAsync( + updateHandler: _updateHandler, + receiverOptions: receiverOptions, + cancellationToken: cancellationToken + ); _logger.Info("Receiving updates from Telegram API via polling has been finished."); } diff --git a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Factories/BotPollingReceiverFactory.cs b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Factories/BotPollingReceiverFactory.cs index 36433b67..8cedffe6 100644 --- a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Factories/BotPollingReceiverFactory.cs +++ b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Factories/BotPollingReceiverFactory.cs @@ -1,9 +1,6 @@ -using System; using Acolyte.Assertions; using ProjectV.Logging; using ProjectV.TelegramBotWebService.Options; -using ProjectV.TelegramBotWebService.v1.Domain.Bot; -using ProjectV.TelegramBotWebService.v1.Domain.Polling.Receivers; using Telegram.Bot.Polling; namespace ProjectV.TelegramBotWebService.v1.Domain.Polling.Factories @@ -13,45 +10,19 @@ public sealed class BotPollingReceiverFactory : IBotPollingReceiverFactory private static readonly ILogger _logger = LoggerFactory.CreateLoggerFor(); - private readonly IBotService _botService; - - public BotPollingReceiverFactory( - IBotService botService) + public BotPollingReceiverFactory() { - _botService = botService.ThrowIfNull(nameof(botService)); } - #region IBotPollingProcessorFactory Implementation + #region IBotPollingReceiverFactory Implementation - public IUpdateReceiver Create(BotPollingOptions options) + public ReceiverOptions Create(BotPollingOptions options) { options.ThrowIfNull(nameof(options)); - _logger.Info($"Creating bot polling receiver for mode: {options.ProcessingMode}."); - - var receiverOptions = CreateReceiverOptions(options); - - return options.ProcessingMode switch - { - _ when options.IsMode(BotPollingProcessingMode.LoopReceiving) => new DefaultUpdateReceiver(_botService.BotClient, receiverOptions), - - _ when options.IsMode(BotPollingProcessingMode.AsyncQueuedReceiving) => new AsyncQueuedUpdateReceiver(_botService.BotClient, receiverOptions), - - _ when options.IsMode(BotPollingProcessingMode.AsyncBlockingReceiving) => new AsyncBlockingUpdateReceiver(_botService.BotClient, receiverOptions), - - _ => throw new ArgumentOutOfRangeException( - nameof(options), - options.ProcessingMode, - $"Unexpected processing mode: '{options.ProcessingMode}'." - ) - }; - } - - #endregion + _logger.Info($"Creating receiver options for polling mode: {options.ProcessingMode}."); - private static ReceiverOptions CreateReceiverOptions(BotPollingOptions options) - { return new ReceiverOptions { Offset = options.Offset, @@ -60,5 +31,7 @@ private static ReceiverOptions CreateReceiverOptions(BotPollingOptions options) DropPendingUpdates = options.DropPendingUpdates, }; } + + #endregion } } diff --git a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Factories/IBotPollingReceiverFactory.cs b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Factories/IBotPollingReceiverFactory.cs index 205abb68..e27fbf63 100644 --- a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Factories/IBotPollingReceiverFactory.cs +++ b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Factories/IBotPollingReceiverFactory.cs @@ -1,10 +1,18 @@ -using ProjectV.TelegramBotWebService.Options; +using ProjectV.TelegramBotWebService.Options; using Telegram.Bot.Polling; namespace ProjectV.TelegramBotWebService.v1.Domain.Polling.Factories { + /// + /// Factory to create for polling. + /// + /// + /// NOTE: This interface is kept for potential future use. As of Telegram.Bot 22.10, + /// the IUpdateReceiver abstraction has been removed from the library. Polling is now + /// performed via directly. + /// public interface IBotPollingReceiverFactory { - IUpdateReceiver Create(BotPollingOptions options); + ReceiverOptions Create(BotPollingOptions options); } } diff --git a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncBlockingUpdateReceiver.cs b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncBlockingUpdateReceiver.cs index af880532..081af19b 100644 --- a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncBlockingUpdateReceiver.cs +++ b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncBlockingUpdateReceiver.cs @@ -1,13 +1,21 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Telegram.Bot; using Telegram.Bot.Polling; using Telegram.Bot.Types; namespace ProjectV.TelegramBotWebService.v1.Domain.Polling.Receivers { + /// + /// Blocking update receiver implementation. + /// + /// + /// NOTE: As of Telegram.Bot 22.10, BlockingUpdateReceiver has been removed from the + /// library. This class is kept for source compatibility but is no longer wired into the polling + /// pipeline. Polling is performed via + /// directly. + /// public sealed class AsyncBlockingUpdateReceiver : AsyncUpdateReceiverBase { - public AsyncBlockingUpdateReceiver( ITelegramBotClient botClient, ReceiverOptions? receiverOptions = default) @@ -17,14 +25,13 @@ public AsyncBlockingUpdateReceiver( #region UpdateReceiverBase Overridden Methods - protected override IAsyncEnumerable CreateAsyncEnumerator( + protected override async IAsyncEnumerable CreateAsyncEnumerator( IUpdateHandler updateHandler) { - return new BlockingUpdateReceiver( - botClient: _botClient, - receiverOptions: _receiverOptions, - pollingErrorHandler: (ex, token) => updateHandler.HandleErrorAsync(_botClient, ex, HandleErrorSource.HandleUpdateError, token) - ); + // NOTE: BlockingUpdateReceiver was removed in Telegram.Bot 22.10. + // This method is no longer called from the polling pipeline. + await System.Threading.Tasks.Task.CompletedTask; + yield break; } #endregion diff --git a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncQueuedUpdateReceiver.cs b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncQueuedUpdateReceiver.cs index 8ce59794..d878610b 100644 --- a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncQueuedUpdateReceiver.cs +++ b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncQueuedUpdateReceiver.cs @@ -1,10 +1,19 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Telegram.Bot; using Telegram.Bot.Polling; using Telegram.Bot.Types; namespace ProjectV.TelegramBotWebService.v1.Domain.Polling.Receivers { + /// + /// Queued update receiver implementation. + /// + /// + /// NOTE: As of Telegram.Bot 22.10, QueuedUpdateReceiver has been removed from the + /// library. This class is kept for source compatibility but is no longer wired into the polling + /// pipeline. Polling is performed via + /// directly. + /// public sealed class AsyncQueuedUpdateReceiver : AsyncUpdateReceiverBase { public AsyncQueuedUpdateReceiver( @@ -16,14 +25,13 @@ public AsyncQueuedUpdateReceiver( #region UpdateReceiverBase Overridden Methods - protected override IAsyncEnumerable CreateAsyncEnumerator( + protected override async IAsyncEnumerable CreateAsyncEnumerator( IUpdateHandler updateHandler) { - return new QueuedUpdateReceiver( - botClient: _botClient, - receiverOptions: _receiverOptions, - pollingErrorHandler: (ex, token) => updateHandler.HandleErrorAsync(_botClient, ex, HandleErrorSource.HandleUpdateError, token) - ); + // NOTE: QueuedUpdateReceiver was removed in Telegram.Bot 22.10. + // This method is no longer called from the polling pipeline. + await System.Threading.Tasks.Task.CompletedTask; + yield break; } #endregion diff --git a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncUpdateReceiverBase.cs b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncUpdateReceiverBase.cs index c0a2557f..2112142f 100644 --- a/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncUpdateReceiverBase.cs +++ b/ProjectV/WebServices/ProjectV.TelegramBotWebService/v1/Domain/Polling/Receivers/AsyncUpdateReceiverBase.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Acolyte.Assertions; @@ -8,7 +8,16 @@ namespace ProjectV.TelegramBotWebService.v1.Domain.Polling.Receivers { - public abstract class AsyncUpdateReceiverBase : IUpdateReceiver + /// + /// Base class for async update receivers. + /// + /// + /// NOTE: As of Telegram.Bot 22.10, IUpdateReceiver has been removed from the library. + /// This base class is kept for potential future extension but is no longer wired into the + /// polling pipeline directly. Polling is performed via + /// on . + /// + public abstract class AsyncUpdateReceiverBase { protected readonly ITelegramBotClient _botClient; @@ -23,8 +32,6 @@ public AsyncUpdateReceiverBase( _receiverOptions = receiverOptions; } - #region IUpdateReceiver Implementation - public async Task ReceiveAsync(IUpdateHandler updateHandler, CancellationToken cancellationToken = default) { @@ -36,8 +43,6 @@ public async Task ReceiveAsync(IUpdateHandler updateHandler, } } - #endregion - protected abstract IAsyncEnumerable CreateAsyncEnumerator( IUpdateHandler updateHandler); }