Доработка работы с несколькими адаптерами

This commit is contained in:
2026-02-06 07:45:19 +03:00
parent cd280369bc
commit 5dc071c750
10 changed files with 79 additions and 165 deletions

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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();
}