diff --git a/Telegrator.Hosting/Logging/MicrosoftLoggingAdapter.cs b/Telegrator.Hosting/Logging/MicrosoftLoggingAdapter.cs index 1caf4d7..12e4e6e 100644 --- a/Telegrator.Hosting/Logging/MicrosoftLoggingAdapter.cs +++ b/Telegrator.Hosting/Logging/MicrosoftLoggingAdapter.cs @@ -1,3 +1,4 @@ +using Microsoft.Extensions.Logging; using Telegrator.Logging; namespace Telegrator.Hosting.Logging @@ -8,27 +9,27 @@ namespace Telegrator.Hosting.Logging /// public class MicrosoftLoggingAdapter : ITelegratorLogger { - private readonly Microsoft.Extensions.Logging.ILogger _logger; + private readonly ILogger _logger; /// /// Initializes a new instance of MicrosoftLoggingAdapter. /// /// The Microsoft.Extensions.Logging logger instance. - public MicrosoftLoggingAdapter(Microsoft.Extensions.Logging.ILogger logger) + public MicrosoftLoggingAdapter(ILogger logger) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } /// - public void Log(LogLevel level, string message, Exception? exception = null) + public void Log(Telegrator.Logging.LogLevel level, string message, Exception? exception = null) { var msLogLevel = level switch { - LogLevel.Trace => Microsoft.Extensions.Logging.LogLevel.Trace, - LogLevel.Debug => Microsoft.Extensions.Logging.LogLevel.Debug, - LogLevel.Information => Microsoft.Extensions.Logging.LogLevel.Information, - LogLevel.Warning => Microsoft.Extensions.Logging.LogLevel.Warning, - LogLevel.Error => Microsoft.Extensions.Logging.LogLevel.Error, + Telegrator.Logging.LogLevel.Trace => Microsoft.Extensions.Logging.LogLevel.Trace, + Telegrator.Logging.LogLevel.Debug => Microsoft.Extensions.Logging.LogLevel.Debug, + Telegrator.Logging.LogLevel.Information => Microsoft.Extensions.Logging.LogLevel.Information, + Telegrator.Logging.LogLevel.Warning => Microsoft.Extensions.Logging.LogLevel.Warning, + Telegrator.Logging.LogLevel.Error => Microsoft.Extensions.Logging.LogLevel.Error, _ => Microsoft.Extensions.Logging.LogLevel.Information }; diff --git a/Telegrator.Hosting/TypesExtensions.cs b/Telegrator.Hosting/TypesExtensions.cs index d245c30..93b3f69 100644 --- a/Telegrator.Hosting/TypesExtensions.cs +++ b/Telegrator.Hosting/TypesExtensions.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Diagnostics.CodeAnalysis; @@ -50,7 +49,6 @@ namespace Telegrator.Hosting services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - //services.AddSingleton(services => new TelegramBotInfo(services.GetRequiredService().GetMe().Result)); services.AddSingleton(); return services; diff --git a/Telegrator.sln b/Telegrator.sln index f9bed94..88c8e42 100644 --- a/Telegrator.sln +++ b/Telegrator.sln @@ -20,6 +20,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegrator.Analyzers", "Tel EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegrator.Hosting.Web", "Telegrator.Hosting.Web\Telegrator.Hosting.Web.csproj", "{98AB490F-6A36-CCFF-F6E6-B029D1665965}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SosalBot", "..\SosalBot\SosalBot\SosalBot.csproj", "{D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AnalyzersDebug|Any CPU = AnalyzersDebug|Any CPU @@ -63,6 +65,12 @@ Global {98AB490F-6A36-CCFF-F6E6-B029D1665965}.Debug|Any CPU.Build.0 = Debug|Any CPU {98AB490F-6A36-CCFF-F6E6-B029D1665965}.Release|Any CPU.ActiveCfg = Release|Any CPU {98AB490F-6A36-CCFF-F6E6-B029D1665965}.Release|Any CPU.Build.0 = Release|Any CPU + {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.AnalyzersDebug|Any CPU.ActiveCfg = Release|Any CPU + {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.AnalyzersDebug|Any CPU.Build.0 = Release|Any CPU + {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Telegrator/Attributes/Components/StateKeeperAttributeBase.cs b/Telegrator/Attributes/Components/StateKeeperAttributeBase.cs index f1b5262..ba69146 100644 --- a/Telegrator/Attributes/Components/StateKeeperAttributeBase.cs +++ b/Telegrator/Attributes/Components/StateKeeperAttributeBase.cs @@ -12,7 +12,7 @@ namespace Telegrator.Attributes.Components public abstract class StateKeeperAttributeBase : Attribute, IFilter { /// - public bool IsCollectible => this.HasPublicProperties(); + public bool IsCollectible => GetType().HasPublicProperties(); /// /// Creates a new instance diff --git a/Telegrator/Attributes/Components/UpdateHandlerAttributeBase.cs b/Telegrator/Attributes/Components/UpdateHandlerAttributeBase.cs index ed49421..9f596c6 100644 --- a/Telegrator/Attributes/Components/UpdateHandlerAttributeBase.cs +++ b/Telegrator/Attributes/Components/UpdateHandlerAttributeBase.cs @@ -13,7 +13,7 @@ namespace Telegrator.Attributes.Components public abstract class UpdateHandlerAttributeBase : Attribute, IFilter { /// - public bool IsCollectible => this.HasPublicProperties(); + public bool IsCollectible => GetType().HasPublicProperties(); /// /// Gets an array of that this attribute can be attached to diff --git a/Telegrator/Filters/Components/AnonymousTypeFilter.cs b/Telegrator/Filters/Components/AnonymousTypeFilter.cs index 61ca05b..2dddc98 100644 --- a/Telegrator/Filters/Components/AnonymousTypeFilter.cs +++ b/Telegrator/Filters/Components/AnonymousTypeFilter.cs @@ -8,6 +8,8 @@ namespace Telegrator.Filters.Components /// public class AnonymousTypeFilter : Filter, INamedFilter { + private static readonly Type[] IgnoreLog = [typeof(CompiledFilter<>), typeof(AnonymousCompiledFilter), typeof(AnonymousTypeFilter)]; + private readonly Func, object, bool> FilterAction; private readonly Func GetFilterringTarget; private readonly string _name; @@ -74,7 +76,7 @@ namespace Telegrator.Filters.Components FilterExecutionContext context = updateContext.CreateChild((T)filterringTarget); if (!filter.CanPass(context)) { - if (filter is not AnonymousCompiledFilter && filter is not AnonymousTypeFilter) + if (IgnoreLog.Contains(filter.GetType().MakeGenericType())) Alligator.LogDebug("{0} filter of {1} didnt pass!", filter.GetType().Name, context.Data["handler_name"]); return false; diff --git a/Telegrator/Filters/Components/CompiledFilter.cs b/Telegrator/Filters/Components/CompiledFilter.cs index a407db8..f95969a 100644 --- a/Telegrator/Filters/Components/CompiledFilter.cs +++ b/Telegrator/Filters/Components/CompiledFilter.cs @@ -49,7 +49,7 @@ namespace Telegrator.Filters.Components if (!filter.CanPass(context)) { if (filter is not AnonymousCompiledFilter && filter is not AnonymousTypeFilter) - Alligator.LogDebug("{0} filter of {1} didnt pass! (Compiled)", filter.GetType().Name, context.Data["handler_name"]); + Alligator.LogTrace("{0} filter of {1} didnt pass! (Compiled)", filter.GetType().Name, context.Data["handler_name"]); return false; } diff --git a/Telegrator/Filters/Components/CompletedFiltersList.cs b/Telegrator/Filters/Components/CompletedFiltersList.cs index 343188f..64f904e 100644 --- a/Telegrator/Filters/Components/CompletedFiltersList.cs +++ b/Telegrator/Filters/Components/CompletedFiltersList.cs @@ -47,7 +47,7 @@ namespace Telegrator.Filters.Components if (!typeof(TFilter).IsFilterType()) throw new NotFilterTypeException(typeof(TFilter)); - return CompletedFilters.WhereCast(); + return CompletedFilters.OfType(); } /// diff --git a/Telegrator/Filters/Filter.cs b/Telegrator/Filters/Filter.cs index f8802e7..56a6cbf 100644 --- a/Telegrator/Filters/Filter.cs +++ b/Telegrator/Filters/Filter.cs @@ -67,7 +67,7 @@ namespace Telegrator.Filters /// /// Gets a value indicating whether this filter is collectible. /// - public bool IsCollectible => this.HasPublicProperties(); + public bool IsCollectible => GetType().HasPublicProperties(); /// /// Determines whether the filter can pass for the given context. diff --git a/Telegrator/Handlers/AbstractHandlerContainer.cs b/Telegrator/Handlers/AbstractHandlerContainer.cs index 0803a6a..6709a3b 100644 --- a/Telegrator/Handlers/AbstractHandlerContainer.cs +++ b/Telegrator/Handlers/AbstractHandlerContainer.cs @@ -11,26 +11,62 @@ namespace Telegrator.Handlers /// Provides access to the update, client, filters, and other execution context. /// /// The type of update being handled. - public class AbstractHandlerContainer(DescribedHandlerInfo handlerInfo) : IAbstractHandlerContainer where TUpdate : class + public class AbstractHandlerContainer : IAbstractHandlerContainer where TUpdate : class { /// /// Gets the actual update object of type TUpdate. /// - public TUpdate ActualUpdate { get; } = handlerInfo.HandlingUpdate.GetActualUpdateObject(); + public TUpdate ActualUpdate { get; } /// - public Update HandlingUpdate { get; } = handlerInfo.HandlingUpdate; + public Update HandlingUpdate { get; } /// - public ITelegramBotClient Client { get; } = handlerInfo.Client; + public ITelegramBotClient Client { get; } /// - public Dictionary ExtraData { get; } = handlerInfo.ExtraData; + public Dictionary ExtraData { get; } /// - public CompletedFiltersList CompletedFilters { get; } = handlerInfo.CompletedFilters; + public CompletedFiltersList CompletedFilters { get; } /// - public IAwaitingProvider AwaitingProvider { get; } = handlerInfo.AwaitingProvider; + public IAwaitingProvider AwaitingProvider { get; } + + public AbstractHandlerContainer(DescribedHandlerInfo handlerInfo) + { + ActualUpdate = handlerInfo.HandlingUpdate.GetActualUpdateObject(); + HandlingUpdate = handlerInfo.HandlingUpdate; + Client = handlerInfo.Client; + ExtraData = handlerInfo.ExtraData; + CompletedFilters = handlerInfo.CompletedFilters; + AwaitingProvider = handlerInfo.AwaitingProvider; + } + + public AbstractHandlerContainer(TUpdate actualUpdate, Update handlingUpdate, ITelegramBotClient client, Dictionary extraData, CompletedFiltersList filters, IAwaitingProvider awaitingProvider) + { + ActualUpdate = actualUpdate; + HandlingUpdate = handlingUpdate; + Client = client; + ExtraData = extraData; + CompletedFilters = filters; + AwaitingProvider = awaitingProvider; + } + + public AbstractHandlerContainer CreateChild() where QUpdate : class + { + return new AbstractHandlerContainer( + HandlingUpdate.GetActualUpdateObject(), + HandlingUpdate, Client, ExtraData, + CompletedFilters, AwaitingProvider); + } + + public static AbstractHandlerContainer From(IAbstractHandlerContainer other) where QUpdate : class + { + return new AbstractHandlerContainer( + other.HandlingUpdate.GetActualUpdateObject(), + other.HandlingUpdate, other.Client, other.ExtraData, + other.CompletedFilters, other.AwaitingProvider); + } } } diff --git a/Telegrator/Handlers/InlineQueryHandler.cs b/Telegrator/Handlers/InlineQueryHandler.cs new file mode 100644 index 0000000..62038b1 --- /dev/null +++ b/Telegrator/Handlers/InlineQueryHandler.cs @@ -0,0 +1,64 @@ +using Telegram.Bot.Types; +using Telegram.Bot.Types.Enums; +using Telegram.Bot.Types.InlineQueryResults; +using Telegrator.Attributes; +using Telegrator.Filters.Components; +using Telegrator.Handlers.Components; + +namespace Telegrator.Handlers +{ + public class InlineQueryHandlerAttribute(int importance = 0) : UpdateHandlerAttribute(UpdateType.InlineQuery, importance) + { + public override bool CanPass(FilterExecutionContext context) => context.Input.InlineQuery is { } | context.Input.ChosenInlineResult is { }; + } + + public abstract class InlineQueryHandler() : AbstractUpdateHandler(UpdateType.InlineQuery) + { + protected IAbstractHandlerContainer QueryContainer { get; private set; } = null!; + + protected IAbstractHandlerContainer ChosenContainer { get; private set; } = null!; + + protected InlineQuery InputQuery { get; private set; } = null!; + + protected ChosenInlineResult InputChosen { get; private set; } = null!; + + public override async Task Execute(IAbstractHandlerContainer container, CancellationToken cancellation) + { + switch (container.HandlingUpdate.Type) + { + case UpdateType.InlineQuery: + { + QueryContainer = AbstractHandlerContainer.From(container); + InputQuery = QueryContainer.ActualUpdate; + return await Requested(QueryContainer, cancellation); + } + + case UpdateType.ChosenInlineResult: + { + ChosenContainer = AbstractHandlerContainer.From(container); + InputChosen = ChosenContainer.ActualUpdate; + return await Chosen(ChosenContainer, cancellation); + } + + default: + throw new NotImplementedException(); + } + } + + public abstract Task Requested(IAbstractHandlerContainer container, CancellationToken cancellation); + + public abstract Task Chosen(IAbstractHandlerContainer container, CancellationToken cancellation); + + protected async Task Answer( + IEnumerable results, + int? cacheTime = null, + bool isPersonal = false, + string? nextOffset = null, + InlineQueryResultsButton? button = null, + CancellationToken cancellationToken = default) + => await QueryContainer.AnswerInlineQuery( + results, cacheTime, + isPersonal, nextOffset, + button, cancellationToken); + } +} diff --git a/Telegrator/Logging/Alligator.cs b/Telegrator/Logging/Alligator.cs index 8dea892..f044951 100644 --- a/Telegrator/Logging/Alligator.cs +++ b/Telegrator/Logging/Alligator.cs @@ -1,3 +1,5 @@ +using System.Security.Cryptography.X509Certificates; + namespace Telegrator.Logging { /// @@ -70,28 +72,29 @@ namespace Telegrator.Logging /// The log level. /// The message to log. /// Optional exception. - public static void Log(LogLevel level, string message, Exception? exception = null) + /// + public static void Log(LogLevel level, string message, Exception? exception = null, params object[] args) { // Fast path: if no adapters, do nothing if (_adapters.Count == 0) return; - if (level < MinimalLevel) + if (level != LogLevel.Trace & level < MinimalLevel) return; // Lock only during enumeration to prevent collection modification during iteration - lock (_lock) + foreach (var adapter in _adapters) { - foreach (var adapter in _adapters) + try { - try - { - adapter.Log(level, message, exception); - } - catch - { - _ = 0xBAD + 0xC0DE; // Ignore adapter errors to prevent logging failures - } + if (args != null) + message = string.Format(message, args); + + adapter.Log(level, message, exception); + } + catch + { + _ = 0xBAD + 0xC0DE; // Ignore adapter errors to prevent logging failures } } } @@ -112,7 +115,7 @@ namespace Telegrator.Logging /// public static void LogTrace(string message, params object[] args) { - Log(LogLevel.Trace, string.Format(message, args)); + Log(LogLevel.Trace, message, args: args); } /// @@ -131,7 +134,7 @@ namespace Telegrator.Logging /// public static void LogDebug(string message, params object[] args) { - Log(LogLevel.Debug, string.Format(message, args)); + Log(LogLevel.Debug, message, args: args); } /// @@ -150,7 +153,7 @@ namespace Telegrator.Logging /// public static void LogInformation(string message, params object[] args) { - Log(LogLevel.Information, string.Format(message, args)); + Log(LogLevel.Information, message, args: args); } /// @@ -169,7 +172,7 @@ namespace Telegrator.Logging /// public static void LogWarning(string message, params object[] args) { - Log(LogLevel.Warning, string.Format(message, args)); + Log(LogLevel.Warning, message, args: args); } /// @@ -189,7 +192,7 @@ namespace Telegrator.Logging /// public static void LogError(string message, params object[] args) { - Log(LogLevel.Error, string.Format(message, args)); + Log(LogLevel.Error, message, args: args); } /// @@ -209,7 +212,7 @@ namespace Telegrator.Logging /// public static void LogError(string message, Exception? exception = null, params object[] args) { - Log(LogLevel.Error, string.Format(message, args), exception); + Log(LogLevel.Error, message, exception, args); } } } \ No newline at end of file diff --git a/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs b/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs index ec2aacc..ff9cffe 100644 --- a/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs +++ b/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs @@ -61,7 +61,7 @@ namespace Telegrator.MadiatorCore.Descriptors if (!result) { anyErrors = true; - Alligator.LogDebug("(E) UpdateValidator filter of '{0}' for Update ({1}) didnt pass!", filterContext.Data["handler_name"], filterContext.Update.Id); + Alligator.LogTrace("(E) UpdateValidator filter of '{0}' for Update ({1}) didnt pass!", filterContext.Data["handler_name"], filterContext.Update.Id); if (!formReport) return Result.Fault(); @@ -84,7 +84,7 @@ namespace Telegrator.MadiatorCore.Descriptors if (!result) { anyErrors = true; - Alligator.LogDebug("(E) StateKeeperValidator filter of '{0}' for Update ({1}) didnt pass!", filterContext.Data["handler_name"], filterContext.Update.Id); + Alligator.LogTrace("(E) StateKeeperValidator filter of '{0}' for Update ({1}) didnt pass!", filterContext.Data["handler_name"], filterContext.Update.Id); if (!formReport) return Result.Fault(); @@ -110,7 +110,7 @@ namespace Telegrator.MadiatorCore.Descriptors if (!result) { anyErrors = true; - Alligator.LogDebug("(E) '{0}' filter of '{1}' for Update ({2}) didnt pass!", filterName, filterContext.Data["handler_name"], filterContext.Update.Id); + Alligator.LogTrace("(E) '{0}' filter of '{1}' for Update ({2}) didnt pass!", filterName, filterContext.Data["handler_name"], filterContext.Update.Id); if (!formReport) return Result.Fault(); diff --git a/Telegrator/Providers/HandlersCollection.cs b/Telegrator/Providers/HandlersCollection.cs index ff67aaf..0394c1c 100644 --- a/Telegrator/Providers/HandlersCollection.cs +++ b/Telegrator/Providers/HandlersCollection.cs @@ -76,7 +76,15 @@ namespace Telegrator.Providers _allowedTypes.Union(mightAwaits.SelectMany(attr => attr.UpdateTypes)); IntersectCommands(descriptor); - GetDescriptorList(descriptor).Add(descriptor); + HandlerDescriptorList list = GetDescriptorList(descriptor); + + if (descriptor.UpdateType == UpdateType.InlineQuery || descriptor.UpdateType == UpdateType.ChosenInlineResult) + { + if (list.Count > 0) + throw new Exception("Bot cannot have more than one InlineQuery handler"); + } + + list.Add(descriptor); return this; } @@ -123,10 +131,14 @@ namespace Telegrator.Providers /// The descriptor list for the update type. public virtual HandlerDescriptorList GetDescriptorList(HandlerDescriptor descriptor) { - if (!InnerDictionary.TryGetValue(descriptor.UpdateType, out HandlerDescriptorList? list)) + UpdateType updateType = UpdateTypeExtensions.SuppressTypes.TryGetValue(descriptor.UpdateType, out UpdateType suppressType) + ? suppressType + : descriptor.UpdateType; + + if (!InnerDictionary.TryGetValue(updateType, out HandlerDescriptorList? list)) { - list = new HandlerDescriptorList(descriptor.UpdateType, Options); - InnerDictionary.Add(descriptor.UpdateType, list); + list = new HandlerDescriptorList(updateType, Options); + InnerDictionary.Add(updateType, list); } return list; diff --git a/Telegrator/Providers/HandlersProvider.cs b/Telegrator/Providers/HandlersProvider.cs index b6f716e..56c4b00 100644 --- a/Telegrator/Providers/HandlersProvider.cs +++ b/Telegrator/Providers/HandlersProvider.cs @@ -105,6 +105,9 @@ namespace Telegrator.Providers /// public virtual bool TryGetDescriptorList(UpdateType updateType, out HandlerDescriptorList? list) { + if (UpdateTypeExtensions.SuppressTypes.TryGetValue(updateType, out UpdateType suppressType)) + updateType = suppressType; + return HandlersDictionary.TryGetValue(updateType, out list); } diff --git a/Telegrator/TypesExtensions.cs b/Telegrator/TypesExtensions.cs index 716af16..b577f7c 100644 --- a/Telegrator/TypesExtensions.cs +++ b/Telegrator/TypesExtensions.cs @@ -1,9 +1,9 @@ -using System.Collections; -using System.Collections.ObjectModel; +using System.Collections.ObjectModel; using System.Reflection; using Telegram.Bot; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; +using Telegram.Bot.Types.InlineQueryResults; using Telegram.Bot.Types.Payments; using Telegram.Bot.Types.ReplyMarkups; using Telegrator.Annotations; @@ -150,6 +150,26 @@ namespace Telegrator /// public static class AbstractHandlerContainerExtensions { + public static async Task React( + this IAbstractHandlerContainer container, + IEnumerable reactions, + bool isBig = false, + CancellationToken cancellationToken = default) + => await container.Client.SetMessageReaction( + container.ActualUpdate.Chat, + container.ActualUpdate.Id, + reactions, isBig, cancellationToken); + + public static async Task React( + this IAbstractHandlerContainer container, + bool isBig = false, + CancellationToken cancellationToken = default, + params IEnumerable reactions) + => await container.Client.SetMessageReaction( + container.ActualUpdate.Chat, + container.ActualUpdate.Id, + reactions, isBig, cancellationToken); + /// /// Sends a reply message to the current message. /// @@ -344,6 +364,19 @@ namespace Telegrator url: url, cacheTime: cacheTime, cancellationToken: cancellationToken); + + public static async Task AnswerInlineQuery( + this IAbstractHandlerContainer container, + IEnumerable results, + int? cacheTime = null, + bool isPersonal = false, + string? nextOffset = null, + InlineQueryResultsButton? button = null, + CancellationToken cancellationToken = default) + { + string id = container.ActualUpdate.Id; + await container.Client.AnswerInlineQuery(id, results.Take(50), cacheTime, isPersonal, nextOffset, button, cancellationToken); + } } /// @@ -806,6 +839,7 @@ namespace Telegrator return source; } + /* Found built in method :_( /// /// Creates a new with the elements of the that were successfully cast to the /// @@ -820,6 +854,7 @@ namespace Telegrator yield return result; } } + */ /// /// Sets the value of a key in a dictionary, or if the key does not exist, adds it @@ -1000,12 +1035,12 @@ namespace Telegrator */ /// - /// Checks is has public properties + /// Checks is has public properties /// - /// + /// /// - public static bool HasPublicProperties(this object obj) - => obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(prop => prop.Name != "IsCollectible").Any(); + public static bool HasPublicProperties(this Type type) + => type.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(prop => prop.Name != "IsCollectible").Any(); /// /// Determines whether an instance of a specified type can be assigned to an instance of the current type @@ -1181,6 +1216,9 @@ namespace Telegrator /// public static T GetActualUpdateObject(this Update update) { + if (update is T upd) + return upd; + object actualUpdate = update.GetActualUpdateObject() ?? throw new Exception(); if (actualUpdate is not T actualCasted) throw new Exception(); @@ -1207,6 +1245,14 @@ namespace Telegrator UpdateType.EditedChannelPost ]; + /// + /// Dictionary of s that suppresses to generic type for handling types that has complex multi-type handlers + /// + public static readonly Dictionary SuppressTypes = new Dictionary() + { + { UpdateType.ChosenInlineResult, UpdateType.InlineQuery } + }; + /// /// Checks if matches one of the 's give on ///