diff --git a/PARR.AIHIT/AIHIT/MappingProfiles/RequestToDomain.cs b/PARR.AIHIT/AIHIT/MappingProfiles/RequestToDomain.cs new file mode 100644 index 00000000..5747325a --- /dev/null +++ b/PARR.AIHIT/AIHIT/MappingProfiles/RequestToDomain.cs @@ -0,0 +1,35 @@ +using AutoMapper; +using System.Xml; + +namespace PARR.AIHIT.MappingProfiles +{ + internal class RequestToDomain : Profile + { + public RequestToDomain() + { + CreateMap() + .ForMember(d => d.HostName, o => o.MapFrom(s => (s.Attributes!["ХОСТ"] != null) ? s.Attributes!["ХОСТ"]!.Value.Trim() : "")) + .ForMember(d => d.IP, o => o.MapFrom(s => s.Attributes!["IP_АДРЕС"]!.Value.Trim())) + .ForMember(d => d.RegionalEK, o => o.MapFrom(s => s.Attributes!["РЕГИОНАЛЬНЫЙ_ЭК"]!.Value.Trim())) + .ForMember(d => d.LinkEK, o => o.MapFrom(s => s.Attributes!["СВЯЗАННЫЙ_ЭК"]!.Value.Trim())) + .ForMember(d => d.Status, o => o.MapFrom(s => s.Attributes!["СТАТУС"]!.Value.Trim())) + .ForMember(d => d.WorkGroup, o => o.MapFrom(s => (s.Attributes!["РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК"] != null) ? s.Attributes!["РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК"]!.Value.Trim() : "")) + .ForMember(d => d.Responsible, o => o.MapFrom(s => s.Attributes!["ОТВЕТСТВЕННЫЙ_ЗА_ЭК"]!.Value.Trim())) + .ForMember(d => d.OS, o => o.MapFrom(s => (s.Attributes!["ОС"] != null) ? s.Attributes!["ОС"]!.Value.Trim() : "")) + .ForMember(d => d.DB, o => o.MapFrom(s => (s.Attributes!["СУБД"] != null) ? s.Attributes!["СУБД"]!.Value.Trim() : "")) + .ForMember(d => d.APP, o => o.MapFrom(s => (s.Attributes!["СП"] != null) ? s.Attributes!["СП"]!.Value.Trim() : "")); + + //CreateMap() + // .ForMember(d => d.HostName, o => o.MapFrom(s => s.HostName)) + // .ForMember(d => d.IP, o => o.MapFrom(s => s.IP)) + // .ForMember(d => d.RegionalEK, o => o.MapFrom(s => s.RegionalEK)) + // .ForMember(d => d.LinkEK, o => o.MapFrom(s => s.LinkEK)) + // .ForMember(d => d.Status, o => o.MapFrom(s => s.Status)) + // .ForMember(d => d.WorkGroup, o => o.MapFrom(s => s.WorkGroup)) + // .ForMember(d => d.Responsible, o => o.MapFrom(s => s.Responsible)) + // .ForMember(d => d.OS, o => o.MapFrom(s => s.OS)) + // .ForMember(d => d.DB, o => o.MapFrom(s => s.DB)) + // .ForMember(d => d.APP, o => o.MapFrom(s => s.APP)); + } + } +} diff --git a/PARR.AIHIT/AIHIT/PARR.AIHIT.csproj b/PARR.AIHIT/AIHIT/PARR.AIHIT.csproj index 046f3ed5..a745fd80 100644 --- a/PARR.AIHIT/AIHIT/PARR.AIHIT.csproj +++ b/PARR.AIHIT/AIHIT/PARR.AIHIT.csproj @@ -7,6 +7,7 @@ + diff --git a/PARR.AIHIT/AIHIT/Syncher.cs b/PARR.AIHIT/AIHIT/Syncher.cs index 865ba557..17002932 100644 --- a/PARR.AIHIT/AIHIT/Syncher.cs +++ b/PARR.AIHIT/AIHIT/Syncher.cs @@ -1,9 +1,14 @@ -using MailKit.Search; +using AutoMapper; +using MailKit.Search; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using MimeKit; using PARR.AIHIT.Settings; +using PARR.DAL.Models; using PARR.DAL.Services.Interfaces; using PARR.Mail.Services; +using System.Text; +using System.Xml; namespace PARR.AIHIT { @@ -13,10 +18,18 @@ namespace PARR.AIHIT private readonly IMailService mailService; private readonly SyncherSettings syncherSettings; private readonly IHostService hostService; + private readonly IMapper mapper; - public Syncher(ILogger logger, IMailService mailService, SyncherSettings syncherSettings, IHostService hostService) + public Syncher( + ILogger logger, + IMailService mailService, + SyncherSettings syncherSettings, + IHostService hostService, + IMapper mapper + ) { this.hostService = hostService; + this.mapper = mapper; this.logger = logger; this.mailService = mailService; this.syncherSettings = syncherSettings; @@ -30,14 +43,153 @@ namespace PARR.AIHIT { return; } - //var includeAddresses = aIHITSyncherSettings.IncludeAddresses.Any() ? aIHITSyncherSettings.IncludeAddresses.Split(",") : null; - // var filtered = messages.Where(m => includeAddresses.Any(i => m.Envelope.From.Mailboxes.First().Address == i)).ToList(); - var filtered = messages.Where(m => syncherSettings.IncludeAddressesArray.Any(i => m.Envelope.From.Mailboxes.First().Address == i)).ToList(); + var lastMessage = filtered.OrderByDescending(f => f.Date).First(); + var attachments = await mailService.GetAttachmentsAsync(lastMessage); + foreach (var attachment in attachments) + { + if (attachment is MessagePart) + { + continue; + } + else + { + var stream = new MemoryStream(); + ((MimePart)attachment).Content.DecodeTo(stream); + if (stream.Position > 0) stream.Position = 0; + + var fileName = EncodeString(((MimePart)attachment).FileName); + logger.LogInformation($" Получен файл {fileName}"); + if (fileName.Equals("Компонентный состав регионального ЭК.xml")) + { + XmlDocument doc = new XmlDocument(); + doc.Load(stream); + var vms = doc.GetElementsByTagName("Сведения"); + //var hosts = await hostService.Get().ToListAsync(); + foreach (XmlNode vm in vms) + { + var ip = vm?.Attributes?["IP_АДРЕС"]?.Value.Trim(); + if (ip == null) continue; + var regionalEK = vm!.Attributes!["РЕГИОНАЛЬНЫЙ_ЭК"]!.Value.Trim(); + var eK = vm!.Attributes!["СВЯЗАННЫЙ_ЭК"]!.Value.Trim(); + if (!eK.StartsWith("ВРТ")) continue; + + var foundHost = await hostService.GetHostByIPAndRegionalEKAsync(ip, regionalEK); + var mappedHost = mapper.Map(vm); + + if (foundHost != null) + { + var isChanged = false; + if (!foundHost.RegionalEK!.Equals(mappedHost.RegionalEK)) + { + foundHost.RegionalEK = mappedHost.RegionalEK; isChanged = true; + } + else if (!foundHost.LinkEK!.Equals(mappedHost.LinkEK)) + { + foundHost.LinkEK = mappedHost.LinkEK; + isChanged = true; + } + else if (!foundHost.Status!.Equals(mappedHost.Status)) + { + foundHost.Status = mappedHost.Status; + isChanged = true; + } + else if (!foundHost.WorkGroup!.Equals(mappedHost.WorkGroup)) + { + foundHost.WorkGroup = mappedHost.WorkGroup; + isChanged = true; + } + else if (!foundHost.Responsible!.Equals(mappedHost.Responsible)) + { + foundHost.Responsible = mappedHost.Responsible; + isChanged = true; + } + else if (!foundHost.OS!.Equals(mappedHost.OS)) + { + foundHost.OS = mappedHost.OS; + isChanged = true; + } + else if (!foundHost.DB!.Equals(mappedHost.DB)) + { + foundHost.DB = mappedHost.DB; + isChanged = true; + } + else if (!foundHost.APP!.Equals(mappedHost.APP)) + { + foundHost.APP = mappedHost.APP; + isChanged = true; + } + foundHost.DateModified = DateTimeOffset.UtcNow; ; + + if (isChanged && !await hostService.CommitAsync()) + logger.LogError($"Не удалось обновить узел {mappedHost.IP} {mappedHost.RegionalEK}"); + else logger.LogInformation($"Обновлён узел {mappedHost.IP} {mappedHost.RegionalEK}"); + + } + else + { + if (!await hostService.CreateAsync(mappedHost) || !await hostService.CommitAsync()) + logger.LogError($"Не удалось создать узел {mappedHost.IP} {mappedHost.RegionalEK}"); + } + + + + + //host.DateModified = ... + //var host = new PARR.DAL.Models.Host + //{ + // HostName = "", + // IP = vm!.Attributes["IP_АДРЕС"]!.Value, + // RegionalEK = vm?.Attributes?["РЕГИОНАЛЬНЫЙ_ЭК"]?.Value, + // LinkEK = vm?.Attributes?["СВЯЗАННЫЙ_ЭК"]?.Value, + // Status = vm?.Attributes?["СТАТУС"]?.Value, + // WorkGroup = vm?.Attributes?["РАБОЧАЯ_ГР_ОТВ_ЗА_ЭК"]?.Value, + // Responsible = vm?.Attributes?["ОТВЕТСТВЕННЫЙ_ЗА_ЭК"]?.Value, + // OS = vm?.Attributes?["ОС"]?.Value, + // DB = vm?.Attributes?["СУБД"]?.Value, + // APP = vm?.Attributes?["СП"]?.Value, + + //}; + //logger.LogInformation($"Запись сервера {mappedHost.IP}, региональный ЭК {mappedHost.RegionalEK}"); + //if (String.IsNullOrEmpty(host.Status) || !host.Status.Equals("3-В эксплуатации")) continue; + //if (String.IsNullOrEmpty(host.IP)) continue; + + } + } + break; + + } + } + + //прочитано для всех foreach (var message in filtered) { - // + await mailService.SetAsSeenAsync(message); } } + + private bool IsChanged(Host host, Host mappedHost) + { + if (host == null) return true; + if (mappedHost == null) return true; + if (!host.IP.Equals(mappedHost.IP)) return true; + if (!host.RegionalEK!.Equals(mappedHost.RegionalEK)) return true; + if (!host.LinkEK!.Equals(mappedHost.LinkEK)) return true; + if (!host.Status!.Equals(mappedHost.Status)) return true; + if (!host.WorkGroup!.Equals(mappedHost.WorkGroup)) return true; + if (!host.Responsible!.Equals(mappedHost.Responsible)) return true; + if (!host.OS!.Equals(mappedHost.OS)) return true; + if (!host.DB!.Equals(mappedHost.DB)) return true; + if (!host.APP!.Equals(mappedHost.APP)) return true; + return false; + } + + private static string EncodeString(string str) + { + byte[] bStr = Encoding.GetEncoding("koi8r").GetBytes(str); + Encoding encoding = Encoding.GetEncoding("koi8r"); + str = encoding.GetString(bStr, 0, bStr.Length); + return str; + } } } \ No newline at end of file diff --git a/PARR.AIHIT/AIHIT/SyncherInstaller.cs b/PARR.AIHIT/AIHIT/SyncherInstaller.cs index 92886e04..24d8fb28 100644 --- a/PARR.AIHIT/AIHIT/SyncherInstaller.cs +++ b/PARR.AIHIT/AIHIT/SyncherInstaller.cs @@ -12,6 +12,8 @@ namespace PARR.AIHIT configuration.GetSection(nameof(SyncherSettings)).Bind(syncherSettings); services.AddSingleton(syncherSettings); + services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); + services.AddTransient(); } } diff --git a/PARR.DAL/Models/Host.cs b/PARR.DAL/Models/Host.cs index 6431f52a..9fc9bdb5 100644 --- a/PARR.DAL/Models/Host.cs +++ b/PARR.DAL/Models/Host.cs @@ -11,7 +11,7 @@ namespace PARR.DAL.Models public Guid Id { get; set; } public DateTimeOffset DateCreated { get; set; } public DateTimeOffset? DateModified { get; set; } - public required string HostName { get; set; } + public string HostName { get; set; } public required string IP { get; set; } public string? RegionalEK { get; set; } public string? LinkEK { get; set; } diff --git a/PARR.DAL/Services/Implementations/HostService.cs b/PARR.DAL/Services/Implementations/HostService.cs index 606e6015..ee06a6a5 100644 --- a/PARR.DAL/Services/Implementations/HostService.cs +++ b/PARR.DAL/Services/Implementations/HostService.cs @@ -20,5 +20,64 @@ namespace PARR.DAL.Services.Implementations this.dataContext = dataContext; this.logger = logger; } + + public async Task GetHostByIPAndRegionalEKAsync(string IP, string RegionalEK) + { + try + { + var host = await EntitySet.FirstAsync(h => h.IP == IP && h.RegionalEK == RegionalEK); + return host; + } + catch + { + logger.LogInformation($"Не найден узел с IP адресом {IP} и региональным ЭК {RegionalEK}"); + return null; + } + } + + //public async Task GetHostByRegionalEKAsync(string RegionalEK) + //{ + // try + // { + // var host = await EntitySet.FirstAsync(h => h.RegionalEK == RegionalEK); + // return host; + // } + // catch + // { + // logger.LogInformation($"Не найден узел с региональным ЭК {RegionalEK}"); + // return null; + // } + //} + + //public async Task UpdateAsync(Host host) + //{ + // var orig = await EntitySet.FirstAsync(h => h.IP == host.IP); + // if (orig == null) + // return false; + + // orig.DateModified = DateTimeOffset.UtcNow; + // orig.HostName = host.HostName; + // orig.RegionalEK = host.RegionalEK; + // orig.LinkEK = host.LinkEK; + // orig.Status = host.Status; + // orig.WorkGroup = host.WorkGroup; + // orig.Responsible = host.Responsible; + // orig.OS = host.OS; + // orig.DB = host.DB; + // orig.APP = host.APP; + + // if (!await CommitAsync()) + // { + // logger.LogError($"Ошибка обновления узла {host.IP}"); + // return false; + // } + // else + // { + // logger.LogInformation($"Обновлен узел {host.IP}"); + // return true; + // } + + //} + } } diff --git a/PARR.DAL/Services/Interfaces/IHostService.cs b/PARR.DAL/Services/Interfaces/IHostService.cs index 84013a81..e1775b8e 100644 --- a/PARR.DAL/Services/Interfaces/IHostService.cs +++ b/PARR.DAL/Services/Interfaces/IHostService.cs @@ -5,5 +5,8 @@ namespace PARR.DAL.Services.Interfaces { public interface IHostService : IBaseService { + Task GetHostByIPAndRegionalEKAsync(string IP, string RegionalEK); + //Task GetHostByRegionalEKAsync(string LinkEK); + //Task UpdateAsync(Host host); } } diff --git a/PARR.Worker/PARR.Worker/Program.cs b/PARR.Worker/PARR.Worker/Program.cs index 895c53af..67211d6d 100644 --- a/PARR.Worker/PARR.Worker/Program.cs +++ b/PARR.Worker/PARR.Worker/Program.cs @@ -1,12 +1,24 @@ +using Microsoft.Extensions.Configuration; using PARR.AIHIT; using PARR.DAL; using PARR.Mail; using PARR.Worker; +using PARR.Worker.Settings; using Serilog; +using System.Text; + +Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); IHost host = Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { + IConfiguration configuration = hostContext.Configuration; + + var workerSettings = new WorkerSettings(); + workerSettings = hostContext.Configuration.GetSection(nameof(WorkerSettings)).Get(); + services.AddSingleton(workerSettings); + + services.InstallMailServices(hostContext.Configuration); services.InstallDalServices(hostContext.Configuration); services.InstallerSyncerServices(hostContext.Configuration); diff --git a/PARR.Worker/PARR.Worker/Settings/SyncherSettings.cs b/PARR.Worker/PARR.Worker/Settings/SyncherSettings.cs deleted file mode 100644 index 12f29751..00000000 --- a/PARR.Worker/PARR.Worker/Settings/SyncherSettings.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace PARR.Worker.Settings -{ - internal class SyncherSettings - { - public int OccursEvery { get; set; } - public string? IncludeAddresses { get; set; } - - public List IncludeAddressesArray => IncludeAddresses == null ? new List() : IncludeAddresses.Split(",").ToList(); - } -} diff --git a/PARR.Worker/PARR.Worker/Settings/WorkerSettings.cs b/PARR.Worker/PARR.Worker/Settings/WorkerSettings.cs new file mode 100644 index 00000000..30645916 --- /dev/null +++ b/PARR.Worker/PARR.Worker/Settings/WorkerSettings.cs @@ -0,0 +1,7 @@ +namespace PARR.Worker.Settings +{ + public class WorkerSettings + { + public int OccursEvery { get; set; } + } +} diff --git a/PARR.Worker/PARR.Worker/Worker.cs b/PARR.Worker/PARR.Worker/Worker.cs index 69b9c6ba..f95cfb5f 100644 --- a/PARR.Worker/PARR.Worker/Worker.cs +++ b/PARR.Worker/PARR.Worker/Worker.cs @@ -1,4 +1,5 @@ using PARR.AIHIT; +using PARR.Worker.Settings; namespace PARR.Worker { @@ -6,11 +7,16 @@ namespace PARR.Worker { private readonly ILogger logger; private readonly IServiceProvider serviceProvider; + private readonly WorkerSettings workerSettings; - public Worker(ILogger logger, IServiceProvider serviceProvider) + public Worker(ILogger logger, + IServiceProvider serviceProvider, + WorkerSettings workerSettings + ) { this.logger = logger; this.serviceProvider = serviceProvider; + this.workerSettings = workerSettings; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) @@ -30,7 +36,7 @@ namespace PARR.Worker //await attachmentUploader.UploadAsync(); //logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); - await Task.Delay(60 * 1000, stoppingToken); + await Task.Delay(workerSettings.OccursEvery, stoppingToken); } } } diff --git a/PARR.Worker/PARR.Worker/appsettings.json b/PARR.Worker/PARR.Worker/appsettings.json index 607cdc52..4e6dc96d 100644 --- a/PARR.Worker/PARR.Worker/appsettings.json +++ b/PARR.Worker/PARR.Worker/appsettings.json @@ -33,9 +33,11 @@ "SSL": false, "UserName": "IVC_Robot" }, - "AIHITSyncherSettings": { - "OccursEvery": 60000, + "SyncherSettings": { "IncludeAddresses": "aihit@gvc.rzd" + }, + "WorkerSettings": { + "OccursEvery": 60000 } }