Update Namespaces

This commit is contained in:
2024-08-09 09:54:22 -07:00
parent a0699ef634
commit 29bec0cb9a
38 changed files with 74 additions and 74 deletions

View File

@ -0,0 +1,151 @@
using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240403
{
private record DynamicHostConfigurationProtocolConfiguration(string[] Columns,
string Directory,
string Ignore,
int KeyIndex,
string Pattern,
string Primary);
private static void AlertIfNewDeviceIsConnected(DynamicHostConfigurationProtocolConfiguration dynamicHostConfigurationProtocolConfiguration, ILogger<Worker> logger)
{
string[] files = Directory.GetFiles(dynamicHostConfigurationProtocolConfiguration.Directory, dynamicHostConfigurationProtocolConfiguration.Pattern, SearchOption.TopDirectoryOnly);
string? match = GetMatch(dynamicHostConfigurationProtocolConfiguration, files);
if (string.IsNullOrEmpty(match))
throw new NotSupportedException($"{dynamicHostConfigurationProtocolConfiguration.Primary} doesn't exist!");
ReadOnlyDictionary<string, int> keyToCounts = GetKeyToCounts(dynamicHostConfigurationProtocolConfiguration, files);
foreach (KeyValuePair<string, int> keyToCount in keyToCounts)
{
if (keyToCount.Value < 2)
continue;
logger.LogInformation("{Key}: {Count}", keyToCount.Key, keyToCount.Value);
}
ReadOnlyDictionary<string, ReadOnlyDictionary<string, ReadOnlyCollection<string>>> keyValuePairs = GetKeyValuePairs(dynamicHostConfigurationProtocolConfiguration, files);
foreach (KeyValuePair<string, ReadOnlyDictionary<string, ReadOnlyCollection<string>>> keyValuePair in keyValuePairs)
{
if (!keyValuePair.Key.EndsWith(dynamicHostConfigurationProtocolConfiguration.Primary))
continue;
}
}
internal static void AlertIfNewDeviceIsConnected(ILogger<Worker> logger, List<string> args)
{
string ignore = args[6];
string pattern = args[2];
string primary = args[3];
string keyIndex = args[5];
string directory = args[0];
logger.LogInformation(directory);
string[] columns = args[4].Split('|');
DynamicHostConfigurationProtocolConfiguration dynamicHostConfigurationProtocolConfiguration = new(columns, directory, ignore, int.Parse(keyIndex), pattern, primary);
AlertIfNewDeviceIsConnected(dynamicHostConfigurationProtocolConfiguration, logger);
}
private static string? GetMatch(DynamicHostConfigurationProtocolConfiguration dynamicHostConfigurationProtocolConfiguration, string[] files)
{
string? result = null;
foreach (string file in files)
{
if (file.EndsWith(dynamicHostConfigurationProtocolConfiguration.Primary))
result = file;
}
return result;
}
private static ReadOnlyDictionary<string, int> GetKeyToCounts(DynamicHostConfigurationProtocolConfiguration dynamicHostConfigurationProtocolConfiguration, string[] files)
{
Dictionary<string, int> results = [];
bool check;
string key;
string[] lines;
string[] segments;
List<int>? collection;
Dictionary<string, List<int>> keyValuePairs = [];
int columnsLength = dynamicHostConfigurationProtocolConfiguration.Columns.Length;
foreach (string file in files)
{
check = false;
lines = File.ReadAllLines(file);
foreach (string line in lines)
{
if (line.Length < 3 || line[0] != '|' || line[^1] != '|')
continue;
segments = line.Split('|');
if (segments.Length != columnsLength)
continue;
key = segments[dynamicHostConfigurationProtocolConfiguration.KeyIndex].Trim();
if (!check)
{
if (!key.StartsWith('-') || !key.EndsWith('-'))
continue;
check = true;
continue;
}
if (key == dynamicHostConfigurationProtocolConfiguration.Ignore)
break;
if (!keyValuePairs.TryGetValue(key, out collection))
{
keyValuePairs.Add(key, []);
if (!keyValuePairs.TryGetValue(key, out collection))
throw new Exception();
}
collection.Add(1);
}
}
foreach (KeyValuePair<string, List<int>> keyValuePair in keyValuePairs.OrderByDescending(l => l.Value.Count))
results.Add(keyValuePair.Key, keyValuePair.Value.Count);
return new(results);
}
private static ReadOnlyDictionary<string, ReadOnlyDictionary<string, ReadOnlyCollection<string>>> GetKeyValuePairs(DynamicHostConfigurationProtocolConfiguration dynamicHostConfigurationProtocolConfiguration, string[] files)
{
ReadOnlyDictionary<string, ReadOnlyDictionary<string, ReadOnlyCollection<string>>> results;
bool check;
string key;
string[] lines;
string[] segments;
List<string> keys = [];
Dictionary<string, ReadOnlyCollection<string>> keyValuePairs;
Dictionary<string, ReadOnlyDictionary<string, ReadOnlyCollection<string>>> fileTo = [];
int columnsLength = dynamicHostConfigurationProtocolConfiguration.Columns.Length;
foreach (string file in files)
{
keys.Clear();
check = false;
keyValuePairs = [];
lines = File.ReadAllLines(file);
foreach (string line in lines)
{
if (line.Length < 3 || line[0] != '|' || line[^1] != '|')
continue;
segments = line.Split('|');
if (segments.Length != columnsLength)
continue;
key = segments[dynamicHostConfigurationProtocolConfiguration.KeyIndex].Trim();
if (!check)
{
if (!key.StartsWith('-') || !key.EndsWith('-'))
continue;
check = true;
continue;
}
if (key == dynamicHostConfigurationProtocolConfiguration.Ignore)
break;
if (keys.Contains(key))
throw new NotSupportedException($"{key}: is a duplicate!");
keys.Add(key);
keyValuePairs.Add(key, new(segments.Select(l => l.Trim()).ToArray()));
}
fileTo.Add(Path.GetFullPath(file), new(keyValuePairs));
}
results = new(fileTo);
return results;
}
}

View File

@ -0,0 +1,96 @@
using Microsoft.Extensions.Logging;
using System.Text.RegularExpressions;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240404
{
private record MetaData(int DeviceId,
string DeviceType,
int DeviceNumber,
string DescriptionName,
string DescriptionTest,
string Frequency,
string Date);
private record CommaSeparatedValuesConfiguration(int Columns,
string Directory,
int TestIndex,
int RegularExpressionGroupCount,
string RegularExpressionPattern,
string SearchPattern);
private static void ParseCSV(CommaSeparatedValuesConfiguration commaSeparatedValuesConfiguration, ILogger<Worker> logger)
{
string line;
string test;
string[] lines;
string[] columns;
MetaData? metaData;
string fileNameWithoutExtension;
string[] files = Directory.GetFiles(commaSeparatedValuesConfiguration.Directory, commaSeparatedValuesConfiguration.SearchPattern, SearchOption.TopDirectoryOnly);
logger.LogInformation(files.Length.ToString());
foreach (string file in files)
{
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
metaData = GetMetaData(commaSeparatedValuesConfiguration, fileNameWithoutExtension);
if (metaData is null)
continue;
lines = File.ReadAllLines(file);
if (lines.Length < 2)
continue;
line = lines[0];
columns = line.Split('"');
if (columns.Length != commaSeparatedValuesConfiguration.Columns)
continue;
test = columns[commaSeparatedValuesConfiguration.TestIndex].Trim().Trim('"');
if (test.IndexOf(metaData.DescriptionTest, 0, StringComparison.CurrentCultureIgnoreCase) == -1)
continue;
for (int i = 1; i < lines.Length; i++)
{
line = lines[i];
if (line.Length < 1)
continue;
columns = line.Split(',').Select(l => l.Trim().Trim('"')).ToArray();
if (columns.Length != commaSeparatedValuesConfiguration.Columns)
continue;
}
}
}
internal static void ParseCSV(ILogger<Worker> logger, List<string> args)
{
string directory = args[0];
string regularExpressionPattern = args[2];
string regularExpressionGroupCount = args[3];
string searchPattern = args[4];
string columns = args[5];
string testIndex = args[6];
logger.LogInformation(directory);
CommaSeparatedValuesConfiguration commaSeparatedValuesConfiguration = new(int.Parse(columns), directory, int.Parse(testIndex), int.Parse(regularExpressionGroupCount), regularExpressionPattern, searchPattern);
ParseCSV(commaSeparatedValuesConfiguration, logger);
}
private static MetaData? GetMetaData(CommaSeparatedValuesConfiguration commaSeparatedValuesConfiguration, string fileNameWithoutExtension)
{
MetaData? result;
Match match = Regex.Match(fileNameWithoutExtension, commaSeparatedValuesConfiguration.RegularExpressionPattern);
if (!match.Success || match.Groups.Count != commaSeparatedValuesConfiguration.RegularExpressionGroupCount)
result = null;
else
{
int deviceId = int.Parse(match.Groups["DeviceId"].Value);
int deviceNumber = int.Parse(match.Groups["DeviceNumber"].Value);
result = new(deviceId,
match.Groups["DeviceType"].Value,
deviceNumber,
match.Groups["DescriptionName"].Value,
match.Groups["DescriptionTest"].Value,
match.Groups["Frequency"].Value,
match.Groups["Date"].Value);
}
return result;
}
}

