Импорт групповых чатом, мелкие правки, внешний вид чата, GIF тип
This commit is contained in:
@@ -117,7 +117,7 @@ public sealed class TelegramImportController : ControllerBase
|
||||
});
|
||||
}
|
||||
|
||||
public sealed record ExecuteImportRequest(Guid Token, Dictionary<string, Guid> Mapping);
|
||||
public sealed record ExecuteImportRequest(Guid Token, Dictionary<string, Guid> Mapping, string? GroupName);
|
||||
|
||||
[HttpPost("execute")]
|
||||
public async Task<IActionResult> Execute([FromBody] ExecuteImportRequest req, CancellationToken ct)
|
||||
@@ -161,7 +161,7 @@ public sealed class TelegramImportController : ControllerBase
|
||||
else
|
||||
{
|
||||
// Create a group
|
||||
var command = new CreateChatCommand("Импортированный чат", ChatType.Group, chatMembers);
|
||||
var command = new CreateChatCommand(req.GroupName ?? "Импортированный чат", ChatType.Group, chatMembers);
|
||||
var res = await _sender.Send(command, ct);
|
||||
if (res.IsFailure) return BadRequest(res.Error);
|
||||
chatId = res.Value;
|
||||
@@ -224,15 +224,25 @@ public sealed class TelegramImportController : ControllerBase
|
||||
Guid senderGuid = lastSenderGuid;
|
||||
|
||||
string content = "";
|
||||
if (textNode != null)
|
||||
var mainBodyNode = node.QuerySelector(".body");
|
||||
var isForwarded = node.QuerySelector(".forwarded") != null;
|
||||
|
||||
// To avoid grabbing text from inside the forwarded block as main text,
|
||||
// we can look for .text that is a direct child of the main .body
|
||||
// The .forwarded block has its own .text
|
||||
var contentTextNode = isForwarded
|
||||
? (node.QuerySelector(".body > .text") ?? node.QuerySelector(".text:not(.forwarded .text)"))
|
||||
: node.QuerySelector(".text");
|
||||
|
||||
if (contentTextNode != null)
|
||||
{
|
||||
var html = textNode.InnerHtml
|
||||
var html = contentTextNode.InnerHtml
|
||||
.Replace("<br>", "\n", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("<br/>", "\n", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("<br />", "\n", StringComparison.OrdinalIgnoreCase);
|
||||
var tempParser = new AngleSharp.Html.Parser.HtmlParser();
|
||||
var tempDoc = tempParser.ParseDocument("<div>" + html + "</div>");
|
||||
content = tempDoc.Body.TextContent.Trim();
|
||||
content = tempDoc.Body?.TextContent.Trim() ?? "";
|
||||
}
|
||||
|
||||
DateTime createdAt = lastCreatedAt;
|
||||
@@ -282,6 +292,7 @@ public sealed class TelegramImportController : ControllerBase
|
||||
}
|
||||
|
||||
// Parse forwards
|
||||
Guid? forwardedFromId = null;
|
||||
var forwardedNode = node.QuerySelector(".forwarded.body");
|
||||
if (forwardedNode != null)
|
||||
{
|
||||
@@ -294,6 +305,15 @@ public sealed class TelegramImportController : ControllerBase
|
||||
}
|
||||
var fwdName = fwdNameText != null ? fwdNameText.TextContent.Trim() : "Неизвестного";
|
||||
|
||||
if (req.Mapping.TryGetValue(fwdName, out var mappedFwdId) && mappedFwdId != Guid.Empty)
|
||||
{
|
||||
forwardedFromId = mappedFwdId;
|
||||
}
|
||||
else if (fwdName == "Это я" || fwdName == req.Mapping.FirstOrDefault(x => x.Value == myId).Key)
|
||||
{
|
||||
forwardedFromId = myId;
|
||||
}
|
||||
|
||||
var fwdTextNode = forwardedNode.QuerySelector(".text");
|
||||
string fwdContent = "";
|
||||
if (fwdTextNode != null)
|
||||
@@ -304,12 +324,20 @@ public sealed class TelegramImportController : ControllerBase
|
||||
.Replace("<br />", "\n", StringComparison.OrdinalIgnoreCase);
|
||||
var tempParser = new AngleSharp.Html.Parser.HtmlParser();
|
||||
var tempDoc = tempParser.ParseDocument("<div>" + fHtml + "</div>");
|
||||
fwdContent = tempDoc.Body.TextContent.Trim();
|
||||
fwdContent = tempDoc.Body?.TextContent.Trim() ?? "";
|
||||
}
|
||||
|
||||
content = string.IsNullOrEmpty(content)
|
||||
? $"[Переслано от {fwdName}]:\n{fwdContent}"
|
||||
: $"{content}\n\n[Переслано от {fwdName}]:\n{fwdContent}";
|
||||
if (forwardedFromId == null)
|
||||
{
|
||||
// We don't have this user in the app, map to generic string
|
||||
content = string.IsNullOrEmpty(content)
|
||||
? $"[Переслано от {fwdName}]:\n{fwdContent}"
|
||||
: $"{content}\n\n[Переслано от {fwdName}]:\n{fwdContent}";
|
||||
}
|
||||
else if (string.IsNullOrEmpty(content))
|
||||
{
|
||||
content = fwdContent;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse replies
|
||||
@@ -356,6 +384,15 @@ public sealed class TelegramImportController : ControllerBase
|
||||
if (firstHref != null)
|
||||
{
|
||||
messageType = GetMediaTypes(firstHref).mType;
|
||||
if (mediaNodes[0].ClassName?.Contains("animated") == true || firstHref.EndsWith(".mp4"))
|
||||
{
|
||||
// Treat telegram animated gifs as image format in app (we auto-loop mp4 images)
|
||||
// But web app specifically handles "image" and "video" and microlink crashes on mp4 video
|
||||
// Let's just keep "video" or "image". Actually, telegram exports gifs as mp4.
|
||||
// We should let our app player handle it.
|
||||
if (mediaNodes[0].ClassName?.Contains("animated") == true)
|
||||
messageType = "image";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,7 +407,7 @@ public sealed class TelegramImportController : ControllerBase
|
||||
else
|
||||
{
|
||||
string finalContent = content;
|
||||
targetMessage = Message.Import(chatId, senderGuid, finalContent, messageType, createdAt, replyToId, null);
|
||||
targetMessage = Message.Import(chatId, senderGuid, finalContent, messageType, createdAt, replyToId, forwardedFromId);
|
||||
|
||||
var idAttr = node.GetAttribute("id");
|
||||
if (!string.IsNullOrEmpty(idAttr))
|
||||
@@ -396,8 +433,10 @@ public sealed class TelegramImportController : ControllerBase
|
||||
ms.Position = 0;
|
||||
|
||||
var types = GetMediaTypes(href);
|
||||
var finalMType = types.mType;
|
||||
if (mediaNode.ClassName?.Contains("animated") == true) finalMType = "image";
|
||||
var fileId = await _fileStorage.UploadFileAsync(ms, Path.GetFileName(href), types.cType);
|
||||
targetMessage.AddMedia(types.mType, $"/api/files/{fileId}", Path.GetFileName(href), zipEntry.Length);
|
||||
targetMessage.AddMedia(finalMType, $"/api/files/{fileId}", Path.GetFileName(href), zipEntry.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user