This commit is contained in:
105
BotPages.Telegram/TelegramAlbumBuilder.cs
Normal file
105
BotPages.Telegram/TelegramAlbumBuilder.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using BotPages.Core;
|
||||
using BotPages.Core.Abstractions;
|
||||
using BotPages.Core.Logging;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
|
||||
namespace BotPages.Telegram;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Внутренний билдер альбомов (медиагрупп) для Telegram.
|
||||
/// </summary>
|
||||
public sealed class TelegramAlbumBuilder : IAlbumBuilder
|
||||
{
|
||||
private readonly TelegramAdapter _adapter;
|
||||
private readonly PageContext _ctx;
|
||||
private readonly ILogger _logger;
|
||||
private readonly TelegramBotClient? _client;
|
||||
private readonly List<(FileDescriptor file, string? caption)> _items = new();
|
||||
|
||||
/// <summary>Создать билдер альбома.</summary>
|
||||
public TelegramAlbumBuilder(TelegramAdapter adapter, PageContext ctx, ILogger logger, TelegramBotClient? client)
|
||||
{
|
||||
_adapter = adapter;
|
||||
_ctx = ctx;
|
||||
_logger = logger;
|
||||
_client = client;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IAlbumBuilder Add(FileDescriptor file, string? caption = null)
|
||||
{
|
||||
_items.Add((file, caption));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(CancellationToken ct = default)
|
||||
{
|
||||
if (_client is null)
|
||||
{
|
||||
_logger.Log(LogLevel.Critical, "Telegram client is not initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
var chatId = long.Parse(_ctx.Update.Chat.Id);
|
||||
|
||||
if (!_ctx.Update.Chat.Capabilities.SupportsAlbums)
|
||||
{
|
||||
_logger.Log(LogLevel.Warn, "Albums not supported. Degraded to sequential sends.");
|
||||
foreach (var (file, caption) in _items)
|
||||
await _adapter.SendFileAsync(_ctx, file, caption, ct);
|
||||
return;
|
||||
}
|
||||
|
||||
var media = new List<IAlbumInputMedia>();
|
||||
foreach (var (file, caption) in _items)
|
||||
{
|
||||
Stream? stream = null;
|
||||
if (file.GetStreamAsync is not null)
|
||||
{
|
||||
stream = await file.GetStreamAsync(ct);
|
||||
}
|
||||
|
||||
InputFile inputFile;
|
||||
|
||||
if (stream is not null && stream != Stream.Null)
|
||||
{
|
||||
inputFile = new InputFileStream(stream, file.Name);
|
||||
}
|
||||
else if (file.Id.StartsWith("http://") || file.Id.StartsWith("https://"))
|
||||
{
|
||||
inputFile = new InputFileUrl(file.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
inputFile = new InputFileId(file.Id);
|
||||
}
|
||||
|
||||
IAlbumInputMedia? m = file.Kind switch
|
||||
{
|
||||
FileKind.Audio => new InputMediaAudio(inputFile) { Caption = caption ?? "" },
|
||||
FileKind.Document => new InputMediaDocument(inputFile) { Caption = caption ?? "" },
|
||||
FileKind.Photo => new InputMediaPhoto(inputFile) { Caption = caption ?? "" },
|
||||
FileKind.Video => new InputMediaVideo(inputFile) { Caption = caption ?? "" },
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (m is not null) media.Add(m);
|
||||
else
|
||||
{
|
||||
// Telegram не поддерживает document в альбомах — деградация
|
||||
_logger.Log(LogLevel.Warn, $"Document '{file.Kind}' in album not supported. Sending document separately.");
|
||||
await _adapter.SendFileAsync(_ctx, file, caption, ct);
|
||||
}
|
||||
}
|
||||
|
||||
if (media.Count > 0)
|
||||
await _client.SendMediaGroup(chatId, media, cancellationToken: ct);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user