View File

@ -0,0 +1,91 @@
using Microsoft.Extensions.Logging;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240409
{
internal record FsSize( // cSpell:disable
[property: JsonPropertyName("name")] string Name,
[property: JsonPropertyName("object")] string Object,
[property: JsonPropertyName("pmon")] string PMon,
[property: JsonPropertyName("unit")] string Unit,
[property: JsonPropertyName("timeresolution")] string TimeResolution,
[property: JsonPropertyName("aggr")] string Aggr,
[property: JsonPropertyName("data")] List<double[]> Data
); // cSpell:restore
[JsonSourceGenerationOptions(WriteIndented = true, AllowTrailingCommas = true)]
[JsonSerializable(typeof(FsSize))]
internal partial class FsSizeSourceGenerationContext : JsonSerializerContext
{
}
internal static void MonA(ILogger<Worker> logger, List<string> args)
{
string url;
FsSize? fsSize;
string[] segments;
Task<string> json;
string jsonSection;
string urlBase = args[3];
string selector = args[6];
string urlPartA = args[4];
string urlPartC = args[5];
string directory = args[0];
string aggregation = args[8];
int skip = int.Parse(args[7]);
string searchPattern = args[2];
string fileNameWithoutExtension;
string[] ignore = args[9].Split(',');
Task<HttpResponseMessage> httpResponseMessage;
string[] files = Directory.GetFiles(directory, searchPattern, SearchOption.TopDirectoryOnly);
HttpClient httpClient = new(new HttpClientHandler { UseCookies = false }) { BaseAddress = new Uri(urlBase) };
logger.LogInformation("{directory} has {files}(s)", directory, files.Length);
foreach (string file in files)
{
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
if (ignore.Contains(fileNameWithoutExtension))
continue;
url = $"{httpClient.BaseAddress}{urlPartA}{fileNameWithoutExtension}{urlPartC}";
httpResponseMessage = httpClient.GetAsync(url);
httpResponseMessage.Wait();
if (!httpResponseMessage.Result.IsSuccessStatusCode)
{
logger.LogWarning("{StatusCode} for {url}", httpResponseMessage.Result.StatusCode, url);
continue;
}
json = httpResponseMessage.Result.Content.ReadAsStringAsync();
json.Wait();
if (json.Result.Length < 3)
{
logger.LogInformation("{Size} | {Julian} | {PMon} | {FileNameWithoutExtension}", -1, -1, "{}", fileNameWithoutExtension);
continue;
}
segments = json.Result.Split($"\"{fileNameWithoutExtension}{selector}");
if (segments.Length < 2)
{
logger.LogInformation("{Size} | {Julian} | {PMon} | {FileNameWithoutExtension}", -1, -1, selector, fileNameWithoutExtension);
continue;
}
for (int i = 1; i < segments.Length; i++)
{
jsonSection = segments[i][skip..][..^1];
fsSize = JsonSerializer.Deserialize(jsonSection, FsSizeSourceGenerationContext.Default.FsSize);
if (fsSize is null)
continue;
if (fsSize.Aggr != aggregation)
continue;
if (fsSize.Data.Count == 0 || fsSize.Data[0].Length == 0)
{
logger.LogInformation("{Size} | {Julian} | {PMon} | {FileNameWithoutExtension}", -1, -1, nameof(FsSize.Data), fileNameWithoutExtension);
continue;
}
logger.LogInformation("{Size} | {Julian} | {PMon} | {FileNameWithoutExtension}", fsSize.Data[0][1].ToString().PadLeft(20, '0'), fsSize.Data[0][0], fsSize.PMon, fileNameWithoutExtension);
}
}
}
}

View File

@ -0,0 +1,62 @@
using File_Folder_Helper.Helpers;
using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240417
{
private static void RunCommand(ILogger<Worker> logger, string directory, string commandFileName, List<string> files, int before, CancellationToken cancellationToken)
{
bool usePathCombine = false;
string command = $"npx eclint fix {string.Join(' ', files)}";
string output = HelperNPM.RunCommand(commandFileName, command, directory);
logger.LogInformation(output);
if (output.Contains("error", StringComparison.OrdinalIgnoreCase))
{
Environment.ExitCode = 2;
logger.LogCritical("Setting exit code {ExitCode}", Environment.ExitCode);
throw new Exception(output);
}
ReadOnlyCollection<string> afterGitOthersModifiedAndDeletedExcludingStandardFiles = HelperGit.GetOthersModifiedAndDeletedExcludingStandardFiles(directory, usePathCombine, cancellationToken);
int after = afterGitOthersModifiedAndDeletedExcludingStandardFiles.Count;
if (before != after)
{
List<string> fileNames = [];
foreach (string file in afterGitOthersModifiedAndDeletedExcludingStandardFiles)
{
if (file.Contains(' '))
continue;
if (files.Contains(file))
continue;
fileNames.Add(Path.GetFileName(file));
}
Environment.ExitCode = 1;
throw new Exception($"Files were modified exiting with exit code {Environment.ExitCode}!{Environment.NewLine}{string.Join(Environment.NewLine, fileNames)}");
}
}
internal static void FilteredRunCommand(ILogger<Worker> logger, List<string> args, CancellationToken cancellationToken)
{
List<string> files = [];
string directory = args[0];
bool usePathCombine = false;
string commandFileName = args[2];
ReadOnlyCollection<string> gitOthersModifiedAndDeletedExcludingStandardFiles = HelperGit.GetOthersModifiedAndDeletedExcludingStandardFiles(directory, usePathCombine, cancellationToken);
int before = gitOthersModifiedAndDeletedExcludingStandardFiles.Count;
foreach (string file in gitOthersModifiedAndDeletedExcludingStandardFiles)
{
if (file.Contains(' '))
{
logger.LogInformation("Skipping <{File}>", file);
continue;
}
files.Add(file);
}
logger.LogInformation("{directory} has {files} file(s)", directory, before);
if (files.Count > 0)
RunCommand(logger, directory, commandFileName, files, before, cancellationToken);
}
}

View File

