Добавлен вывод кнопок для файлов
All checks were successful
CI / build-test (push) Successful in 31s
Release / pack-and-publish (release) Successful in 31s

This commit is contained in:
2025-12-07 08:26:45 +03:00
parent db122e8aef
commit d6f54bb0e6
6 changed files with 93 additions and 33 deletions

View File

@@ -9,22 +9,33 @@ namespace BotPages.Core.Abstractions;
/// </summary> /// </summary>
public interface IMessengerAdapter public interface IMessengerAdapter
{ {
/// <summary>
/// Доступные возможности мессенджера.
/// </summary>
Capabilities Capabilities { get; } Capabilities Capabilities { get; }
/// <summary> /// <summary>
/// Отправить текстовое сообщение в чат. /// Отправить текстовое сообщение в чат.
/// </summary> /// </summary>
Task<string?> SendTextAsync(string chatId, string text, MessageFormat format, Task<string?> SendTextAsync(string chatId,
IEnumerable<IEnumerable<InlineButton>>? inline, string text,
IEnumerable<IEnumerable<ReplyButton>>? reply, MessageFormat format = MessageFormat.Plain,
string? messageId, IEnumerable<IEnumerable<InlineButton>>? inline = null,
CancellationToken ct IEnumerable<IEnumerable<ReplyButton>>? reply = null,
string? messageId = null,
CancellationToken ct = default
); );
/// <summary> /// <summary>
/// Отправить файл в чат. /// Отправить файл в чат.
/// </summary> /// </summary>
Task SendFileAsync(string chatId, FileDescriptor file, string? caption, MessageFormat? captionFormat, CancellationToken ct); Task SendFileAsync(string chatId,
FileDescriptor file,
string? caption = null,
MessageFormat? captionFormat = null,
IEnumerable<IEnumerable<InlineButton>>? inline = null,
IEnumerable<IEnumerable<ReplyButton>>? reply = null,
CancellationToken ct = default);
/// <summary> /// <summary>
/// Создать билдер альбома для отправки медиагруппы. /// Создать билдер альбома для отправки медиагруппы.

View File

@@ -11,7 +11,9 @@ public static class PageContextAdapterExtensions
/// <summary> /// <summary>
/// Отправить текстовое сообщение. /// Отправить текстовое сообщение.
/// </summary> /// </summary>
public static Task<string?> SendTextAsync(this PageContext ctx, string text, MessageFormat format = MessageFormat.Plain, public static Task<string?> SendTextAsync(this PageContext ctx,
string text,
MessageFormat format = MessageFormat.Plain,
IEnumerable<IEnumerable<InlineButton>>? inline = null, IEnumerable<IEnumerable<InlineButton>>? inline = null,
IEnumerable<IEnumerable<ReplyButton>>? reply = null, IEnumerable<IEnumerable<ReplyButton>>? reply = null,
string? messageId = null, string? messageId = null,
@@ -21,12 +23,19 @@ public static class PageContextAdapterExtensions
/// <summary> /// <summary>
/// Отправить файл. /// Отправить файл.
/// </summary> /// </summary>
public static Task SendFileAsync(this PageContext ctx, FileDescriptor file, string? caption = null, MessageFormat? captionFormat = null, CancellationToken ct = default) public static Task SendFileAsync(this PageContext ctx,
=> ctx.Adapter.SendFileAsync(ctx.Update.Chat.Id, file, caption, captionFormat, ct); FileDescriptor file,
string? caption = null,
/// <summary> MessageFormat? captionFormat = null,
/// Отправить файл. IEnumerable<IEnumerable<InlineButton>>? inline = null,
/// </summary> IEnumerable<IEnumerable<ReplyButton>>? reply = null,
public static Task SendFileAsync(this PageContext ctx, FileDescriptor file, string? caption = null, CancellationToken ct = default) CancellationToken ct = default
=> ctx.Adapter.SendFileAsync(ctx.Update.Chat.Id, file, caption, null, ct); )
=> ctx.Adapter.SendFileAsync(chatId: ctx.Update.Chat.Id,
file: file,
caption: caption,
captionFormat: captionFormat,
inline: inline,
reply: reply,
ct: ct);
} }

View File

@@ -123,19 +123,25 @@ public sealed class MessageBuilder
{ {
string? messageId = null; string? messageId = null;
List<List<ReplyButton>>? reply = null;
if (_disableReplyKeyboard) reply = new();
else if (_reply.Any()) reply = _reply;
// Текст // Текст
if (!string.IsNullOrWhiteSpace(_text)) if (!string.IsNullOrWhiteSpace(_text))
{ {
List<List<ReplyButton>>? reply = null;
if (_disableReplyKeyboard) reply = new();
else if (_reply.Any()) reply = _reply;
messageId = await _ctx.SendTextAsync(_text, _format, _inline, reply, _editMessageId, ct); messageId = await _ctx.SendTextAsync(_text, _format, _inline, reply, _editMessageId, ct);
} }
// Файлы // Файлы
foreach (var (file, caption, captionFormat) in _files) foreach (var (file, caption, captionFormat) in _files)
await _ctx.SendFileAsync(file, caption, captionFormat, ct); await _ctx.SendFileAsync(file: file
, caption: caption
, captionFormat: captionFormat
, reply: reply
, inline: _inline
, ct: ct
);
// Альбом // Альбом
if (_album.Count > 0) if (_album.Count > 0)

View File

@@ -85,11 +85,12 @@ public sealed class TelegramAdapter : IMessangerAdapterSetup
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task<string?> SendTextAsync(string chatId, string text, MessageFormat format, public async Task<string?> SendTextAsync(string chatId, string text,
IEnumerable<IEnumerable<InlineButton>>? inline, MessageFormat format = MessageFormat.Plain,
IEnumerable<IEnumerable<ReplyButton>>? reply, IEnumerable<IEnumerable<InlineButton>>? inline = null,
string? messageId, IEnumerable<IEnumerable<ReplyButton>>? reply = null,
CancellationToken ct) string? messageId = null,
CancellationToken ct = default)
{ {
if (_client is null) if (_client is null)
{ {
@@ -187,7 +188,14 @@ public sealed class TelegramAdapter : IMessangerAdapterSetup
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task SendFileAsync(string chatId, FileDescriptor file, string? caption, MessageFormat? captionFormat, CancellationToken ct) public async Task SendFileAsync(string chatId,
FileDescriptor file,
string? caption = null,
MessageFormat? captionFormat = null,
IEnumerable<IEnumerable<InlineButton>>? inline = null,
IEnumerable<IEnumerable<ReplyButton>>? reply = null,
CancellationToken ct = default
)
{ {
if (_client is null) if (_client is null)
{ {
@@ -249,20 +257,46 @@ public sealed class TelegramAdapter : IMessangerAdapterSetup
} }
} }
ReplyMarkup? markup = null;
if (inline is not null && inline.Any())
{
markup = new InlineKeyboardMarkup(
inline.Select(row => row.Select(b => new InlineKeyboardButton(b.Label, b.Value)).ToArray())
.ToArray()
);
}
else if (reply is not null)
{
if (reply.Any())
{
markup = new ReplyKeyboardMarkup(
reply.Select(row => row.Select(b => new KeyboardButton(b.Label)).ToArray()).ToArray()
)
{
ResizeKeyboard = true
};
}
else
{
markup = new ReplyKeyboardRemove();
}
}
// В зависимости от FileKind выбираем подходящий метод // В зависимости от FileKind выбираем подходящий метод
switch (file.Kind) switch (file.Kind)
{ {
case FileKind.Photo: case FileKind.Photo:
await _client.SendPhoto(long.Parse(chatId), inputFile, caption ?? "", parseMode, cancellationToken: ct); await _client.SendPhoto(long.Parse(chatId), inputFile, caption ?? "", parseMode, replyMarkup: markup, cancellationToken: ct);
break; break;
case FileKind.Video: case FileKind.Video:
await _client.SendVideo(long.Parse(chatId), inputFile, caption: caption ?? "", parseMode, cancellationToken: ct); await _client.SendVideo(long.Parse(chatId), inputFile, caption: caption ?? "", parseMode, replyMarkup: markup, cancellationToken: ct);
break; break;
case FileKind.Audio: case FileKind.Audio:
await _client.SendAudio(long.Parse(chatId), inputFile, caption ?? "", parseMode, cancellationToken: ct); await _client.SendAudio(long.Parse(chatId), inputFile, caption ?? "", parseMode, replyMarkup: markup, cancellationToken: ct);
break; break;
default: default:
await _client.SendDocument(long.Parse(chatId), inputFile, caption ?? "", parseMode, cancellationToken: ct); await _client.SendDocument(long.Parse(chatId), inputFile, caption ?? "", parseMode, replyMarkup: markup, cancellationToken: ct);
break; break;
} }
} }

View File

@@ -53,7 +53,7 @@ public sealed class TelegramAlbumBuilder : IAlbumBuilder
{ {
_logger.Log(LogLevel.Warn, "Albums not supported. Degraded to sequential sends."); _logger.Log(LogLevel.Warn, "Albums not supported. Degraded to sequential sends.");
foreach (var (file, caption, captionFormat) in _items) foreach (var (file, caption, captionFormat) in _items)
await _adapter.SendFileAsync(_ctx.Update.Chat.Id, file, caption, captionFormat, ct); await _adapter.SendFileAsync(_ctx.Update.Chat.Id, file, caption, captionFormat, ct: ct);
return; return;
} }
@@ -95,7 +95,7 @@ public sealed class TelegramAlbumBuilder : IAlbumBuilder
{ {
// Telegram не поддерживает document в альбомах — деградация // Telegram не поддерживает document в альбомах — деградация
_logger.Log(LogLevel.Warn, $"Document '{file.Kind}' in album not supported. Sending document separately."); _logger.Log(LogLevel.Warn, $"Document '{file.Kind}' in album not supported. Sending document separately.");
await _adapter.SendFileAsync(_ctx.Update.Chat.Id, file, caption, captionFormat, ct); await _adapter.SendFileAsync(_ctx.Update.Chat.Id, file, caption, captionFormat, ct: ct);
} }
} }

View File

@@ -20,7 +20,7 @@ public sealed class FilesPage : SingletonPage
{ {
foreach (var file in files) foreach (var file in files)
{ {
await ctx.SendFileAsync(file, $"Файл '{file.Name}' получен и отправлен обратно.", ct); await ctx.SendFileAsync(file, $"Файл '{file.Name}' получен и отправлен обратно.", ct: ct);
} }
//Обращение через Storage //Обращение через Storage