using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; namespace File_Folder_Helper.ADO2024.PI1; internal static partial class Helper20240106 { private record Host([property: JsonPropertyName("a")] string? Id, [property: JsonPropertyName("b")] string? Colon, [property: JsonPropertyName("c")] string? Hyphen, [property: JsonPropertyName("d")] string? Line, [property: JsonPropertyName("e")] string? Count, [property: JsonPropertyName("f")] string? Segments, [property: JsonPropertyName("g")] string? Type, [property: JsonPropertyName("h")] string? Device, [property: JsonPropertyName("i")] string? Name, [property: JsonPropertyName("j")] string? Location); [JsonSourceGenerationOptions(WriteIndented = true, AllowTrailingCommas = true)] [JsonSerializable(typeof(Host[]))] private partial class HostCollectionSourceGenerationContext : JsonSerializerContext { } [JsonSourceGenerationOptions(WriteIndented = true)] [JsonSerializable(typeof(Dictionary>))] private partial class DictionaryDictionarySourceGenerationContext : JsonSerializerContext { } private record Record(string Key, Dictionary KeyValuePairs); private static Dictionary> GetKeyValuePairs(List collection, bool replaceFound) { Dictionary> results = []; if (replaceFound) { foreach ((string key, Dictionary keyValuePairs) in collection) _ = results.TryAdd(key, keyValuePairs); } else { foreach ((string key, Dictionary keyValuePairs) in collection.OrderBy(l => l.Key)) _ = results.TryAdd(key, keyValuePairs); } return results; } private static Dictionary GetHosts(string jsonl) { Dictionary results = []; int id; string json = $"[{File.ReadAllText(jsonl).Replace("\r\n", ",")}]"; Host[] hosts = JsonSerializer.Deserialize(json, HostCollectionSourceGenerationContext.Default.HostArray) ?? throw new NullReferenceException(nameof(json)); foreach (Host host in hosts) { if (host.Id is null) continue; if (host.Hyphen is not null and nameof(host.Hyphen)) continue; if (!int.TryParse(host.Id, out id)) throw new NotSupportedException($"{host.Id} is not a number"); if (results.ContainsKey(id)) throw new NotSupportedException($"Id {id} is not unique!"); results.Add(id, host); } return results; } private static int? GetHeaderLine(string[] lines) { int? headerLine = null; for (int i = 0; i < lines.Length - 1; i++) { if (!lines[i].Contains('\t')) continue; headerLine = i; } return headerLine; } private static Dictionary> GetKeyValuePairs(int keyIndex, int keyLength, string replace, string[] headers, string[] lines, int headerLine) { Dictionary> results; string? key; Record record; bool replaceFound = false; List collection = []; Dictionary keyValuePairs; for (int i = headerLine + 1; i < lines.Length; i++) { key = null; keyValuePairs = []; for (int j = 0; j < headers.Length; j++) { if (j > 0) i++; if (lines.Length <= i) { keyValuePairs.Clear(); break; } if (j == keyIndex) { key = lines[i]; if (key.Length != keyLength) { keyValuePairs.Clear(); break; } } if (lines[i] != replace) _ = keyValuePairs.TryAdd(headers[j], lines[i]); else { if (!replaceFound) replaceFound = true; _ = keyValuePairs.TryAdd(headers[j], lines[i]); j++; _ = keyValuePairs.TryAdd(headers[j], lines[i]); } } if (keyValuePairs.Count != headers.Length) continue; key ??= "-"; record = new(key, keyValuePairs); collection.Add(record); } results = GetKeyValuePairs(collection, replaceFound); return results; } private static ReadOnlyCollection GetIpAddressAndVerify(ILogger logger, string key, Dictionary> keyValuePairs, Dictionary hosts, string filter) { List results = []; int id; bool found; Host? host; string text; string? ipAddress; StringBuilder stringBuilder = new(); foreach (KeyValuePair> keyValuePair in keyValuePairs) { found = false; if (keyValuePair.Key.StartsWith(filter)) continue; if (!keyValuePair.Value.TryGetValue(key, out ipAddress)) throw new NotSupportedException($"{key} isn't present!"); if (ipAddress == "0.0.0.0") continue; results.Add(ipAddress); _ = stringBuilder.Clear(); foreach (KeyValuePair keyValue in keyValuePair.Value) _ = stringBuilder.AppendLine(keyValue.Value); text = stringBuilder.ToString(); if (!int.TryParse(ipAddress.Split('.')[^1], out id)) throw new NotSupportedException($"{ipAddress} isn't valid!"); if (!hosts.TryGetValue(id, out host)) throw new NotSupportedException($"{id} isn't valid!"); foreach (KeyValuePair keyValue in keyValuePair.Value) { if (keyValue.Value != host.Hyphen) continue; found = true; } if (!found) throw new NotSupportedException($"{host}{Environment.NewLine}{text} doesn't match!"); if (text.Contains("Unknown", StringComparison.InvariantCultureIgnoreCase)) logger.LogWarning($"{text} contains Unknown and should be {host.Device}!"); } return new(results); } private static void WriteAppendToHostConfFile(FileInfo fileInfo, string hostConfFile, Dictionary hosts, ReadOnlyCollection ipAddress) { int id; Host host; string ip; string line; List distinct = []; List lines = [$"# {fileInfo.LastWriteTime.Ticks}"]; string firstSegmentsOfIpAddress = string.Join('.', ipAddress[0].Split('.').Take(3)); foreach (KeyValuePair keyValuePair in hosts) { host = keyValuePair.Value; if (host.Hyphen is not null and nameof(host.Hyphen)) continue; if (host.Id is null || host.Hyphen is null || host.Device is null || host.Name is null || host.Hyphen.Length != 17) throw new NotSupportedException($"{host.Id} is Null or not 17"); if (!int.TryParse(host.Id, out id)) throw new NotSupportedException($"{host.Id} is not a number"); if (distinct.Contains(id)) throw new NotSupportedException($"{id} is not distinct!"); distinct.Add(id); ip = ipAddress.Contains($"{firstSegmentsOfIpAddress}.{id}") ? $"{firstSegmentsOfIpAddress}.{id}" : $"# {firstSegmentsOfIpAddress}.{id}"; line = $"{ip} {host.Name} # https://{host.Name} | {host.Colon} | {host.Hyphen} | {host.Device} |"; lines.Add(line); } lines.Add($"# {fileInfo.LastWriteTime.Ticks}"); File.AppendAllLines(hostConfFile, lines); } internal static void TextToJson(ILogger logger, List args) { string json; string[] lines; int? headerLine; FileInfo fileInfo; string key = args[7]; string filter = args[10]; string replace = args[5]; int keyIndex = int.Parse(args[3]); int keyLength = int.Parse(args[4]); ReadOnlyCollection ipAddress; string[] headers = args[6].Split(','); string jsonl = Path.Combine(args[0], args[8]); string hostConfFile = Path.Combine(args[0], args[9]); string[] txtFiles = Directory.GetFiles(args[0], args[2]); Dictionary> keyValuePairs; if (!File.Exists(jsonl)) throw new NotSupportedException($"{args[8]} doesn't exist!"); Dictionary hosts = GetHosts(jsonl); if (hosts.Count == 0) throw new NotSupportedException($"{args[8]} isn't valid!"); foreach (string txtFile in txtFiles) { lines = File.ReadAllLines(txtFile); if (lines.Length == 0) continue; headerLine = GetHeaderLine(lines); if (headerLine is null) continue; fileInfo = new(txtFile); keyValuePairs = GetKeyValuePairs(keyIndex, keyLength, replace, headers, lines, headerLine.Value); if (keyValuePairs.Count == 0) continue; ipAddress = GetIpAddressAndVerify(logger, key, keyValuePairs, hosts, filter); if (ipAddress.Count == 0) continue; json = JsonSerializer.Serialize(keyValuePairs, DictionaryDictionarySourceGenerationContext.Default.DictionaryStringDictionaryStringString); logger.LogInformation("Writing output file..."); File.WriteAllText($"{fileInfo.FullName}-{fileInfo.LastWriteTime.Ticks}.json", json); WriteAppendToHostConfFile(fileInfo, hostConfFile, hosts, ipAddress); File.WriteAllLines(txtFile, [string.Empty, string.Empty, lines[^1]]); } } }