From dd58efce06f92f9fa548092de1cb89d93faabd62 Mon Sep 17 00:00:00 2001 From: glax Date: Fri, 19 May 2023 16:27:56 +0200 Subject: [PATCH] Working TaskManager and Tasks --- Tranga-CLI/Tranga_Cli.cs | 195 ++++++++++++++++++++++++++++++++------- Tranga/TaskExecutor.cs | 12 ++- Tranga/TaskManager.cs | 36 ++++++-- Tranga/TrangaTask.cs | 17 ++-- 4 files changed, 207 insertions(+), 53 deletions(-) diff --git a/Tranga-CLI/Tranga_Cli.cs b/Tranga-CLI/Tranga_Cli.cs index c83f832..b21ac53 100644 --- a/Tranga-CLI/Tranga_Cli.cs +++ b/Tranga-CLI/Tranga_Cli.cs @@ -7,70 +7,198 @@ public static class Tranga_Cli { public static void Main(string[] args) { - Console.WriteLine("Output folder path (D:):"); + Console.WriteLine("Output folder path [standard D:]:"); string? folderPath = Console.ReadLine(); while(folderPath is null ) folderPath = Console.ReadLine(); if (folderPath.Length < 1) folderPath = "D:"; - DownloadNow(folderPath); + Console.Write("Mode (D: downloadNow, T: tasks):"); + ConsoleKeyInfo mode = Console.ReadKey(); + while (mode.Key != ConsoleKey.D && mode.Key != ConsoleKey.T) + mode = Console.ReadKey(); + Console.WriteLine(); + + if(mode.Key == ConsoleKey.D) + DownloadNow(folderPath); + else if (mode.Key == ConsoleKey.T) + TaskMode(folderPath); + } + + private static void TaskMode(string folderPath) + { + TaskManager taskManager = new TaskManager(folderPath); + ConsoleKey selection = ConsoleKey.NoName; + int menu = 0; + while (selection != ConsoleKey.Escape && selection != ConsoleKey.Q) + { + switch (menu) + { + case 1: + PrintTasks(taskManager); + Console.WriteLine("Press any key."); + Console.ReadKey(); + menu = 0; + break; + case 2: + Connector connector = SelectConnector(folderPath, taskManager.GetAvailableConnectors().Values.ToArray()); + TrangaTask.Task task = SelectTask(); + Publication? publication = null; + if(task != TrangaTask.Task.UpdatePublications) + publication = SelectPublication(connector); + TimeSpan reoccurrence = SelectReoccurence(); + taskManager.AddTask(task, connector, publication, reoccurrence, "en"); + Console.WriteLine($"{task} - {connector.name} - {publication?.sortName}"); + Console.WriteLine("Press any key."); + Console.ReadKey(); + menu = 0; + break; + case 3: + RemoveTask(taskManager); + Console.WriteLine("Press any key."); + Console.ReadKey(); + menu = 0; + break; + default: + selection = Menu(folderPath); + switch (selection) + { + case ConsoleKey.L: + menu = 1; + break; + case ConsoleKey.C: + menu = 2; + break; + case ConsoleKey.D: + menu = 3; + break; + default: + menu = 0; + break; + } + break; + } + } + taskManager.Shutdown(); + } + + private static ConsoleKey Menu(string folderPath) + { + Console.Clear(); + Console.WriteLine($"Download Folder: {folderPath}"); + Console.WriteLine("Select Option:"); + Console.WriteLine("L: List tasks"); + Console.WriteLine("C: Create Task"); + Console.WriteLine("D: Delete Task"); + Console.WriteLine("Q: Exit with saving"); + ConsoleKey selection = Console.ReadKey().Key; + Console.WriteLine(); + return selection; + } + + private static int PrintTasks(TaskManager taskManager) + { + Console.Clear(); + TrangaTask[] tasks = taskManager.GetAllTasks(); + int tIndex = 0; + Console.WriteLine("Tasks:"); + foreach(TrangaTask trangaTask in tasks) + Console.WriteLine($"{tIndex++}: {trangaTask.task} - {trangaTask.publication?.sortName} - {trangaTask.connectorName}"); + return tasks.Length; + } + + private static void RemoveTask(TaskManager taskManager) + { + int length = PrintTasks(taskManager); + + TrangaTask[] tasks = taskManager.GetAllTasks(); + Console.WriteLine($"Select Task (0-{length - 1}:"); + + string? selectedTask = Console.ReadLine(); + while(selectedTask is null || selectedTask.Length < 1) + selectedTask = Console.ReadLine(); + int selectedTaskIndex = Convert.ToInt32(selectedTask); + + taskManager.RemoveTask(tasks[selectedTaskIndex].task, tasks[selectedTaskIndex].connectorName, tasks[selectedTaskIndex].publication); + } + + private static TrangaTask.Task SelectTask() + { + Console.Clear(); + string[] taskNames = Enum.GetNames(); + + int tIndex = 0; + Console.WriteLine("Available Tasks:"); + foreach (string taskName in taskNames) + Console.WriteLine($"{tIndex++}: {taskName}"); + Console.WriteLine($"Select Task (0-{taskNames.Length - 1}):"); + + string? selectedTask = Console.ReadLine(); + while(selectedTask is null || selectedTask.Length < 1) + selectedTask = Console.ReadLine(); + int selectedTaskIndex = Convert.ToInt32(selectedTask); + + string selectedTaskName = taskNames[selectedTaskIndex]; + return Enum.Parse(selectedTaskName); + } + + private static TimeSpan SelectReoccurence() + { + return TimeSpan.FromSeconds(30); //TODO } private static void DownloadNow(string folderPath) { Connector connector = SelectConnector(folderPath); - Console.WriteLine("Search query (leave empty for all):"); - string? query = Console.ReadLine(); - - Publication[] publications = connector.GetPublications(query ?? ""); - Publication selectedPub = SelectPublication(publications); + Publication publication = SelectPublication(connector); - Chapter[] allChapteres = connector.GetChapters(selectedPub, "en"); - Chapter[] downloadChapters = SelectChapters(allChapteres); + Chapter[] downloadChapters = SelectChapters(connector, publication); if (downloadChapters.Length > 0) { - connector.DownloadCover(selectedPub); - File.WriteAllText(Path.Join(folderPath, selectedPub.folderName, "series.json"),selectedPub.GetSeriesInfo()); + connector.DownloadCover(publication); + connector.SaveSeriesInfo(publication); } foreach (Chapter chapter in downloadChapters) { - Console.WriteLine($"Downloading {selectedPub.sortName} V{chapter.volumeNumber}C{chapter.chapterNumber}"); - connector.DownloadChapter(selectedPub, chapter); + Console.WriteLine($"Downloading {publication.sortName} V{chapter.volumeNumber}C{chapter.chapterNumber}"); + connector.DownloadChapter(publication, chapter); } } - private static Connector SelectConnector(string folderPath) + private static Connector SelectConnector(string folderPath, Connector[]? availableConnectors = null) { - Console.WriteLine("Select Connector:"); - Console.WriteLine("0: MangaDex"); + Console.Clear(); + Connector[] connectors = availableConnectors ?? new Connector[] { new MangaDex(folderPath) }; + + int cIndex = 0; + Console.WriteLine("Connectors:"); + foreach (Connector connector in connectors) + Console.WriteLine($"{cIndex++}: {connector.name}"); + Console.WriteLine($"Select Connector (0-{connectors.Length - 1}):"); string? selectedConnector = Console.ReadLine(); while(selectedConnector is null || selectedConnector.Length < 1) selectedConnector = Console.ReadLine(); int selectedConnectorIndex = Convert.ToInt32(selectedConnector); - - Connector connector; - switch (selectedConnectorIndex) - { - case 0: - connector = new MangaDex(folderPath); - break; - default: - connector = new MangaDex(folderPath); - break; - } - - return connector; + + return connectors[selectedConnectorIndex]; } - private static Publication SelectPublication(Publication[] publications) + private static Publication SelectPublication(Connector connector) { + Console.Clear(); + Console.WriteLine($"Connector: {connector.name}"); + Console.WriteLine("Publication search query (leave empty for all):"); + string? query = Console.ReadLine(); + + Publication[] publications = connector.GetPublications(query ?? ""); int pIndex = 0; + Console.WriteLine("Publications:"); foreach(Publication publication in publications) Console.WriteLine($"{pIndex++}: {publication.sortName}"); Console.WriteLine($"Select publication to Download (0-{publications.Length - 1}):"); @@ -81,9 +209,14 @@ public static class Tranga_Cli return publications[Convert.ToInt32(selected)]; } - private static Chapter[] SelectChapters(Chapter[] chapters) + private static Chapter[] SelectChapters(Connector connector, Publication publication) { + Console.Clear(); + Console.WriteLine($"Connector: {connector.name} Publication: {publication.sortName}"); + Chapter[] chapters = connector.GetChapters(publication, "en"); + int cIndex = 0; + Console.WriteLine("Chapters:"); foreach (Chapter ch in chapters) { string name = cIndex.ToString(); diff --git a/Tranga/TaskExecutor.cs b/Tranga/TaskExecutor.cs index dd4bd77..07111c5 100644 --- a/Tranga/TaskExecutor.cs +++ b/Tranga/TaskExecutor.cs @@ -2,18 +2,22 @@ public static class TaskExecutor { - public static void Execute(TrangaTask trangaTask, Dictionary> chapterCollection) + public static void Execute(Connector[] connectors, TrangaTask trangaTask, Dictionary> chapterCollection) { + Connector? connector = connectors.FirstOrDefault(c => c.name == trangaTask.connectorName); + if (connector is null) + throw new ArgumentException($"Connector {trangaTask.connectorName} is not a known connector."); + switch (trangaTask.task) { case TrangaTask.Task.DownloadNewChapters: - DownloadNewChapters(trangaTask.connector, trangaTask.publication, trangaTask.language, chapterCollection); + DownloadNewChapters(connector, (Publication)trangaTask.publication!, trangaTask.language, chapterCollection); break; case TrangaTask.Task.UpdateChapters: - UpdateChapters(trangaTask.connector, trangaTask.publication, trangaTask.language, chapterCollection); + UpdateChapters(connector, (Publication)trangaTask.publication!, trangaTask.language, chapterCollection); break; case TrangaTask.Task.UpdatePublications: - UpdatePublications(trangaTask.connector, chapterCollection); + UpdatePublications(connector, chapterCollection); break; } } diff --git a/Tranga/TaskManager.cs b/Tranga/TaskManager.cs index e50f991..a9e70ea 100644 --- a/Tranga/TaskManager.cs +++ b/Tranga/TaskManager.cs @@ -8,9 +8,13 @@ public class TaskManager private readonly Dictionary> _chapterCollection; private readonly HashSet _allTasks; private bool _continueRunning = true; - - public TaskManager() + private readonly Connector[] connectors; + private readonly string folderPath; + + public TaskManager(string folderPath) { + this.folderPath = folderPath; + this.connectors = new Connector[]{ new MangaDex(folderPath) }; _chapterCollection = new(); _allTasks = ImportTasks(Directory.GetCurrentDirectory()); Thread taskChecker = new(TaskCheckerThread); @@ -21,29 +25,43 @@ public class TaskManager { while (_continueRunning) { - foreach (TrangaTask task in _allTasks.Where(trangaTask => trangaTask.ShouldExecute(true))) + foreach (TrangaTask task in _allTasks) { - TaskExecutor.Execute(task, this._chapterCollection); + if(task.ShouldExecute()) + TaskExecutor.Execute(this.connectors, task, this._chapterCollection); + task.lastExecuted = DateTime.Now; } Thread.Sleep(1000); } } - public bool AddTask(TrangaTask.Task task, Connector connector, Publication publication, TimeSpan reoccurrence, + public bool AddTask(TrangaTask.Task task, Connector connector, Publication? publication, TimeSpan reoccurrence, string language = "") { - if(!_allTasks.Any(trangaTask => trangaTask.task != task && trangaTask.publication.downloadUrl != publication.downloadUrl)) - return _allTasks.Add(new TrangaTask(connector, task, publication, reoccurrence, language)); + if(!_allTasks.Any(trangaTask => trangaTask.task != task && trangaTask.connectorName != connector.name && trangaTask.publication?.downloadUrl != publication?.downloadUrl)) + return _allTasks.Add(new TrangaTask(connector.name, task, publication, reoccurrence, language)); return false; } - public bool RemoveTask(TrangaTask.Task task, Publication publication) + public bool RemoveTask(TrangaTask.Task task, string connectorName, Publication? publication) { return (_allTasks.RemoveWhere(trangaTask => - trangaTask.task == task && trangaTask.publication.downloadUrl == publication.downloadUrl) + trangaTask.task == task && trangaTask.connectorName == connectorName && trangaTask.publication?.downloadUrl == publication?.downloadUrl) > 0); } + public Dictionary GetAvailableConnectors() + { + return this.connectors.ToDictionary(connector => connector.name, connector => connector); + } + + public TrangaTask[] GetAllTasks() + { + TrangaTask[] ret = new TrangaTask[_allTasks.Count]; + _allTasks.CopyTo(ret); + return ret; + } + public void Shutdown() { _continueRunning = false; diff --git a/Tranga/TrangaTask.cs b/Tranga/TrangaTask.cs index e0260b7..fe9af96 100644 --- a/Tranga/TrangaTask.cs +++ b/Tranga/TrangaTask.cs @@ -1,6 +1,6 @@ namespace Tranga; -public struct TrangaTask +public class TrangaTask { public TimeSpan reoccurrence { get; } public DateTime lastExecuted { get; set; } @@ -9,22 +9,21 @@ public struct TrangaTask public Publication? publication { get; } public string language { get; } - public TrangaTask(Connector connector, Task task, Publication publication, TimeSpan reoccurrence, string language = "") + public TrangaTask(string connectorName, Task task, Publication? publication, TimeSpan reoccurrence, string language = "") { + if (task != Task.UpdatePublications && publication is null) + throw new ArgumentException($"Publication has to be not null for task {task}"); + this.publication = publication; this.reoccurrence = reoccurrence; this.lastExecuted = DateTime.Now.Subtract(reoccurrence); - this.connector = connector; + this.connectorName = connectorName; this.task = task; - this.publication = publication; this.language = language; } - public bool ShouldExecute(bool willBeExecuted) + public bool ShouldExecute() { - bool ret = (DateTime.Now - lastExecuted) > reoccurrence; - if (ret && willBeExecuted) - lastExecuted = DateTime.Now; - return ret; + return DateTime.Now.Subtract(this.lastExecuted) > reoccurrence; } public enum Task