@ -0,0 +1,93 @@
using Microsoft.Extensions.Logging;
using System.Text;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240426
{
private static void Write(string toA, string toB, string matchA, string matchB, string file, List<string> lines)
{
StringBuilder stringBuilder = new();
foreach (string line in lines)
_ = stringBuilder.AppendLine(line.Replace(matchB, toB));
string checkFile = file.Replace(matchA, toA);
_ = Directory.CreateDirectory(Path.GetDirectoryName(checkFile) ?? throw new NullReferenceException());
if (!File.Exists(checkFile))
File.WriteAllText(checkFile, stringBuilder.ToString());
}
private static void UpdateTestFiles(ILogger<Worker> logger, string to, string match, string staticDirectoryName, List<string> files)
{
List<string> lines;
string directoryName;
string fistLineCheck;
string lastLineCheck = "#endif";
foreach (string file in files)
{
directoryName = Path.GetFileName(Path.GetDirectoryName(file) ?? throw new NullReferenceException(nameof(directoryName)));
if (directoryName == staticDirectoryName)
continue;
lines = File.ReadAllLines(file).ToList();
if (directoryName == match)
Write(to, to.Replace('.', '_'), match, match.Replace('.', '_'), file, lines);
if (lines.Count < 3)
continue;
fistLineCheck = $"#if {directoryName.Replace('.', '_')}";
if (lines[0].StartsWith("#if true") || lines[0].StartsWith(fistLineCheck))
continue;
for (int i = lines.Count - 1; i > 0; i--)
{
if (!string.IsNullOrEmpty(lines[i]))
break;
lines.RemoveAt(i);
}
if (lines[^1].StartsWith(lastLineCheck))
continue;
if (lines.All(l => string.IsNullOrEmpty(l) || l.StartsWith("//")))
continue;
lines.Add(lastLineCheck);
lines.Insert(0, fistLineCheck);
File.WriteAllText(file, string.Join(Environment.NewLine, lines));
logger.LogDebug(file);
}
}
private static void UpdateProjectTests(ILogger<Worker> logger, string to, string match, string searchPattern, string staticDirectoryName, string extractDirectoryName, string createSelfDescriptionDirectoryName, string sourceCodeDirectory)
{
List<string> files = [];
List<string> knownDirectories = [];
knownDirectories.AddRange(Directory.GetDirectories(sourceCodeDirectory, createSelfDescriptionDirectoryName, SearchOption.AllDirectories));
knownDirectories.AddRange(Directory.GetDirectories(sourceCodeDirectory, extractDirectoryName, SearchOption.AllDirectories));
knownDirectories.AddRange(Directory.GetDirectories(sourceCodeDirectory, staticDirectoryName, SearchOption.AllDirectories));
foreach (string knownDirectory in knownDirectories)
files.AddRange(Directory.GetFiles(knownDirectory, searchPattern, SearchOption.AllDirectories));
logger.LogInformation("{directory} has {files} file(s)", sourceCodeDirectory, files.Count);
UpdateTestFiles(logger, to, match, staticDirectoryName, files);
}
internal static void UpdateTests(ILogger<Worker> logger, List<string> args)
{
string to = args[9];
string match = args[8];
string searchPattern = args[7];
string[] sourceCodeDirectories;
string staticDirectoryName = args[6];
string extractDirectoryName = args[5];
string sourceCodeDirectoryName = args[3];
string directory = Path.GetFullPath(args[0]);
string createSelfDescriptionDirectoryName = args[4];
string systemVolumeInformation = Path.Combine(directory, args[2]);
string[] subDirectories = Directory.GetDirectories(directory, "*", SearchOption.TopDirectoryOnly);
foreach (string subDirectory in subDirectories)
{
if (subDirectory == systemVolumeInformation)
continue;
sourceCodeDirectories = Directory.GetDirectories(subDirectory, sourceCodeDirectoryName, SearchOption.AllDirectories);
if (sourceCodeDirectories.Length != 1)
continue;
UpdateProjectTests(logger, to, match, searchPattern, staticDirectoryName, extractDirectoryName, createSelfDescriptionDirectoryName, sourceCodeDirectories[0]);
}
}
}

View File

@ -0,0 +1,145 @@
using File_Folder_Helper.Helpers;
using Microsoft.Extensions.Logging;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240427
{
internal record Asset( // cSpell:disable
[property: JsonPropertyName("id")] string? Id,
[property: JsonPropertyName("deviceAssetId")] string? DeviceAssetId,
[property: JsonPropertyName("ownerId")] string? OwnerId,
[property: JsonPropertyName("deviceId")] string? DeviceId,
[property: JsonPropertyName("type")] string? Type,
[property: JsonPropertyName("originalPath")] string? OriginalPath,
[property: JsonPropertyName("previewPath")] string? PreviewPath,
[property: JsonPropertyName("fileCreatedAt")] DateTime? FileCreatedAt,
[property: JsonPropertyName("fileModifiedAt")] DateTime? FileModifiedAt,
[property: JsonPropertyName("isFavorite")] bool? IsFavorite,
[property: JsonPropertyName("duration")] object? Duration,
[property: JsonPropertyName("thumbnailPath")] string? ThumbnailPath,
[property: JsonPropertyName("encodedVideoPath")] string? EncodedVideoPath,
[property: JsonPropertyName("checksum")] string? Checksum,
[property: JsonPropertyName("isVisible")] bool? IsVisible,
[property: JsonPropertyName("livePhotoVideoId")] object? LivePhotoVideoId,
[property: JsonPropertyName("updatedAt")] DateTime? UpdatedAt,
[property: JsonPropertyName("createdAt")] DateTime? CreatedAt,
[property: JsonPropertyName("isArchived")] bool? IsArchived,
[property: JsonPropertyName("originalFileName")] string? OriginalFileName,
[property: JsonPropertyName("sidecarPath")] string? SidecarPath,
[property: JsonPropertyName("isReadOnly")] bool? IsReadOnly,
[property: JsonPropertyName("thumbhash")] string? Thumbhash,
[property: JsonPropertyName("isOffline")] bool? IsOffline,
[property: JsonPropertyName("libraryId")] string? LibraryId,
[property: JsonPropertyName("isExternal")] bool? IsExternal,
[property: JsonPropertyName("deletedAt")] DateTime? DeletedAt,
[property: JsonPropertyName("localDateTime")] DateTime? LocalDateTime,
[property: JsonPropertyName("stackId")] object? StackId); // cSpell:restore
[JsonSourceGenerationOptions(WriteIndented = true, AllowTrailingCommas = true)]
[JsonSerializable(typeof(List<Asset>))]
internal partial class AssetCollectionSourceGenerationContext : JsonSerializerContext
{
}
private static string? MoveAsset(string home, string originalFileName, string lastVarDirectoryName, string path)
{
string? result;
string checkFile;
string sourceFile;
int? match = null;
string checkDirectory = home;
string sourceDirectory = home;
string originalFileNameWithoutExtension = Path.GetFileNameWithoutExtension(originalFileName);
List<string> directoryNames = HelperDirectory.GetDirectoryNames(path);
for (int i = 0; i < directoryNames.Count; i++)
{
if (directoryNames[i] != lastVarDirectoryName)
continue;
match = i;
break;
}
if (match is null)
result = null;
else
{
string[] fileNameSegments = directoryNames[^1].Split('-');
foreach (string directory in directoryNames.Skip(match.Value + 1).Take(directoryNames.Count - match.Value - 2))
sourceDirectory = Path.Combine(sourceDirectory, directory);
if (!Directory.Exists(sourceDirectory))
result = null;
else
{
sourceFile = Path.Combine(sourceDirectory, directoryNames[^1]);
if (!File.Exists(sourceFile))
result = null;
else
{
foreach (string directory in directoryNames.Skip(match.Value + 1).Take(directoryNames.Count - match.Value - 2))
checkDirectory = Path.Combine(checkDirectory, directory);
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
checkFile = Path.Combine(checkDirectory, $"{originalFileNameWithoutExtension}{fileNameSegments[^1]}");
if (File.Exists(checkFile))
result = null;
else
{
File.Move(sourceFile, checkFile);
result = checkFile;
}
}
}
}
return result;
}
private static void MoveAssets(ILogger<Worker> logger, string var, string home, string pictures, List<Asset> assets)
{
string? checkFile;
List<string> varDirectoryNames = HelperDirectory.GetDirectoryNames(home);
string lastVarDirectoryName = varDirectoryNames[^1];
foreach (Asset asset in assets)
{
if (asset.OriginalFileName is null)
continue;
if (asset.Type is null or not "IMAGE")
continue;
if (asset.PreviewPath is null || !asset.PreviewPath.StartsWith(var))
continue;
if (asset.ThumbnailPath is null || !asset.ThumbnailPath.StartsWith(var))
continue;
if (asset.OriginalPath is null || !asset.OriginalPath.StartsWith(pictures))
continue;
checkFile = MoveAsset(home, asset.OriginalFileName, lastVarDirectoryName, asset.PreviewPath);
if (checkFile is null)
continue;
checkFile = MoveAsset(home, asset.OriginalFileName, lastVarDirectoryName, asset.ThumbnailPath);
if (checkFile is null)
continue;
logger.LogDebug("<{OriginalFileName}> moved.", asset.OriginalFileName);
}
}
#pragma warning restore IDE0055, IDE0059, IDE0060, IDE2000, CS0168
internal static void Immich(Models.AppSettings appSettings, ILogger<Worker> logger, List<string> args)
{
string var = args[5];
string home = args[6];
string query = args[3];
string jsonFile = args[4];
string pictures = args[7];
string directory = args[0];
logger.LogInformation(query);
string databasePassword = args[2];
string json = File.ReadAllText(Path.Combine(directory, jsonFile));
List<Asset> assets = JsonSerializer.Deserialize(json, AssetCollectionSourceGenerationContext.Default.ListAsset) ?? throw new NullReferenceException();
string encryptedPassword = RijndaelEncryption.Encrypt(databasePassword, appSettings.Company);
MoveAssets(logger, var, home, pictures, assets);
logger.LogInformation("Encrypted Password: [{EncryptedPassword}]", encryptedPassword);
}
}

