Переработанная версия ядра
All checks were successful
CI / build-test (push) Successful in 42s

This commit is contained in:
2025-12-05 12:57:05 +03:00
parent ee175a35a0
commit d817417a69
81 changed files with 2335 additions and 1453 deletions

View File

@@ -1,46 +1,157 @@
using BotPages.Core;
using BotPages.Core.Abstractions;
using BotPages.Core.Context;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Types;
namespace BotPages.Telegram
namespace BotPages.Telegram;
/// <summary>
/// Утилита для маппинга Telegram Update → UpdateContext.
/// </summary>
public static class TelegramUpdateMapper
{
/// <summary>
/// Утилиты для извлечения контекста из Telegram Update.
/// Маппинг Telegram Update в UpdateContext BotPages.
/// </summary>
public static class TelegramUpdateMapper
public static UpdateContext Map(Update update, TelegramBotClient client)
{
/// <summary>
/// Преобразует Telegram Update в универсальный UpdateContext.
/// </summary>
public static UpdateContext Map(ITelegramBotClient bot, INavigationService nav, IStateStore store, Update update)
var chat = update.Message?.Chat ?? update.CallbackQuery?.Message?.Chat;
var user = update.Message?.From ?? update.CallbackQuery?.From;
var userContext = new UserContext
{
var chat = update.Message?.Chat ?? update.CallbackQuery?.Message?.Chat;
var user = update.Message?.From ?? update.CallbackQuery?.From;
Id = user?.Id.ToString() ?? "unknown",
DisplayName = user?.Username,
};
var text = update.Message?.Text ?? update.CallbackQuery?.Data;
var files = new List<FileDescriptor>();
if (update.Message?.Document is { } doc)
var chatContext = new ChatContext
{
Id = chat?.Id.ToString() ?? "unknown",
Title = chat?.Title,
Capabilities = new Capabilities
{
files.Add(new FileDescriptor(doc.FileId, doc.FileName ?? "file", doc.MimeType ?? "application/octet-stream"));
SupportsInlineButtons = true,
SupportsReplyButtons = true,
SupportsAlbums = true,
SupportsFormattingMarkdown = true,
SupportsFormattingHtml = true,
MaxMessageLength = 4096,
}
if (update.Message?.Photo is { } photos && photos.Count() > 0)
};
string? text = null;
UpdateKind kind = UpdateKind.None;
var files = new List<FileDescriptor>();
if (update.Message is { } msg)
{
if (msg.Text is not null)
{
var largest = photos.OrderBy(p => p.FileSize).Last();
files.Add(new FileDescriptor(largest.FileId, "photo.jpg", "image/jpeg"));
text = msg.Text;
kind |= UpdateKind.Text;
}
return new UpdateContext
if (msg.Photo is { Length: > 0 })
{
Client = new TelegramClientAdapter(bot),
Chat = new ChatContext { Id = chat!.Id, Title = chat.Title },
User = new UserContext { Id = user!.Id, DisplayName = $"{user.FirstName} {user.LastName}" },
Text = text,
IncomingFiles = files,
RawUpdate = update,
Nav = nav,
State = store
};
foreach (var p in msg.Photo)
{
files.Add(new FileDescriptor
{
Id = p.FileId,
Name = "photo",
Extension = "jpg",
Size = p.FileSize ?? 0,
Kind = FileKind.Photo,
GetStreamAsync = GetStreamAsync(client, p.FileId),
});
}
}
if (msg.Document is not null)
{
files.Add(new FileDescriptor
{
Id = msg.Document.FileId,
Name = msg.Document.FileName ?? "document",
Extension = System.IO.Path.GetExtension(msg.Document.FileName) ?? "bin",
Size = msg.Document.FileSize ?? 0,
Kind = FileKind.Document,
Mime = msg.Document.MimeType,
GetStreamAsync = GetStreamAsync(client, msg.Document.FileId),
});
}
if (msg.Audio is not null)
{
files.Add(new FileDescriptor
{
Id = msg.Audio.FileId,
Name = msg.Audio.FileName ?? "audio",
Extension = System.IO.Path.GetExtension(msg.Audio.FileName) ?? "mp3",
Size = msg.Audio.FileSize ?? 0,
Kind = FileKind.Audio,
Mime = msg.Audio.MimeType,
GetStreamAsync = GetStreamAsync(client, msg.Audio.FileId),
});
}
if (msg.Video is not null)
{
files.Add(new FileDescriptor
{
Id = msg.Video.FileId,
Name = "video",
Extension = "mp4",
Size = msg.Video.FileSize ?? 0,
Kind = FileKind.Video,
Mime = msg.Video.MimeType,
GetStreamAsync = GetStreamAsync(client, msg.Video.FileId),
});
}
if (files.Count > 0)
{
kind |= UpdateKind.File;
}
}
if (update.CallbackQuery is { } cb)
{
kind |= UpdateKind.Button;
text = cb.Data;
}
return new UpdateContext
{
MessengerType = "Telegram",
User = userContext,
Chat = chatContext,
Text = text,
Kind = kind,
Files = files
};
}
private static Func<CancellationToken, Task<Stream>> GetStreamAsync(TelegramBotClient client, string fileId)
{
Func<CancellationToken, Task<Stream>> getStreamAsync = async _ =>
{
var file = await client.GetFile(fileId);
var stream = new MemoryStream();
await client.DownloadFile(file, stream);
stream.Position = 0;
return stream;
};
return getStreamAsync;
}
}