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 string? _editMessageId = null;
private AdapterOptionsBag? _adapterOptions = 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;
}
/// Текст сообщения.
public MessageBuilder Text(string text, MessageFormat format = MessageFormat.Plain)
{
_text = text;
_format = format;
return this;
}
/// Редактировать сообщение.
public MessageBuilder EditMessage(string messagId)
{
_editMessageId = messagId;
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 SendAsync(CancellationToken ct = default)
{
string? messageId = null;
List>? reply = null;
if (_disableReplyKeyboard) reply = new();
else if (_reply.Any()) reply = _reply;
// Текст
if (!string.IsNullOrWhiteSpace(_text))
{
var req = new SendRequest
{
ChatId = _ctx.Update.Chat.Id,
Text = _text,
TextFormat = _format,
Inline = _inline,
Reply = reply,
MessageId = _editMessageId,
AdapterOptions = _adapterOptions
};
messageId = await _ctx.SendAsync(req, ct);
}
// Файлы
foreach (var (file, caption, captionFormat) in _files)
{
var req = new SendRequest
{
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 (messageId is null && res is not null) messageId = 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();
_editMessageId = null;
_adapterOptions = null;
return messageId;
}
}