Разделение

This commit is contained in:
Халимов Рустам
2026-03-30 15:35:28 +03:00
parent 465e84e686
commit 09e5cbaa76
57 changed files with 631 additions and 233 deletions

View File

@@ -1,5 +1,3 @@
using Knot.Modules.Conversations.Domain;
using Knot.Modules.Messaging.Domain;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -8,11 +6,11 @@ using System.IO.Compression;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AngleSharp.Html.Parser;
using AngleSharp.Dom;
using Knot.Shared.Kernel;
using AngleSharp.Html.Parser;
using Knot.Contracts.Settings.Application.Abstractions;
using Knot.Contracts.Settings.Application.DTOs;
using Knot.Shared.Kernel;
using MediatR;
namespace Knot.Modules.TelegramImport.Application.TelegramImport;
@@ -25,8 +23,8 @@ public static class TelegramImportState
public record ImportConflictDto(string Type, string Message, bool Blocked);
public record AnalyzeImportResponseDto(
Guid Token,
List<string> Names,
Guid Token,
List<string> Names,
List<ImportConflictDto> Conflicts);
public record AnalyzeImportCommand(Stream FileStream, string FileName) : ICommand<AnalyzeImportResponseDto>;
@@ -43,12 +41,12 @@ internal sealed class AnalyzeImportCommandHandler : ICommandHandler<AnalyzeImpor
{
if (request.FileStream == null || request.FileStream.Length == 0)
{
return Result.Failure<AnalyzeImportResponseDto>(ChatErrors.FileEmpty);
return Result.Failure<AnalyzeImportResponseDto>(TelegramImportErrors.FileEmpty);
}
if (!request.FileName.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
{
return Result.Failure<AnalyzeImportResponseDto>(ChatErrors.FileInvalidExtension);
return Result.Failure<AnalyzeImportResponseDto>(TelegramImportErrors.FileInvalidExtension);
}
var token = Guid.NewGuid();
@@ -104,12 +102,12 @@ internal sealed class AnalyzeImportCommandHandler : ICommandHandler<AnalyzeImpor
var settings = await _settingsService.GetSettingsAsync(cancellationToken);
var conflicts = new List<ImportConflictDto>();
if (!settings.Messages.AllowMedia)
if (!settings.Messages.AllowMedia)
conflicts.Add(new ImportConflictDto("Media", "Медиафайлы (фото/видео) отключены на сервере. Они не будут импортированы.", true));
if (!settings.Messages.AllowVoiceMessages)
conflicts.Add(new ImportConflictDto("Voice", "Голосовые сообщения запрещены администратором. Будут пропущены.", true));
if (!settings.Messages.AllowPolls)
conflicts.Add(new ImportConflictDto("Polls", "Опросы не поддерживаются текущими настройками сервера.", true));

View File

@@ -0,0 +1,7 @@
namespace Knot.Modules.TelegramImport.Application.TelegramImport;
public static class TelegramImportErrors
{
public static readonly Knot.Shared.Kernel.Error FileEmpty = new("File.Empty", "No file uploaded");
public static readonly Knot.Shared.Kernel.Error FileInvalidExtension = new("File.InvalidExtension", "Only .zip files are supported");
}

View File

@@ -4,17 +4,17 @@ using System.IO.Compression;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Knot.Contracts.Conversations.Application.Abstractions;
using Knot.Contracts.Conversations.Domain;
using Knot.Contracts.Messaging.Application.Abstractions;
using Knot.Contracts.Messaging.Domain;
using Knot.Modules.TelegramImport.Application.Abstractions;
using Knot.Modules.TelegramImport.Application.TelegramImport;
using Knot.Modules.TelegramImport.Infrastructure.Background;
using Knot.Shared.Kernel.Storage;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Knot.Modules.TelegramImport.Application.Abstractions;
using Knot.Modules.TelegramImport.Application.TelegramImport;
using Knot.Modules.Messaging.Application.Abstractions;
using Knot.Modules.Conversations.Application.Abstractions;
using Knot.Modules.Messaging.Domain;
using Knot.Modules.Conversations.Domain;
using Knot.Shared.Kernel.Storage;
using Knot.Modules.TelegramImport.Infrastructure.Background;
namespace Knot.Modules.TelegramImport.Infrastructure.Background;
@@ -34,7 +34,7 @@ public class TelegramImportWorker : BackgroundService
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Telegram Import Worker started.");
// В реальном проекте здесь будет чтение из Channels или RabbitMQ
// Для примера оставим заглушку цикла
while (!stoppingToken.IsCancellationRequested)
@@ -55,33 +55,33 @@ public class TelegramImportWorker : BackgroundService
var jobInfo = new ImportJobInfo { JobId = jobId, Status = ImportJobStatus.Processing };
_jobStore.AddOrUpdate(jobInfo);
try
try
{
using var archive = ZipFile.OpenRead(zipPath);
var entries = archive.Entries.Where(e => e.Name.StartsWith("messages") && e.Name.EndsWith(".html")).ToList();
using var archive = ZipFile.OpenRead(zipPath);
var entries = archive.Entries.Where(e => e.Name.StartsWith("messages") && e.Name.EndsWith(".html")).ToList();
// 1. Создание чата (уже было в оригинале, но здесь в фоне)
Guid targetChatId = Guid.NewGuid(); // Упростим логику для демонстрации рефакторинга
// 1. Создание чата (уже было в оригинале, но здесь в фоне)
Guid targetChatId = Guid.NewGuid(); // Упростим логику для демонстрации рефакторинга
foreach (var entry in entries)
{
using var stream = entry.Open();
var messages = await parser.ParseMessagesAsync(stream, "", ct);
foreach (var m in messages)
{
Guid senderGuid = request.Mapping.TryGetValue(m.SenderName ?? "", out var sid) ? sid : request.CurrentUserId;
var textMsg = new TextMessage(Guid.NewGuid(), targetChatId, senderGuid, m.Content, null, null, null, m.CreatedAt, true);
msgRepo.Add(textMsg);
jobInfo.ProcessedMessages++;
_jobStore.AddOrUpdate(jobInfo);
}
await uow.SaveChangesAsync(ct);
}
jobInfo.Status = ImportJobStatus.Completed;
foreach (var entry in entries)
{
using var stream = entry.Open();
var messages = await parser.ParseMessagesAsync(stream, "", ct);
foreach (var m in messages)
{
Guid senderGuid = request.Mapping.TryGetValue(m.SenderName ?? "", out var sid) ? sid : request.CurrentUserId;
var textMsg = new TextMessage(Guid.NewGuid(), targetChatId, senderGuid, m.Content, null, null, null, m.CreatedAt, true);
msgRepo.Add(textMsg);
jobInfo.ProcessedMessages++;
_jobStore.AddOrUpdate(jobInfo);
}
await uow.SaveChangesAsync(ct);
}
jobInfo.Status = ImportJobStatus.Completed;
}
catch (Exception ex)
{

View File

@@ -2,9 +2,14 @@
<ItemGroup>
<ProjectReference Include="..\..\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
<ProjectReference Include="..\Conversations\Knot.Modules.Conversations.csproj" />
<ProjectReference Include="..\Messaging\Knot.Modules.Messaging.csproj" />
<ProjectReference Include="..\Settings\Knot.Modules.Settings.csproj" />
<ProjectReference Include="..\..\Contracts\Conversations\Knot.Contracts.Conversations.csproj" />
<ProjectReference Include="..\..\Contracts\Messaging\Knot.Contracts.Messaging.csproj" />
<ProjectReference Include="..\..\Contracts\Settings\Knot.Contracts.Settings.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AngleSharp" Version="1.1.2" />
<PackageReference Include="Carter" Version="10.0.0" />
</ItemGroup>
<PropertyGroup>