using BotPages.Core.Abstractions; namespace BotPages.Core.Messaging; /// /// Fluent‑билдер для отправки сообщений (текст, кнопки, файлы, альбомы, прогресс). /// Поддерживает указание адаптер-специфичных опций через `WithAdapterOption`. /// public sealed class MessageBuilder { private readonly PageContext _ctx; private string? _text = null; private MessageFormat _format = MessageFormat.Plain; private readonly List> _inline = new(); private readonly List> _reply = new(); private readonly List<(FileDescriptor file, string? caption, MessageFormat? captionFormat)> _files = new(); private readonly List<(FileDescriptor file, string? caption, MessageFormat? captionFormat)> _album = new(); private bool _disableReplyKeyboard; private AdapterOptionsBag? _adapterOptions = null; private string? _chatId = null; /// Создать билдер сообщений. public MessageBuilder(PageContext ctx) => _ctx = ctx; /// /// Установить опции для конкретного адаптера. Ключ адаптера определяется адаптером (напр., "telegram"). /// public MessageBuilder WithAdapterOption(string adapterType, T options) { if (_adapterOptions is null) _adapterOptions = new AdapterOptionsBag(); _adapterOptions.Set(adapterType, options); return this; } /// ID чата куда отрпавить сообщение. public MessageBuilder ChatId(string chatId) { _chatId = chatId; return this; } /// Текст сообщения. public MessageBuilder Text(string text, MessageFormat format = MessageFormat.Plain) { _text = text; _format = format; return this; } /// Добавить inline‑кнопку. public MessageBuilder Inline(string label, string value) { _inline.Add(new() { new(label, value) }); return this; } /// Добавить inline‑кнопку. public MessageBuilder Inline(InlineButton button) { _inline.Add(new() { button }); return this; } /// Добавить inline‑кнопку. public MessageBuilder Inline(params InlineButton[] buttons) { _inline.Add(buttons.ToList()); return this; } /// Добавить строку inline‑кнопок. public MessageBuilder Inline(IEnumerable row) { _inline.Add(row.ToList()); return this; } /// Добавить строки inline‑кнопок. public MessageBuilder Inline(IEnumerable> row) { _inline.AddRange(row.Select(t => t.ToList()).ToList()); return this; } /// /// Отключение Reply клавиатуры. /// public MessageBuilder DisableReply() { _disableReplyKeyboard = true; return this; } /// Добавить reply‑кнопку. public MessageBuilder Reply(params ReplyButton[] label) { _disableReplyKeyboard = false; _reply.Add(label.ToList()); return this; } /// Добавить строку reply‑кнопок. public MessageBuilder Reply(IEnumerable row) { _disableReplyKeyboard = false; _reply.Add(row.ToList()); return this; } /// Добавить строки reply‑кнопок. public MessageBuilder Reply(IEnumerable> row) { _disableReplyKeyboard = false; _reply.AddRange(row.Select(t => t.ToList()).ToList()); return this; } /// Добавить файл для отправки. public MessageBuilder File(FileDescriptor file, string? caption = null, MessageFormat? captionFormat = null) { _files.Add((file, caption, captionFormat)); return this; } /// Добавить файл в альбом. public MessageBuilder Album(FileDescriptor file, string? caption = null, MessageFormat? captionFormat = null) { _album.Add((file, caption, captionFormat)); return this; } /// Удалить сообщение. public async Task DeleteAsync(string messageId, CancellationToken ct = default) { await _ctx.DeleteAsync(this._chatId ?? _ctx.Update.Chat.Id, messageId, ct); } /// Отправить собранное сообщение. public async Task SendAsync(CancellationToken ct = default) => await SendAsync(string.Empty, ct); /// Редактировать сообщение. public async Task SendAsync(string messageId, CancellationToken ct = default) { string? outMessageId = null; List>? reply = null; if (_disableReplyKeyboard) reply = new(); else if (_reply.Any()) reply = _reply; // Текст if (!string.IsNullOrWhiteSpace(_text)) { var req = new SendRequest { ChatId = _chatId ?? _ctx.Update.Chat.Id, Text = _text, TextFormat = _format, Inline = _inline, Reply = reply, MessageId = string.IsNullOrWhiteSpace(messageId) ? null : messageId, AdapterOptions = _adapterOptions }; outMessageId = await _ctx.SendAsync(req, ct); } // Файлы foreach (var (file, caption, captionFormat) in _files) { var req = new SendRequest { ChatId = _chatId ?? _ctx.Update.Chat.Id, File = file, Caption = caption, CaptionFormat = captionFormat, Inline = _inline, Reply = reply, AdapterOptions = _adapterOptions }; var res = await _ctx.SendAsync(req, ct); // сохранить первый возвращённый id сообщения if (outMessageId is null && res is not null) outMessageId = res; } // Альбом if (_album.Count > 0) { var builder = _ctx.Albums; foreach (var (file, caption, captionFormat) in _album) builder.Add(file, caption, captionFormat); await builder.SendAsync(ct); } _text = null; _files.Clear(); _album.Clear(); _adapterOptions = null; _chatId = null; return messageId; } }