Доработка работы с несколькими адаптерами
This commit is contained in:
@@ -13,7 +13,7 @@ public readonly record struct CompositeSessionKey(string AdapterId, string ChatI
|
||||
public static CompositeSessionKey FromUpdate(UpdateContext update)
|
||||
{
|
||||
return new CompositeSessionKey(
|
||||
update.AdapterId,
|
||||
update.Adapter.Id,
|
||||
update.Chat.Id,
|
||||
update.User.Id);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,16 @@ namespace BotPages.Core.Abstractions;
|
||||
/// </summary>
|
||||
public interface IMessengerAdapter
|
||||
{
|
||||
/// <summary>
|
||||
/// Уникальный идентификатор адаптера.
|
||||
/// </summary>
|
||||
string Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Тип адаптера (Telegram, VK, WhatsApp и т.д.).
|
||||
/// </summary>
|
||||
string Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Доступные возможности мессенджера.
|
||||
/// </summary>
|
||||
@@ -87,10 +97,16 @@ public interface IMessengerAdapter
|
||||
/// </summary>
|
||||
public interface IMessengerAdapterSetup : IMessengerAdapter
|
||||
{
|
||||
/// <summary>
|
||||
/// Внутренний метод для установки ID адаптера.
|
||||
/// </summary>
|
||||
void SetAdapterId(string adapterId);
|
||||
|
||||
/// <summary>
|
||||
/// Запуск работы адаптера
|
||||
/// </summary>
|
||||
/// <param name="onUpdate"></param>
|
||||
/// <param name="commands"></param>
|
||||
/// <param name="ct"></param>
|
||||
/// <returns></returns>
|
||||
Task StartAdapterAsync(Func<UpdateContext, Task> onUpdate, List<Routing.Command> commands, CancellationToken ct);
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
using BotPages.Core.Context;
|
||||
using BotPages.Core.Messaging;
|
||||
|
||||
namespace BotPages.Core.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// Базовый класс для адаптеров мессенджеров.
|
||||
/// </summary>
|
||||
public abstract class MessengerAdapterBase : IMessengerAdapterSetup
|
||||
{
|
||||
/// <summary>
|
||||
/// Уникальный идентификатор адаптера.
|
||||
/// </summary>
|
||||
public string AdapterId { get; internal set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Тип адаптера (Telegram, VK, WhatsApp и т.д.).
|
||||
/// </summary>
|
||||
public abstract string AdapterType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Название адаптера для отображения.
|
||||
/// </summary>
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Доступные возможности мессенджера.
|
||||
/// </summary>
|
||||
public abstract Capabilities Capabilities { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Универсальный метод отправки с использованием общего описания запроса.
|
||||
/// </summary>
|
||||
public abstract Task<string?> SendAsync(SendRequest request, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Универсальный метод удаления сообщения.
|
||||
/// </summary>
|
||||
public abstract Task DeleteAsync(string chatId, string messageId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Удалить несколько сообщений за раз.
|
||||
/// </summary>
|
||||
public abstract Task<bool> DeleteMultipleAsync(string chatId, IEnumerable<string> messageIds, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Редактировать только текст сообщения.
|
||||
/// </summary>
|
||||
public abstract Task<string?> EditTextAsync(string chatId, string messageId, string text,
|
||||
MessageFormat? format = null, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Редактировать только клавиатуру сообщения.
|
||||
/// </summary>
|
||||
public abstract Task<string?> EditButtonsAsync(string chatId, string messageId,
|
||||
IEnumerable<IEnumerable<InlineButton>>? inlineButtons = null,
|
||||
CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Закрепить сообщение в чате.
|
||||
/// </summary>
|
||||
public abstract Task<bool> PinMessageAsync(string chatId, string messageId, bool disableNotification = false,
|
||||
CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Открепить сообщение в чате.
|
||||
/// </summary>
|
||||
public abstract Task<bool> UnpinMessageAsync(string chatId, string messageId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Получить информацию о сообщении.
|
||||
/// </summary>
|
||||
public abstract Task<MessageInfo?> GetMessageInfoAsync(string chatId, string messageId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Переслать сообщение.
|
||||
/// </summary>
|
||||
public abstract Task<string?> ForwardMessageAsync(string fromChatId, string messageId, string toChatId,
|
||||
bool disableNotification = false, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Копировать сообщение с возможностью редактирования.
|
||||
/// </summary>
|
||||
public abstract Task<string?> CopyMessageAsync(string fromChatId, string messageId, string toChatId,
|
||||
string? caption = null, MessageFormat? captionFormat = null,
|
||||
bool disableNotification = false, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Создать билдер альбома для отправки медиагруппы.
|
||||
/// </summary>
|
||||
public abstract IAlbumBuilder CreateAlbumBuilder(PageContext ctx);
|
||||
|
||||
/// <summary>
|
||||
/// Вызывается при выходе со страницы.
|
||||
/// </summary>
|
||||
public abstract Task OnLeaveAsync(PageContext ctx, CancellationToken ct);
|
||||
|
||||
/// <summary>
|
||||
/// Запуск работы адаптера.
|
||||
/// </summary>
|
||||
public abstract Task StartAdapterAsync(Func<UpdateContext, Task> onUpdate, List<Routing.Command> commands, CancellationToken ct);
|
||||
}
|
||||
@@ -26,16 +26,13 @@ public sealed class MultiAdapterFactory : IMessengerAdapterFactory
|
||||
throw new ArgumentException($"Adapter with ID '{adapterId}' is already registered", nameof(adapterId));
|
||||
|
||||
// Устанавливаем идентификатор в адаптер
|
||||
if (adapter is MessengerAdapterBase adapterBase)
|
||||
{
|
||||
adapterBase.AdapterId = adapterId;
|
||||
}
|
||||
adapter.SetAdapterId(adapterId);
|
||||
|
||||
_allAdapters.Add(adapter);
|
||||
_adaptersById[adapterId] = adapter;
|
||||
|
||||
// Группируем по типу
|
||||
var adapterType = GetAdapterType(adapter);
|
||||
var adapterType = adapter.Type;
|
||||
if (!_adaptersByType.TryGetValue(adapterType, out var typeList))
|
||||
{
|
||||
typeList = new List<IMessengerAdapterSetup>();
|
||||
@@ -106,7 +103,7 @@ public sealed class MultiAdapterFactory : IMessengerAdapterFactory
|
||||
_allAdapters.Remove(adapter);
|
||||
_adaptersById.Remove(adapterId);
|
||||
|
||||
var adapterType = GetAdapterType(adapter);
|
||||
var adapterType = adapter.Type;
|
||||
if (_adaptersByType.TryGetValue(adapterType, out var typeList))
|
||||
{
|
||||
typeList.Remove(adapter);
|
||||
@@ -122,20 +119,9 @@ public sealed class MultiAdapterFactory : IMessengerAdapterFactory
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string GetAdapterType(IMessengerAdapter adapter)
|
||||
{
|
||||
if (adapter is MessengerAdapterBase adapterBase)
|
||||
{
|
||||
return adapterBase.AdapterType;
|
||||
}
|
||||
|
||||
// Для обратной совместимости
|
||||
return adapter.GetType().Name.Replace("Adapter", "");
|
||||
}
|
||||
|
||||
private static string GenerateAdapterId(IMessengerAdapter adapter)
|
||||
{
|
||||
var adapterType = GetAdapterType(adapter);
|
||||
var adapterType = adapter.Type;
|
||||
var guid = Guid.NewGuid().ToString("N").Substring(0, 8);
|
||||
return $"{adapterType}_{guid}".ToLowerInvariant();
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ public sealed class BotPagesApp
|
||||
SessionKey = sessionKey,
|
||||
StateStorage = _state,
|
||||
Navigation = _navigation,
|
||||
Adapter = _adapterFactory.Resolve(update.AdapterId),
|
||||
Adapter = _adapterFactory.Resolve(update.Adapter.Id),
|
||||
AdapterFactory = _adapterFactory,
|
||||
};
|
||||
|
||||
|
||||
@@ -52,12 +52,12 @@ public sealed class PageContext
|
||||
/// <summary>
|
||||
/// Получить текущий тип адаптера.
|
||||
/// </summary>
|
||||
public string CurrentAdapterType => Update.AdapterType;
|
||||
public string CurrentAdapterType => Update.Adapter.Type;
|
||||
|
||||
/// <summary>
|
||||
/// Получить текущий ID адаптера.
|
||||
/// </summary>
|
||||
public string CurrentAdapterId => Update.AdapterId;
|
||||
public string CurrentAdapterId => Update.Adapter.Id;
|
||||
|
||||
/// <summary>
|
||||
/// Получить все адаптеры.
|
||||
|
||||
@@ -8,11 +8,8 @@ namespace BotPages.Core.Context;
|
||||
/// </summary>
|
||||
public sealed class UpdateContext
|
||||
{
|
||||
/// <summary>Идентификатор адаптера, от которого пришло обновление.</summary>
|
||||
public required string AdapterId { get; init; }
|
||||
|
||||
/// <summary>Тип адаптера (определяется адаптером).</summary>
|
||||
public required string AdapterType { get; init; }
|
||||
/// <summary>Адаптер, от которого пришло обновление.</summary>
|
||||
public required IMessengerAdapter Adapter { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Данные пользователя, от которого пришло обновление.
|
||||
|
||||
@@ -17,7 +17,7 @@ public sealed class LoggingMiddleware : IPageMiddleware
|
||||
public async Task InvokeAsync(PageContext ctx, Func<Task> next, CancellationToken ct)
|
||||
{
|
||||
// Логируем базовую информацию
|
||||
_logger.Log(LogLevel.Info, $"Update from {ctx.Update.AdapterId} | Chat: {ctx.Update.Chat.Id} | User: {ctx.Update.User.Id}");
|
||||
_logger.Log(LogLevel.Info, $"Update from {ctx.Update.Adapter.Id} | Chat: {ctx.Update.Chat.Id} | User: {ctx.Update.User.Id}");
|
||||
|
||||
// Логируем текст, кнопки, файлы
|
||||
if (ctx.Update.Text is not null)
|
||||
|
||||
Reference in New Issue
Block a user