View File

@ -0,0 +1,56 @@
using Microsoft.Extensions.Logging;
using System.Diagnostics;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240429
{
internal static void GitConfigCleanUp(ILogger<Worker> logger, List<string> args)
{
string[] files;
Process? process;
string? directory;
string standardError;
string ignoreError = args[5];
string searchPattern = args[3];
ProcessStartInfo processStartInfo;
string root = Path.GetFullPath(args[0]);
string[] removeRemotes = args[4].Split(',');
string systemVolumeInformation = Path.Combine(root, args[2]);
string[] subDirectories = Directory.GetDirectories(root, "*", SearchOption.TopDirectoryOnly);
foreach (string subDirectory in subDirectories)
{
if (subDirectory == systemVolumeInformation)
continue;
files = Directory.GetFiles(subDirectory, searchPattern, SearchOption.AllDirectories);
foreach (string file in files)
{
directory = Path.GetDirectoryName(file);
if (directory is null)
continue;
foreach (string removeRemote in removeRemotes)
{
processStartInfo = new()
{
FileName = "git",
WorkingDirectory = directory,
Arguments = $"remote rm {removeRemote}",
RedirectStandardError = true
};
process = Process.Start(processStartInfo);
if (process is null)
continue;
#pragma warning disable IDE0058
process.WaitForExit(7000);
#pragma warning restore IDE0058
standardError = process.StandardError.ReadToEnd();
if (!standardError.Contains(ignoreError))
logger.LogInformation(standardError);
logger.LogInformation("for <{directoryName}> remote rm {removeRemote}", directory, removeRemote);
}
}
}
}
}

View File

@ -0,0 +1,34 @@
using Microsoft.Extensions.Logging;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240510
{
internal static void PullIconsForBLM(ILogger<Worker> logger, List<string> args)
{
string fileName;
FileInfo fileInfo;
string searchPattern = args[4];
string sourceDirectory = args[3];
string root = Path.GetFullPath(args[0]);
string createDirectory = Path.Combine(root, args[2]);
if (!Directory.Exists(createDirectory))
_ = Directory.CreateDirectory(createDirectory);
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
fileName = Path.GetFileName(file);
fileInfo = new(Path.Combine(createDirectory, fileName));
if (fileInfo.Exists && fileInfo.LastWriteTime == new FileInfo(file).LastWriteTime)
continue;
File.Copy(file, fileInfo.FullName, overwrite: true);
logger.LogInformation("<{fileName}> copied", fileName);
}
logger.LogWarning("What reactor is this near?");
string? reactor = Console.ReadLine();
if (!string.IsNullOrEmpty(reactor))
_ = Directory.CreateDirectory(Path.Combine(sourceDirectory, Environment.MachineName, reactor));
}
}

View File

@ -0,0 +1,39 @@
using File_Folder_Helper.Models;
using Microsoft.Extensions.Logging;
using System.Text.Json;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240513
{
internal static void PersonKeyToName(ILogger<Worker> logger, List<string> args)
{
Person? person;
string directoryName;
string checkDirectory;
string root = Path.GetFullPath(args[0]);
string json = File.ReadAllText(args[2]);
Dictionary<string, Person> keyValuePairs = [];
string[] directories = Directory.GetDirectories(root, "*", SearchOption.TopDirectoryOnly);
Dictionary<long, Person> people = JsonSerializer.Deserialize(json, PeopleSourceGenerationContext.Default.DictionaryInt64Person) ?? throw new NullReferenceException();
foreach (KeyValuePair<long, Person> keyValuePair in people)
{
if (keyValuePair.Value.Birth?.Note is null)
continue;
keyValuePairs.Add(keyValuePair.Value.Birth.Note, keyValuePair.Value);
}
foreach (string directory in directories)
{
directoryName = Path.GetFileName(directory);
if (!keyValuePairs.TryGetValue(directoryName, out person) || person.Name?.ForwardSlashFull is null)
continue;
checkDirectory = Path.Combine(root, $"{person.Name.ForwardSlashFull.Replace('/', '-')}{directoryName}-{person.Id}");
if (Directory.Exists(checkDirectory))
continue;
Directory.Move(directory, checkDirectory);
logger.LogInformation("<{directory}> was moved", directory);
}
}
}

View File

