Files
BotPages/BotPages.Telegram/TelegramUpdateMapper.cs

212 lines
6.7 KiB
C#

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;
/// <summary>
/// Утилита для маппинга Telegram Update → UpdateContext.
/// </summary>
public static class TelegramUpdateMapper
{
/// <summary>
/// Маппинг Telegram Update в UpdateContext BotPages.
/// </summary>
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<FileDescriptor>();
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
{
Adapter = adapter,
User = userContext,
Chat = chatContext,
Text = text,
Kind = kind,
MessageId = messageId,
ReplyToMessageId = replyToMessageId,
Files = files,
EditInfo = editInfo,
DeleteInfo = deleteInfo,
PinInfo = pinInfo
};
}
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;
}
}