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; /// /// Утилита для маппинга Telegram Update → UpdateContext. /// public static class TelegramUpdateMapper { /// /// Маппинг Telegram Update в UpdateContext BotPages. /// public static UpdateContext? Map(TelegramAdapter adapter, Update update, TelegramBotClient client) { var chat = update.Message?.Chat ?? update.CallbackQuery?.Message?.Chat ?? update.EditedMessage?.Chat; var user = update.Message?.From ?? update.CallbackQuery?.From ?? update.EditedMessage?.From; if (chat == null || user == null) return null; var userContext = new UserContext { Id = user.Id.ToString(), DisplayName = user.Username, }; var chatContext = new ChatContext { Id = chat.Id.ToString(), Title = chat.Title, }; string? text = null; UpdateKind kind = UpdateKind.None; var files = new List(); string? messageId = null; string? replyToMessageId = null; EditInfo? editInfo = null; DeleteInfo? deleteInfo = null; PinInfo? pinInfo = null; // Обработка разных типов обновлений if (update.Message is { } msg) { messageId = msg.MessageId.ToString(); if (msg.ReplyToMessage != null) { kind |= UpdateKind.Reply; replyToMessageId = msg.ReplyToMessage.MessageId.ToString(); } if (msg.PinnedMessage != null) { kind |= UpdateKind.Pin; pinInfo = new PinInfo { MessageId = msg.PinnedMessage.MessageId.ToString(), PinDate = msg.Date, NotificationDisabled = false // Telegram не передает эту информацию }; } if (msg.Text is not null) { text = msg.Text; kind |= UpdateKind.Text; } if (msg.Photo is { Length: > 0 }) { 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; } } else if (update.EditedMessage is { } editedMsg) { messageId = editedMsg.MessageId.ToString(); kind |= UpdateKind.Edit; text = editedMsg.Text; editInfo = new EditInfo { NewText = editedMsg.Text, EditDate = editedMsg.EditDate ?? DateTime.UtcNow }; } else if (update.CallbackQuery is { } cb) { messageId = cb.Message?.MessageId.ToString(); kind |= UpdateKind.Button; text = cb.Data; } else if (update.ChannelPost is { } channelPost) { messageId = channelPost.MessageId.ToString(); if (channelPost.Text is not null) { text = channelPost.Text; kind |= UpdateKind.Text; } } else if (update.EditedChannelPost is { } editedChannelPost) { messageId = editedChannelPost.MessageId.ToString(); kind |= UpdateKind.Edit; text = editedChannelPost.Text; editInfo = new EditInfo { NewText = editedChannelPost.Text, EditDate = editedChannelPost.EditDate ?? DateTime.UtcNow }; } return new UpdateContext { AdapterId = adapter.AdapterId, AdapterType = adapter.AdapterType, User = userContext, Chat = chatContext, Text = text, Kind = kind, MessageId = messageId, ReplyToMessageId = replyToMessageId, Files = files, EditInfo = editInfo, DeleteInfo = deleteInfo, PinInfo = pinInfo }; } private static Func> GetStreamAsync(TelegramBotClient client, string fileId) { Func> getStreamAsync = async _ => { var file = await client.GetFile(fileId); var stream = new MemoryStream(); await client.DownloadFile(file, stream); stream.Position = 0; return stream; }; return getStreamAsync; } }