218 lines
6.8 KiB
C#
218 lines
6.8 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)
|
|
{
|
|
return async ct =>
|
|
{
|
|
try
|
|
{
|
|
var file = await client.GetFile(fileId, ct);
|
|
var stream = new MemoryStream();
|
|
await client.DownloadFile(file.FilePath!, stream, ct);
|
|
stream.Position = 0;
|
|
return stream;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Stream.Null;
|
|
throw;
|
|
}
|
|
};
|
|
}
|
|
} |