using BotPages.Core.Abstractions; namespace BotPages.Core.Messaging; /// /// Fluent‑билдер для отправки сообщений (текст, кнопки, файлы, альбомы, прогресс). /// 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 string? _progressTitle = null; private int? _progressPercent = null; private string? _progressMessageId = null; private bool _disableReplyKeyboard; /// Создать билдер сообщений. public MessageBuilder(PageContext ctx) => _ctx = ctx; /// Текст сообщения. 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 MessageBuilder Progress(string title, int percent = 0) { _progressTitle = title; _progressPercent = percent; return this; } /// Отправить собранное сообщение. public async Task SendAsync(CancellationToken ct = default) { // Текст if (!string.IsNullOrWhiteSpace(_text)) { List>? reply = null; if (_disableReplyKeyboard) reply = new(); else if (_reply.Any()) reply = _reply; await _ctx.SendTextAsync(_text, _format, _inline, reply, ct); } // Файлы foreach (var (file, caption, captionFormat) in _files) await _ctx.SendFileAsync(file, caption, captionFormat, ct); // Альбом if (_album.Count > 0) { var builder = _ctx.Albums; foreach (var (file, caption, captionFormat) in _album) builder.Add(file, caption, captionFormat); await builder.SendAsync(ct); } // Прогресс if (_progressTitle is not null) { if (_progressMessageId is null) _progressMessageId = await _ctx.StartProgressAsync(_progressTitle, ct); if (_progressPercent > 0 && !string.IsNullOrEmpty(_progressMessageId)) await _ctx.UpdateProgressAsync(_progressMessageId, _progressPercent.Value, ct); } _text = null; _files.Clear(); _album.Clear(); if (_progressPercent >= 100) { _progressTitle = null; _progressMessageId = null; _progressPercent = null; } } }