@ -0,0 +1,334 @@
using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240517
{
public record ContentSignature([property: JsonPropertyName("contentSignature")] string Value,
[property: JsonPropertyName("contentSignatureType")] string ContentSignatureType);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ContentSignature))]
public partial class ContentSignatureGenerationContext : JsonSerializerContext
{
}
public record Type([property: JsonPropertyName("count")] int Count,
[property: JsonPropertyName("match")] string Match,
[property: JsonPropertyName("searchData")] SearchData SearchData);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Type))]
public partial class TypeGenerationContext : JsonSerializerContext
{
}
public record ImageAmazon([property: JsonPropertyName("colorSpace")] string ColorSpace,
[property: JsonPropertyName("dateTime")] DateTime DateTime,
[property: JsonPropertyName("dateTimeDigitized")] DateTime DateTimeDigitized,
[property: JsonPropertyName("dateTimeOriginal")] DateTime DateTimeOriginal,
[property: JsonPropertyName("exposureMode")] string ExposureMode,
[property: JsonPropertyName("exposureProgram")] string ExposureProgram,
[property: JsonPropertyName("exposureTime")] string ExposureTime,
[property: JsonPropertyName("flash")] string Flash,
[property: JsonPropertyName("focalLength")] string FocalLength,
[property: JsonPropertyName("height")] int Height,
[property: JsonPropertyName("make")] string Make,
[property: JsonPropertyName("meteringMode")] string MeteringMode,
[property: JsonPropertyName("model")] string Model,
[property: JsonPropertyName("orientation")] string Orientation,
[property: JsonPropertyName("resolutionUnit")] string ResolutionUnit,
[property: JsonPropertyName("sensingMethod")] string SensingMethod,
[property: JsonPropertyName("sharpness")] string Sharpness,
[property: JsonPropertyName("software")] string Software,
[property: JsonPropertyName("subSecTime")] string SubSecTime,
[property: JsonPropertyName("subSecTimeDigitized")] string SubSecTimeDigitized,
[property: JsonPropertyName("subSecTimeOriginal")] string SubSecTimeOriginal,
[property: JsonPropertyName("whiteBalance")] string WhiteBalance,
[property: JsonPropertyName("width")] int Width,
[property: JsonPropertyName("apertureValue")] string ApertureValue);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ImageAmazon))]
public partial class ImageAmazonGenerationContext : JsonSerializerContext
{
}
public record ContentProperties([property: JsonPropertyName("contentDate")] DateTime ContentDate,
[property: JsonPropertyName("contentSignatures")] IReadOnlyList<ContentSignature> ContentSignatures,
[property: JsonPropertyName("contentType")] string ContentType,
[property: JsonPropertyName("extension")] string Extension,
[property: JsonPropertyName("image")] ImageAmazon Image,
[property: JsonPropertyName("md5")] string Md5,
[property: JsonPropertyName("size")] int Size,
[property: JsonPropertyName("version")] int Version);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ContentProperties))]
public partial class ContentPropertiesGenerationContext : JsonSerializerContext
{
}
public record XAccntParentMap();
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(XAccntParentMap))]
public partial class XAccntParentMapGenerationContext : JsonSerializerContext
{
}
public record Datum([property: JsonPropertyName("accessRuleIds")] IReadOnlyList<object> AccessRuleIds,
[property: JsonPropertyName("childAssetTypeInfo")] IReadOnlyList<object> ChildAssetTypeInfo,
[property: JsonPropertyName("contentProperties")] ContentProperties ContentProperties,
[property: JsonPropertyName("createdBy")] string CreatedBy,
[property: JsonPropertyName("createdDate")] DateTime CreatedDate,
[property: JsonPropertyName("eTagResponse")] string ETagResponse,
[property: JsonPropertyName("groupPermissions")] IReadOnlyList<object> GroupPermissions,
[property: JsonPropertyName("id")] string Id,
[property: JsonPropertyName("isRoot")] bool IsRoot,
[property: JsonPropertyName("isShared")] bool IsShared,
[property: JsonPropertyName("keywords")] IReadOnlyList<object> Keywords,
[property: JsonPropertyName("kind")] string Kind,
[property: JsonPropertyName("labels")] IReadOnlyList<object> Labels,
[property: JsonPropertyName("modifiedDate")] DateTime ModifiedDate,
[property: JsonPropertyName("name")] string Name,
[property: JsonPropertyName("ownerId")] string OwnerId,
[property: JsonPropertyName("parentMap")] ParentMap ParentMap,
[property: JsonPropertyName("parents")] IReadOnlyList<string> Parents,
[property: JsonPropertyName("protectedFolder")] bool ProtectedFolder,
[property: JsonPropertyName("restricted")] bool Restricted,
[property: JsonPropertyName("status")] string Status,
[property: JsonPropertyName("subKinds")] IReadOnlyList<object> SubKinds,
[property: JsonPropertyName("transforms")] IReadOnlyList<string> Transforms,
[property: JsonPropertyName("version")] int Version,
[property: JsonPropertyName("xAccntParentMap")] XAccntParentMap XAccntParentMap,
[property: JsonPropertyName("xAccntParents")] IReadOnlyList<object> XAccntParents,
[property: JsonPropertyName("match")] bool? Match);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Datum))]
public partial class DatumGenerationContext : JsonSerializerContext
{
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Dictionary<string, Datum>))]
public partial class DictionaryDatumGenerationContext : JsonSerializerContext
{
}
public record LocationAmazon([property: JsonPropertyName("count")] int Count,
[property: JsonPropertyName("match")] string Match,
[property: JsonPropertyName("searchData")] SearchData SearchData);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(LocationAmazon))]
public partial class LocationAmazonGenerationContext : JsonSerializerContext
{
}
public record LocationInfo([property: JsonPropertyName("city")] string City,
[property: JsonPropertyName("country")] string Country,
[property: JsonPropertyName("countryIso3Code")] string CountryIso3Code,
[property: JsonPropertyName("state")] string State,
[property: JsonPropertyName("stateCode")] string StateCode);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(LocationInfo))]
public partial class LocationInfoGenerationContext : JsonSerializerContext
{
}
public record SearchData([property: JsonPropertyName("clusterName")] string ClusterName,
[property: JsonPropertyName("locationId")] string LocationId,
[property: JsonPropertyName("locationInfo")] LocationInfo LocationInfo,
[property: JsonPropertyName("thingId")] string ThingId);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(SearchData))]
public partial class SearchDataGenerationContext : JsonSerializerContext
{
}
public record AllPerson([property: JsonPropertyName("count")] int Count,
[property: JsonPropertyName("match")] string Match,
[property: JsonPropertyName("searchData")] SearchData SearchData);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(AllPerson))]
public partial class AllPersonGenerationContext : JsonSerializerContext
{
}
public record PersonAmazon([property: JsonPropertyName("count")] int Count,
[property: JsonPropertyName("match")] string Match,
[property: JsonPropertyName("searchData")] SearchData SearchData);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(PersonAmazon))]
public partial class PersonAmazonGenerationContext : JsonSerializerContext
{
}
public record ClusterId([property: JsonPropertyName("count")] int Count,
[property: JsonPropertyName("match")] string Match,
[property: JsonPropertyName("searchData")] SearchData SearchData);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ClusterId))]
public partial class ClusterIdGenerationContext : JsonSerializerContext
{
}
public record Thing([property: JsonPropertyName("count")] int Count,
[property: JsonPropertyName("match")] string Match,
[property: JsonPropertyName("searchData")] SearchData SearchData);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Thing))]
public partial class ThingGenerationContext : JsonSerializerContext
{
}
public record Time([property: JsonPropertyName("count")] int Count,
[property: JsonPropertyName("match")] string Match,
[property: JsonPropertyName("searchData")] SearchData SearchData);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Time))]
public partial class TimeGenerationContext : JsonSerializerContext
{
}
public record ParentMap([property: JsonPropertyName("FOLDER")] IReadOnlyList<string> FOLDER);
public record Aggregations([property: JsonPropertyName("allPeople")] IReadOnlyList<AllPerson> AllPeople,
[property: JsonPropertyName("clusterId")] IReadOnlyList<ClusterId> ClusterId,
[property: JsonPropertyName("location")] IReadOnlyList<LocationAmazon> Location,
[property: JsonPropertyName("people")] IReadOnlyList<PersonAmazon> People,
[property: JsonPropertyName("things")] IReadOnlyList<Thing> Things,
[property: JsonPropertyName("time")] IReadOnlyList<Time> Time,
[property: JsonPropertyName("type")] IReadOnlyList<Type> Type);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Aggregations))]
public partial class AggregationsGenerationContext : JsonSerializerContext
{
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ParentMap))]
public partial class ParentMapGenerationContext : JsonSerializerContext
{
}
public record RootAmazon([property: JsonPropertyName("aggregations")] Aggregations Aggregations,
[property: JsonPropertyName("count")] int Count,
[property: JsonPropertyName("data")] IReadOnlyList<Datum> Data);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(RootAmazon))]
public partial class RootAmazonGenerationContext : JsonSerializerContext
{
}
private static void SaveAmazon(string destination, string harFile)
{
string offset;
string personId;
RootAmazon amazon;
string? personName;
string personIdFile;
string personDirectory;
PersonAmazon personAmazon;
Dictionary<string, string> keyValuePairs = [];
ReadOnlyCollection<(string Url, string AggregationLine)> aggregationLines = GetAggregationLines(harFile);
foreach ((string url, string aggregationLine) in aggregationLines)
{
if (aggregationLine.Contains(",\"category\":\"allPeople\"}"))
continue;
amazon = JsonSerializer.Deserialize(aggregationLine, RootAmazonGenerationContext.Default.RootAmazon) ?? throw new Exception();
if (amazon.Aggregations?.People is null || amazon.Aggregations.People.Count < 1)
continue;
personAmazon = amazon.Aggregations.People[0];
if (!url.Contains(personAmazon.Match))
continue;
personDirectory = Path.Combine(destination, personAmazon.SearchData.ClusterName);
_ = Directory.CreateDirectory(personDirectory);
personIdFile = Path.Combine(personDirectory, $"000) {personAmazon.Match}.json");
_ = keyValuePairs.TryAdd(personAmazon.Match, personAmazon.SearchData.ClusterName);
SaveAmazon(amazon.Data, personIdFile);
}
foreach ((string url, string aggregationLine) in aggregationLines)
{
if (aggregationLine.Contains(",\"category\":\"allPeople\"}"))
continue;
amazon = JsonSerializer.Deserialize(aggregationLine, RootAmazonGenerationContext.Default.RootAmazon) ?? throw new Exception();
if (amazon.Aggregations?.People is not null && amazon.Aggregations.People.Count > 0)
continue;
if (!url.Contains("offset="))
continue;
offset = url.Split("offset=")[1];
if (!url.Contains("people%3A("))
continue;
personId = url.Split("people%3A(")[1].Split(')')[0];
if (!keyValuePairs.TryGetValue(personId, out personName))
continue;
personDirectory = Path.Combine(destination, personName);
_ = Directory.CreateDirectory(personDirectory);
personIdFile = Path.Combine(personDirectory, $"{offset.Split('&')[0]}) {personId}.json");
SaveAmazon(amazon.Data, personIdFile);
}
}
internal static void SaveAmazon(ILogger<Worker> logger, List<string> args)
{
string root = Path.GetFullPath(args[0]);
string destination = Path.GetFullPath(args[2]);
if (string.IsNullOrEmpty(root))
throw new NullReferenceException(nameof(root));
string[] harFiles = Directory.GetFiles(root, "*.har", SearchOption.TopDirectoryOnly);
foreach (string harFile in harFiles)
SaveAmazon(destination, harFile);
logger?.LogInformation("{harFiles} count", harFiles.Length);
}
private static void SaveAmazon(IReadOnlyList<Datum> data, string personIdFile)
{
string json;
Dictionary<string, Datum> keyValuePairs = [];
foreach (Datum datum in data)
_ = keyValuePairs.TryAdd(datum.Name.Split('.')[0], datum);
json = JsonSerializer.Serialize(keyValuePairs, DictionaryDatumGenerationContext.Default.DictionaryStringDatum);
File.WriteAllText(personIdFile, json);
}
private static ReadOnlyCollection<(string, string)> GetAggregationLines(string harFile)
{
List<(string, string)> results = [];
if (!File.Exists(harFile))
throw new Exception();
string lastUrl = string.Empty;
string text = "\"text\": \"{";
string[] lines = File.ReadAllLines(harFile);
foreach (string line in lines)
{
if (line.Contains("\"url\": \""))
lastUrl = line;
if (!line.Contains(text))
continue;
if (!line.Contains("aggregations"))
continue;
if (lastUrl.Contains("search?asset=NONE"))
continue;
results.Add(new(lastUrl, line.Trim()[(text.Length - 1)..^1].Replace("\\\"", "\"")));
lastUrl = string.Empty;
}
return new(results);
}
}

