using System.Diagnostics; using System.Reflection; using Microsoft.Extensions.DependencyInjection; AnsiConsole.Write(new FigletText("Welcome to OF-DL").Color(Color.Red)); ServiceCollection services = await ConfigureServices(args); ServiceProvider serviceProvider = services.BuildServiceProvider(); ExitIfOtherProcess(serviceProvider); Worker worker = serviceProvider.GetRequiredService(); await worker.RunAsync(); static async Task ConfigureServices(string[] args) { // Set up dependency injection with LoggingService and ConfigService ServiceCollection services = new(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(new ExitHelper(new SpectreDownloadEventHandler())); ServiceProvider tempServiceProvider = services.BuildServiceProvider(); ILoggingService loggingService = tempServiceProvider.GetRequiredService(); IConfigService configService = tempServiceProvider.GetRequiredService(); ExitHelper exitHelper = tempServiceProvider.GetRequiredService(); if (!await configService.LoadConfigurationAsync(args)) { AnsiConsole.MarkupLine("\n[red]config.conf is not valid, check your syntax![/]\n"); AnsiConsole.MarkupLine("[red]Press any key to exit.[/]"); Console.ReadKey(); exitHelper.ExitWithCode(3); } if (configService.CurrentConfig.NonInteractiveMode is false) { AnsiConsole.MarkupLine("\n[red]Cannot run in Interactive Mode![/]\n"); AnsiConsole.MarkupLine("[red]Press any key to exit.[/]"); Console.ReadKey(); exitHelper.ExitWithCode(3); } AnsiConsole.Markup("[green]config.conf located successfully!\n[/]"); if (!ParseCommandlineArgs(args, configService.CurrentConfig, out CajetanConfig cajetanConfig)) { AnsiConsole.MarkupLine($"\n[red]{cajetanConfig.ErrorMessage}[/]\n"); AnsiConsole.MarkupLine("[red]Press any key to exit.[/]"); Console.ReadKey(); exitHelper.ExitWithCode(3); } // Set up full dependency injection with loaded config services = []; services.AddSingleton(loggingService); services.AddSingleton(configService); services.AddSingleton(exitHelper); services.AddSingleton(cajetanConfig); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(sp => sp.GetRequiredService()); services.AddSingleton(); services.AddSingleton(sp => sp.GetRequiredService()); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); return services; } static bool ParseCommandlineArgs(string[] args, Config currentConfig, out CajetanConfig parsedConfig) { const string SPECIFIC_LISTS_ARG = "--specific-lists"; const string SPECIFIC_USERS_ARG = "--specific-users"; const string OUTPUT_BLOCKED_USERS_ARG = "--output-blocked"; const string UPDATE_ALL_USER_INFO_ARG = "--update-userinfo"; parsedConfig = new(); if (ParseListAndUserArguments(ref parsedConfig)) return true; if (ParseFlagArgument(OUTPUT_BLOCKED_USERS_ARG, EMode.OutputBlockedUsers, ref parsedConfig)) return true; if (ParseFlagArgument(UPDATE_ALL_USER_INFO_ARG, EMode.UpdateAllUserInfo, ref parsedConfig)) return true; parsedConfig.ErrorMessage = "No mode argument provided!"; return false; bool ParseListAndUserArguments(ref CajetanConfig parsedConfig) { bool hasSpecificListsArg = ParseCommaSeparatedListArgument(SPECIFIC_LISTS_ARG, ref parsedConfig, (c, v) => { c.NonInteractiveSpecificLists = v; Log.Logger = Log.Logger.ForContext(nameof(CajetanConfig.NonInteractiveSpecificLists), string.Join(",", v)); }); if (hasSpecificListsArg) return true; bool hasSpecificUsersArg = ParseCommaSeparatedListArgument(SPECIFIC_USERS_ARG, ref parsedConfig, (c, v) => { c.NonInteractiveSpecificUsers = v; Log.Logger = Log.Logger.ForContext(nameof(CajetanConfig.NonInteractiveSpecificUsers), string.Join(",", v)); }); if (hasSpecificUsersArg) return true; return false; } bool ParseCommaSeparatedListArgument(string argName, ref CajetanConfig parsedConfig, Action assignmentFunc) { char[] separator = [',']; int indexOfArg = Array.FindIndex(args, a => argName.Equals(a, StringComparison.OrdinalIgnoreCase)); if (indexOfArg < 0) return false; int indexOfListValues = indexOfArg + 1; string[] strListValues = args.ElementAtOrDefault(indexOfListValues)?.Split(separator, StringSplitOptions.RemoveEmptyEntries) ?? []; if (strListValues.Length == 0) return false; assignmentFunc(parsedConfig, strListValues); parsedConfig.Mode = EMode.DownloadCreatorContent; Log.Logger = Log.Logger.ForContext("Mode", $"{EMode.DownloadCreatorContent}"); return true; } bool ParseFlagArgument(string argName, EMode modeIfArgIsSet, ref CajetanConfig parsedConfig) { if (!args.Any(a => argName.Equals(a, StringComparison.OrdinalIgnoreCase))) return false; currentConfig.NonInteractiveMode = true; parsedConfig.Mode = modeIfArgIsSet; Log.Logger = Log.Logger.ForContext("Mode", $"{modeIfArgIsSet}"); return true; } } static void ExitIfOtherProcess(ServiceProvider serviceProvider) { Assembly? entryAssembly = Assembly.GetEntryAssembly(); AssemblyName? entryAssemblyName = entryAssembly?.GetName(); if (entryAssemblyName?.Name is null) return; Process thisProcess = Process.GetCurrentProcess(); Process[] otherProcesses = [.. Process.GetProcessesByName(entryAssemblyName.Name).Where(p => p.Id != thisProcess.Id)]; if (otherProcesses.Length <= 0) return; AnsiConsole.Markup($"[green]Other OF DL process detected, exiting..\n[/]"); Log.Warning("Other OF DL process detected, exiting.."); serviceProvider.GetRequiredService().ExitWithCode(0); }