using File_Folder_Helper.Models; using Microsoft.Extensions.Logging; #if ShellProgressBar using ShellProgressBar; #endif using System.Collections.ObjectModel; using System.Diagnostics; using System.Text.Json; namespace File_Folder_Helper.ADO2024.PI4; internal static partial class Helper20241224 { private static readonly HttpClient _HttpClient = new(); private record Record(Uri URI, string Path, DateTime LastModified); private static ReadOnlyCollection? GetRecursiveCollection(string host, string page) { List? results; Uri uri = new($"https://{host}/{page}"); string format = NginxFileSystem.GetFormat(); TimeZoneInfo timeZoneInfo = TimeZoneInfo.Local; Task taskHttpResponseMessage = _HttpClient.GetAsync(uri); taskHttpResponseMessage.Wait(); if (!taskHttpResponseMessage.Result.IsSuccessStatusCode) results = null; else { Task taskString = taskHttpResponseMessage.Result.Content.ReadAsStringAsync(); taskString.Wait(); NginxFileSystem[]? nginxFileSystems = JsonSerializer.Deserialize(taskString.Result, NginxFileSystemCollectionSourceGenerationContext.Default.NginxFileSystemArray); if (nginxFileSystems is null) results = null; else { results = []; NginxFileSystem nginxFileSystem; ReadOnlyCollection? directory; for (int i = 0; i < nginxFileSystems.Length; i++) { nginxFileSystem = NginxFileSystem.Get(format, timeZoneInfo, uri, nginxFileSystems[i]); if (nginxFileSystem.Type == "file") results.Add(nginxFileSystem); else { directory = GetRecursiveCollection(host, $"{page}/{nginxFileSystem.Name}"); if (directory is null) continue; results.AddRange(directory); } } } } return results?.AsReadOnly(); } private static ReadOnlyCollection? GetCollection(string format, TimeZoneInfo timeZoneInfo, Uri uri) { List? results; Task taskHttpResponseMessage = _HttpClient.GetAsync(uri); taskHttpResponseMessage.Wait(); if (!taskHttpResponseMessage.Result.IsSuccessStatusCode) results = null; else { Task taskString = taskHttpResponseMessage.Result.Content.ReadAsStringAsync(); taskString.Wait(); if (taskString.Result.StartsWith('<')) results = null; else { NginxFileSystem[]? nginxFileSystems = JsonSerializer.Deserialize(taskString.Result, NginxFileSystemCollectionSourceGenerationContext.Default.NginxFileSystemArray); if (nginxFileSystems is null) results = null; else { results = []; NginxFileSystem nginxFileSystem; for (int i = 0; i < nginxFileSystems.Length; i++) { nginxFileSystem = NginxFileSystem.Get(format, timeZoneInfo, uri, nginxFileSystems[i]); results.Add(nginxFileSystem); } } } } return results?.AsReadOnly(); } private static Record? CompareFile(string host, ReadOnlyCollection directoryNames, string compareDirectory, NginxFileSystem nginxFileSystem) { Record? result; if (nginxFileSystem.LastModified is null || nginxFileSystem.Length is null) result = null; else { Uri uri = new($"https://{host}/{string.Join('/', directoryNames)}/{nginxFileSystem.Name}"); FileInfo fileInfo = new($"{compareDirectory}\\{string.Join('\\', directoryNames)}\\{nginxFileSystem.Name}"); if (!fileInfo.Exists || fileInfo.Length != nginxFileSystem.Length.Value) result = new(uri, fileInfo.FullName, nginxFileSystem.LastModified.Value); else { double totalSeconds = new TimeSpan(fileInfo.LastWriteTime.Ticks - nginxFileSystem.LastModified.Value.Ticks).TotalSeconds; if (totalSeconds is < 2 and > -2) result = null; else result = new(uri, fileInfo.FullName, nginxFileSystem.LastModified.Value); } } return result; } private static ReadOnlyCollection CompareDirectory(string format, TimeZoneInfo timeZoneInfo, string host, ReadOnlyCollection directoryNames, string compareDirectory, NginxFileSystem nginxFileSystem) { ReadOnlyCollection results; List collection = directoryNames.ToList(); collection.Add(nginxFileSystem.Name); results = GetRecord(format, timeZoneInfo, host, collection.AsReadOnly(), compareDirectory); return results; } private static ReadOnlyCollection GetRecord(string format, TimeZoneInfo timeZoneInfo, string host, ReadOnlyCollection directoryNames, string compareDirectory) { List results = []; Uri uri = new($"https://{host}/{string.Join('/', directoryNames)}"); ReadOnlyCollection? nginxFileSystems = GetCollection(format, timeZoneInfo, uri); if (nginxFileSystems is not null) { NginxFileSystem nginxFileSystem; ReadOnlyCollection records; string checkDirectory = $"{compareDirectory}\\{string.Join('\\', directoryNames)}"; if (!Directory.Exists(checkDirectory)) _ = Directory.CreateDirectory(checkDirectory); for (int i = 0; i < nginxFileSystems.Count; i++) { nginxFileSystem = NginxFileSystem.Get(format, timeZoneInfo, uri, nginxFileSystems[i]); if (nginxFileSystem.Type == "file") { Record? record = CompareFile(host, directoryNames, compareDirectory, nginxFileSystem); if (record is not null) results.Add(record); } else { records = CompareDirectory(format, timeZoneInfo, host, directoryNames, compareDirectory, nginxFileSystem); foreach (Record record in records) results.Add(record); } } } return results.AsReadOnly(); } private static void Download(Record record) { Task taskHttpResponseMessage = _HttpClient.GetAsync(record.URI); taskHttpResponseMessage.Wait(); if (taskHttpResponseMessage.Result.IsSuccessStatusCode) { Task taskString = taskHttpResponseMessage.Result.Content.ReadAsStringAsync(); taskString.Wait(); File.WriteAllText(record.Path, taskString.Result); File.SetLastWriteTime(record.Path, record.LastModified); } } internal static void Compare(ILogger logger, List args) { string host = args[2]; string rootDirectoryName = args[3]; string format = NginxFileSystem.GetFormat(); TimeZoneInfo timeZoneInfo = TimeZoneInfo.Local; string compareDirectory = Path.GetFullPath(args[0]); logger.LogInformation("Comparing files on {host}", host); ReadOnlyCollection records = GetRecord(format, timeZoneInfo, host, new([rootDirectoryName]), compareDirectory); #if ShellProgressBar ProgressBar progressBar = new(records.Count, "Downloading", new ProgressBarOptions() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }); #endif foreach (Record record in records) { #if ShellProgressBar progressBar.Tick(); #endif Download(record); } #if ShellProgressBar progressBar.Dispose(); #endif if (Debugger.IsAttached) { ReadOnlyCollection? recursiveCollection = GetRecursiveCollection(host, rootDirectoryName); string? json = recursiveCollection is null ? null : JsonSerializer.Serialize(recursiveCollection.ToArray(), NginxFileSystemCollectionSourceGenerationContext.Default.NginxFileSystemArray); if (!string.IsNullOrEmpty(json)) File.WriteAllText(Path.Combine(Environment.CurrentDirectory, ".vscode", "helper", ".json"), json); } } }