View File

@ -0,0 +1,35 @@
using File_Folder_Helper.Models;
using Microsoft.Extensions.Logging;
using System.Text.Json;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240518
{
internal static void PersonKeyToImmichImport(ILogger<Worker> logger, List<string> args)
{
string name;
string birthDate;
string ownerId = args[5];
List<string> inserts = [];
string tableName = args[3];
string birthDateFormat = args[6];
string[] columns = args[4].Split(',');
string json = File.ReadAllText(args[2]);
string root = Path.GetFullPath(args[0]);
Dictionary<long, Person> people = JsonSerializer.Deserialize(json, PeopleSourceGenerationContext.Default.DictionaryInt64Person) ?? throw new NullReferenceException();
foreach (KeyValuePair<long, Person> keyValuePair in people)
{
if (keyValuePair.Value.Birth?.Note is null || keyValuePair.Value.Name?.ForwardSlashFull is null || keyValuePair.Value.Birth?.Date is null)
continue;
birthDate = keyValuePair.Value.Birth.Date.Value.ToString(birthDateFormat);
name = keyValuePair.Value.Name.ForwardSlashFull.Replace("/", string.Empty);
inserts.Add($"insert into \"{tableName}\" (\"{string.Join("\", \"", columns)}\") values ('{ownerId}', '{name}', '{birthDate}');");
}
string file = Path.Combine(root, $"{DateTime.Now.Ticks}.sql");
logger.LogInformation("<{file}> saved", file);
File.WriteAllLines(file, inserts);
}
}

View File

@ -0,0 +1,80 @@
using File_Folder_Helper.Helpers;
using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240519
{
private record Record(long Length, long Ticks);
private static ReadOnlyDictionary<string, Record> GetKeyValuePairs(string source, string[] sourceFiles)
{
Dictionary<string, Record> results = [];
string key;
Record? record;
FileInfo fileInfo;
int sourceLength = source.Length;
foreach (string sourceFile in sourceFiles)
{
fileInfo = new(sourceFile);
key = sourceFile[sourceLength..];
if (results.TryGetValue(key, out record))
throw new NotSupportedException();
results.Add(key, new(fileInfo.Length, fileInfo.LastWriteTime.Ticks));
}
return new(results);
}
internal static void FindReplaceDirectoryName(ILogger<Worker> logger, List<string> args)
{
string checkDirectory;
string replaceText = args[3];
string[] findTexts = args[2].Split(',');
string root = Path.GetFullPath(args[0]);
string[] directories = Directory.GetDirectories(root, "*", SearchOption.TopDirectoryOnly);
foreach (string directory in directories)
{
checkDirectory = directory;
foreach (string findText in findTexts)
checkDirectory = checkDirectory.Replace(findText, replaceText);
if (checkDirectory == directory)
continue;
if (Directory.Exists(checkDirectory))
continue;
logger.LogInformation("<{directory}> to <{checkDirectory}>", directory, checkDirectory);
Directory.Move(directory, checkDirectory);
}
string key;
Record? record;
string checkFile;
FileInfo fileInfo;
string target = Path.GetFullPath(args[6]);
string source = Path.GetFullPath(args[4]);
string compare = Path.GetFullPath(args[5]);
string[] sourceFiles = Directory.GetFiles(source, "*", SearchOption.AllDirectories);
ReadOnlyDictionary<string, Record> keyValuePairs = GetKeyValuePairs(source, sourceFiles);
string[] compareFiles = Directory.GetFiles(compare, "*", SearchOption.AllDirectories);
int compareLength = compare.Length;
foreach (string compareFile in compareFiles)
{
fileInfo = new(compareFile);
key = compareFile[compareLength..];
if (!keyValuePairs.TryGetValue(key, out record))
continue;
if (fileInfo.Length != record.Length || fileInfo.LastWriteTime.Ticks != record.Ticks)
continue;
checkFile = $"{target}{key}";
checkDirectory = Path.GetDirectoryName(checkFile) ?? throw new NotSupportedException();
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
if (File.Exists(checkFile))
continue;
logger.LogInformation("<{compareFile}> to <{checkFile}>", compareFile, checkFile);
File.Move(compareFile, checkFile);
}
HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, compare);
}
}

View File

