* Added new handler type "InlineQueryHandler"

* Acts as complex multi-type handler that supports InlineQuery AND ChosenInlineQuery updates
* Added "UpdateTypeExtensions.SuppressTypes" to suppress some of update types for multi-type handlers
* Logging adjustments
* Changed extension method "HasPublicProperties" to extned Type
This commit is contained in:
2025-08-12 00:09:45 +04:00
parent a1af9bdc3e
commit 3b7908756d
16 changed files with 227 additions and 54 deletions
@@ -11,26 +11,62 @@ namespace Telegrator.Handlers
/// Provides access to the update, client, filters, and other execution context.
/// </summary>
/// <typeparam name="TUpdate">The type of update being handled.</typeparam>
public class AbstractHandlerContainer<TUpdate>(DescribedHandlerInfo handlerInfo) : IAbstractHandlerContainer<TUpdate> where TUpdate : class
public class AbstractHandlerContainer<TUpdate> : IAbstractHandlerContainer<TUpdate> where TUpdate : class
{
/// <summary>
/// Gets the actual update object of type TUpdate.
/// </summary>
public TUpdate ActualUpdate { get; } = handlerInfo.HandlingUpdate.GetActualUpdateObject<TUpdate>();
public TUpdate ActualUpdate { get; }
/// <inheritdoc/>
public Update HandlingUpdate { get; } = handlerInfo.HandlingUpdate;
public Update HandlingUpdate { get; }
/// <inheritdoc/>
public ITelegramBotClient Client { get; } = handlerInfo.Client;
public ITelegramBotClient Client { get; }
/// <inheritdoc/>
public Dictionary<string, object> ExtraData { get; } = handlerInfo.ExtraData;
public Dictionary<string, object> ExtraData { get; }
/// <inheritdoc/>
public CompletedFiltersList CompletedFilters { get; } = handlerInfo.CompletedFilters;
public CompletedFiltersList CompletedFilters { get; }
/// <inheritdoc/>
public IAwaitingProvider AwaitingProvider { get; } = handlerInfo.AwaitingProvider;
public IAwaitingProvider AwaitingProvider { get; }
public AbstractHandlerContainer(DescribedHandlerInfo handlerInfo)
{
ActualUpdate = handlerInfo.HandlingUpdate.GetActualUpdateObject<TUpdate>();
HandlingUpdate = handlerInfo.HandlingUpdate;
Client = handlerInfo.Client;
ExtraData = handlerInfo.ExtraData;
CompletedFilters = handlerInfo.CompletedFilters;
AwaitingProvider = handlerInfo.AwaitingProvider;
}
public AbstractHandlerContainer(TUpdate actualUpdate, Update handlingUpdate, ITelegramBotClient client, Dictionary<string, object> extraData, CompletedFiltersList filters, IAwaitingProvider awaitingProvider)
{
ActualUpdate = actualUpdate;
HandlingUpdate = handlingUpdate;
Client = client;
ExtraData = extraData;
CompletedFilters = filters;
AwaitingProvider = awaitingProvider;
}
public AbstractHandlerContainer<QUpdate> CreateChild<QUpdate>() where QUpdate : class
{
return new AbstractHandlerContainer<QUpdate>(
HandlingUpdate.GetActualUpdateObject<QUpdate>(),
HandlingUpdate, Client, ExtraData,
CompletedFilters, AwaitingProvider);
}
public static AbstractHandlerContainer<TUpdate> From<QUpdate>(IAbstractHandlerContainer<QUpdate> other) where QUpdate : class
{
return new AbstractHandlerContainer<TUpdate>(
other.HandlingUpdate.GetActualUpdateObject<TUpdate>(),
other.HandlingUpdate, other.Client, other.ExtraData,
other.CompletedFilters, other.AwaitingProvider);
}
}
}
+64
View File
@@ -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<InlineQueryHandler>(UpdateType.InlineQuery, importance)
{
public override bool CanPass(FilterExecutionContext<Update> context) => context.Input.InlineQuery is { } | context.Input.ChosenInlineResult is { };
}
public abstract class InlineQueryHandler() : AbstractUpdateHandler<Update>(UpdateType.InlineQuery)
{
protected IAbstractHandlerContainer<InlineQuery> QueryContainer { get; private set; } = null!;
protected IAbstractHandlerContainer<ChosenInlineResult> ChosenContainer { get; private set; } = null!;
protected InlineQuery InputQuery { get; private set; } = null!;
protected ChosenInlineResult InputChosen { get; private set; } = null!;
public override async Task<Result> Execute(IAbstractHandlerContainer<Update> container, CancellationToken cancellation)
{
switch (container.HandlingUpdate.Type)
{
case UpdateType.InlineQuery:
{
QueryContainer = AbstractHandlerContainer<InlineQuery>.From(container);
InputQuery = QueryContainer.ActualUpdate;
return await Requested(QueryContainer, cancellation);
}
case UpdateType.ChosenInlineResult:
{
ChosenContainer = AbstractHandlerContainer<ChosenInlineResult>.From(container);
InputChosen = ChosenContainer.ActualUpdate;
return await Chosen(ChosenContainer, cancellation);
}
default:
throw new NotImplementedException();
}
}
public abstract Task<Result> Requested(IAbstractHandlerContainer<InlineQuery> container, CancellationToken cancellation);
public abstract Task<Result> Chosen(IAbstractHandlerContainer<ChosenInlineResult> container, CancellationToken cancellation);
protected async Task Answer(
IEnumerable<InlineQueryResult> 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);
}
}