@ -0,0 +1,160 @@
using File_Folder_Helper.Helpers;
using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240520
{
private record RecordA(string Directory, string Extension, string SourceFile, Identifier Identifier);
private record RecordB(ReadOnlyDictionary<int, Identifier> IdTo, ReadOnlyDictionary<long, Identifier> LengthTo, ReadOnlyDictionary<string, Identifier> PaddedTo);
internal sealed record Identifier(int Id, long Length, string PaddedId, long Ticks)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, IdentifierSourceGenerationContext.Default.Identifier);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Identifier))]
internal partial class IdentifierSourceGenerationContext : JsonSerializerContext
{
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Identifier[]))]
internal partial class IdentifierCollectionSourceGenerationContext : JsonSerializerContext
{
}
private static RecordB GetRecordB(string jsonFile)
{
RecordB result;
Dictionary<int, Identifier> idTo = [];
Dictionary<long, Identifier> lengthTo = [];
Dictionary<string, Identifier> paddedTo = [];
string? json = !File.Exists(jsonFile) ? null : File.ReadAllText(jsonFile);
Identifier[]? identifiers = json is null ? null : JsonSerializer.Deserialize(json, IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
if (identifiers is null && !string.IsNullOrEmpty(jsonFile))
throw new Exception($"Invalid {nameof(jsonFile)}");
if (identifiers is not null)
{
foreach (Identifier identifier in identifiers)
{
idTo.Add(identifier.Id, identifier);
paddedTo.Add(identifier.PaddedId, identifier);
if (lengthTo.ContainsKey(identifier.Length))
{
_ = lengthTo.Remove(identifier.Length);
continue;
}
lengthTo.Add(identifier.Length, identifier);
}
}
result = new(new(idTo), new(lengthTo), new(paddedTo));
return result;
}
internal static void IdentifierRename(ILogger<Worker> logger, List<string> args)
{
int id;
string key;
RecordA recordA;
string checkFile;
FileInfo fileInfo;
string checkDirectory;
Identifier? identifier;
string offset = args[5];
string option = args[7];
string jsonFile = args[4];
string fileNameWithoutExtension;
List<RecordA> recordACollection = [];
RecordB recordB = GetRecordB(jsonFile);
string deterministicHashCode = args[3];
string source = Path.GetFullPath(args[0]);
int intMinValueLength = int.Parse(args[2]);
string destination = Path.GetFullPath(args[6]);
bool isOffsetDeterministicHashCode = offset == deterministicHashCode;
string[] sourceFiles = Directory.GetFiles(source, "*", SearchOption.AllDirectories);
logger.LogInformation("Found {files}(s)", sourceFiles.Length);
int sourceLength = source.Length;
foreach (string sourceFile in sourceFiles)
{
fileInfo = new(sourceFile);
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);
if (fileInfo.Directory is null)
throw new NotSupportedException();
if (option == "Padded")
{
if (fileNameWithoutExtension.Length < intMinValueLength)
continue;
key = fileNameWithoutExtension;
if (recordB.PaddedTo.TryGetValue(key, out identifier))
{
recordACollection.Add(new($"{destination}{fileInfo.Directory.FullName[sourceLength..]}", fileInfo.Extension, fileInfo.FullName, identifier));
continue;
}
}
if (option == "Length")
{
if (recordB.LengthTo.TryGetValue(fileInfo.Length, out identifier))
{
checkDirectory = $"{destination}{fileInfo.Directory.FullName[sourceLength..]}";
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
checkFile = Path.Combine(checkDirectory, $"{identifier.PaddedId}{fileInfo.Extension}");
if (File.Exists(checkFile))
continue;
File.Copy(fileInfo.FullName, checkFile);
logger.LogInformation("<{fileInfo.FullName}> was moved to <{checkFile}>", fileInfo.FullName, checkFile);
continue;
}
}
if (option == "Id")
{
if (int.TryParse(fileNameWithoutExtension, out id))
{
if (recordB.IdTo.TryGetValue(id, out identifier))
{
checkDirectory = $"{destination}{fileInfo.Directory.FullName[sourceLength..]}";
if (!Directory.Exists(checkDirectory))
_ = Directory.CreateDirectory(checkDirectory);
checkFile = Path.Combine(checkDirectory, $"{identifier.PaddedId}{fileInfo.Extension}");
if (File.Exists(checkFile))
continue;
File.Move(fileInfo.FullName, checkFile);
logger.LogInformation("<{fileInfo.FullName}> was moved to <{checkFile}>", fileInfo.FullName, checkFile);
continue;
}
}
}
}
if (option == "Padded")
{
if (!isOffsetDeterministicHashCode)
recordACollection = (from l in recordACollection orderby l.Identifier.Ticks select l).ToList();
for (int i = 0; i < recordACollection.Count; i++)
{
recordA = recordACollection[i];
if (!Directory.Exists(recordA.Directory))
_ = Directory.CreateDirectory(recordA.Directory);
checkFile = Path.Combine(recordA.Directory, isOffsetDeterministicHashCode ? $"{recordA.Identifier.PaddedId}{recordA.Extension}" : $"{offset + i}{recordA.Identifier.PaddedId}{recordA.Extension}");
if (File.Exists(checkFile))
continue;
File.Move(recordA.SourceFile, checkFile);
logger.LogInformation("<{recordA.SourceFile}> was moved to <{checkFile}>", recordA.SourceFile, checkFile);
}
}
HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, source);
}
}

View File

@ -0,0 +1,206 @@
using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240623
{
private record SubTaskLine(string Text, bool Done, long? Ticks, int? Line);
private record Record(int? CodeInsidersLine, string File, string[] Lines, int? StopLine, int? SubTasksLine);
private static List<Record> GetRecords(string sourceDirectory, string searchPattern, string codeInsiders, string subTasks)
{
List<Record> results = [];
int? stopLine;
string[] lines;
int? subTasksLine;
int? codeInsidersLine;
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
foreach (string file in files)
{
stopLine = null;
subTasksLine = null;
codeInsidersLine = null;
lines = File.ReadAllLines(file);
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].StartsWith(codeInsiders) && lines[i][^1] == '"')
{
if (lines.Length > i + 1 && lines[i + 1] == "```")
codeInsidersLine = i;
}
if (lines[i] != subTasks)
continue;
subTasksLine = i;
if (codeInsidersLine is null)
break;
if (lines.Length > i)
{
for (int j = i + 1; j < lines.Length; j++)
{
if (lines[j].Length > 0 && lines[j][0] == '#')
{
stopLine = j;
break;
}
}
}
stopLine ??= lines.Length;
break;
}
results.Add(new(codeInsidersLine, file, lines, stopLine, subTasksLine));
}
return results;
}
private static ReadOnlyCollection<SubTaskLine> GetSubTasks(string subTasks, string[] tasks, bool? foundDone, string fallbackLine, FileInfo fileInfo)
{
List<SubTaskLine> results = [];
string line;
bool doneValue;
string? h1 = null;
bool foundSubTasks = false;
int tasksZeroLength = tasks[0].Length;
string[] lines = File.ReadAllLines(fileInfo.FullName);
for (int i = 0; i < lines.Length; i++)
{
line = lines[i];
if (line.StartsWith("# "))
h1 = line[2..];
if (!foundSubTasks && line == subTasks)
foundSubTasks = true;
if (!foundSubTasks)
continue;
if (line.Length <= tasksZeroLength || !line.StartsWith(tasks[0]) || line[tasksZeroLength] is not ' ' and not 'x' || line[tasksZeroLength + 1] != ']')
continue;
doneValue = foundDone is not null && foundDone.Value;
results.Add(new($" {line}", doneValue, fileInfo.LastWriteTime.Ticks, i));
}
doneValue = foundDone is not null && foundDone.Value;
if (h1 is null)
results.Add(new(fallbackLine, doneValue, fileInfo.LastWriteTime.Ticks, Line: null));
else
results.Add(new(foundDone is null || !foundDone.Value ? $"- [ ] {fileInfo.LastWriteTime.Ticks} ~~~ {h1}" : $"- [x] {fileInfo.LastWriteTime.Ticks} ~~~ {h1}", doneValue, fileInfo.LastWriteTime.Ticks, Line: 0));
return new(results);
}
internal static void UpdateSubTasksInMarkdownFiles(ILogger<Worker> logger, List<string> args)
{
int lineCheck;
bool doneValue;
bool? foundDone;
FileInfo fileInfo;
string[] newLines;
string[] segments;
List<string> lines;
string fallbackLine;
string[] indexLines;
string checkDirectory;
string done = args[7];
List<string> indexFiles;
string subTasks = args[3];
List<string> oldLines = [];
string indexFile = args[5];
string searchPattern = args[2];
string directoryFilter = args[8];
string[] tasks = args[6].Split(',');
string codeInsiders = $"{args[4]} \"";
List<SubTaskLine> allSubTaskLines = [];
ReadOnlyCollection<SubTaskLine> subTaskLines;
string sourceDirectory = Path.GetFullPath(args[0]);
List<Record> records = GetRecords(sourceDirectory, searchPattern, codeInsiders, subTasks);
foreach (Record record in from l in records orderby l.SubTasksLine is null, l.CodeInsidersLine is null select l)
{
if (record.SubTasksLine is null)
continue;
if (record.CodeInsidersLine is not null)
logger.LogInformation("<{file}> has [{subTasks}]", Path.GetFileNameWithoutExtension(record.File), subTasks);
else
{
logger.LogWarning("<{file}> has [{subTasks}] but doesn't have [{codeInsiders}]!", Path.GetFileNameWithoutExtension(record.File), subTasks, codeInsiders);
continue;
}
if (record.StopLine is null)
continue;
checkDirectory = record.Lines[record.CodeInsidersLine.Value][codeInsiders.Length..^1];
if (!Directory.Exists(checkDirectory))
{
logger.LogError("<{checkDirectory}> doesn't exist", Path.GetFileName(checkDirectory));
continue;
}
indexFiles = Directory.GetFiles(checkDirectory, indexFile, SearchOption.AllDirectories).ToList();
if (indexFiles.Count != 1)
{
for (int i = indexFiles.Count - 1; i > -1; i--)
{
if (!indexFiles[i].Contains(directoryFilter, StringComparison.CurrentCultureIgnoreCase))
indexFiles.RemoveAt(i);
}
if (indexFiles.Count != 1)
{
logger.LogError("<{checkDirectory}> doesn't have a [{indexFile}]", Path.GetFileName(checkDirectory), indexFile);
continue;
}
}
foundDone = null;
oldLines.Clear();
allSubTaskLines.Clear();
indexLines = File.ReadAllLines(indexFiles[0]);
checkDirectory = Path.GetDirectoryName(indexFiles[0]) ?? throw new Exception();
for (int i = 0; i < indexLines.Length; i++)
{
if (indexLines[i] == done)
foundDone = true;
segments = indexLines[i].Split(tasks[1]);
doneValue = foundDone is not null && foundDone.Value;
if (segments.Length > 2 || !segments[0].StartsWith(tasks[0]))
continue;
fallbackLine = foundDone is null || !foundDone.Value ? $"- [ ] {segments[0][tasks[0].Length..]}" : $"- [x] {segments[0][tasks[0].Length..]}";
fileInfo = new(Path.GetFullPath(Path.Combine(checkDirectory, segments[1][..^1])));
if (!fileInfo.Exists)
{
allSubTaskLines.Add(new(fallbackLine, doneValue, Ticks: null, Line: null));
continue;
}
subTaskLines = GetSubTasks(subTasks, tasks, doneValue, fallbackLine, fileInfo);
for (int j = subTaskLines.Count - 1; j >= 0; j--)
allSubTaskLines.Add(subTaskLines[j]);
}
if (allSubTaskLines.Count == 0)
continue;
lineCheck = 0;
for (int i = record.SubTasksLine.Value + 1; i < record.StopLine.Value - 1; i++)
oldLines.Add(record.Lines[i]);
if (allSubTaskLines.Any(l => l.Ticks is null))
newLines = (from l in allSubTaskLines select l.Text).ToArray();
else
newLines = (from l in allSubTaskLines orderby l.Done descending, l.Ticks, l.Line select l.Text).ToArray();
if (newLines.Length == oldLines.Count)
{
for (int i = 0; i < newLines.Length; i++)
{
if (newLines[i] != record.Lines[record.SubTasksLine.Value + 1 + i])
continue;
lineCheck++;
}
if (lineCheck == newLines.Length)
continue;
}
checkDirectory = Path.Combine(checkDirectory, DateTime.Now.Ticks.ToString());
_ = Directory.CreateDirectory(checkDirectory);
Thread.Sleep(500);
Directory.Delete(checkDirectory);
lines = record.Lines.ToList();
for (int i = record.StopLine.Value - 1; i > record.SubTasksLine.Value + 1; i--)
lines.RemoveAt(i);
if (record.StopLine.Value == record.Lines.Length && lines[^1].Length == 0)
lines.RemoveAt(lines.Count - 1);
for (int i = 0; i < newLines.Length; i++)
lines.Insert(record.SubTasksLine.Value + 1 + i, newLines[i]);
lines.Insert(record.SubTasksLine.Value + 1, string.Empty);
File.WriteAllLines(record.File, lines);
}
}
}

View File

@ -0,0 +1,88 @@
using Microsoft.Extensions.Logging;
namespace File_Folder_Helper.Day.Q22024;
internal static partial class Helper20240624
{
private static void MoveUpOndDirectory(ILogger<Worker> logger, string sourceDirectory, string[] files)
{
string? match;
string checkFile;
FileInfo fileInfoA;
FileInfo fileInfoB;
string? checkDirectory;
List<string> deleteFiles = [];
Dictionary<string, string> keyValuePairs = [];
foreach (string file in files)
{
checkDirectory = Path.GetDirectoryName(Path.GetDirectoryName(file)) ?? throw new NotSupportedException();
checkFile = Path.Combine(checkDirectory, Path.GetFileName(file));
if (File.Exists(checkFile))
throw new NotSupportedException();
if (keyValuePairs.TryGetValue(checkFile, out match))
{
fileInfoA = new(file);
fileInfoB = new(match);
if (fileInfoA.Length != fileInfoB.Length)
throw new NotSupportedException("Files don't match!");
logger.LogWarning("<{file}> already exists!", file);
deleteFiles.Add(file);
continue;
}
keyValuePairs.Add(checkFile, file);
}
foreach (string file in deleteFiles)
File.Delete(file);
foreach (KeyValuePair<string, string> keyValuePair in keyValuePairs)
File.Move(keyValuePair.Value, keyValuePair.Key);
Helpers.HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, sourceDirectory);
}
private static void Distinct(List<string> args, string sourceDirectory, string[] deleteMatchingIdsDirectoryNames, string[] files)
{
string fileName;
string directory;
List<string> distinct = [];
List<string> duplicate = [];
string[] keepMatchingIdsDirectoryNames = args[4].Split(',');
if (deleteMatchingIdsDirectoryNames.Length != keepMatchingIdsDirectoryNames.Length)
throw new NotSupportedException("Check arg lengths!");
string[] keepMatchingIdsDirectories = keepMatchingIdsDirectoryNames.Select(l => Path.Combine(sourceDirectory, l)).ToArray();
string[] deleteMatchingIdsDirectories = deleteMatchingIdsDirectoryNames.Select(l => Path.Combine(sourceDirectory, l)).ToArray();
foreach (string file in files)
{
fileName = Path.GetFileName(file);
if (distinct.Contains(fileName))
{
duplicate.Add(fileName);
continue;
}
distinct.Add(Path.GetFileName(file));
}
foreach (string file in files)
{
fileName = Path.GetFileName(file);
directory = Path.GetDirectoryName(file) ?? throw new NotSupportedException();
if (!duplicate.Contains(fileName))
continue;
if (deleteMatchingIdsDirectories.Contains(directory))
File.Move(file, $"{file}.del");
else if (!keepMatchingIdsDirectories.Contains(directory))
throw new NotSupportedException($"Missing <{Path.GetFileName(directory)}> as a directory for {fileName}");
}
}
internal static void MoveUpOneDirectory(ILogger<Worker> logger, List<string> args)
{
string searchPattern = args[2];
string sourceDirectory = Path.GetFullPath(args[0]);
string[] deleteMatchingIdsDirectoryNames = args[3].Split(',');
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
if (deleteMatchingIdsDirectoryNames.Length == 0)
MoveUpOndDirectory(logger, sourceDirectory, files);
else
Distinct(args, sourceDirectory, deleteMatchingIdsDirectoryNames, files);
}
}