4 Commits

Author SHA1 Message Date
5fa0c98d05 Documentation how to create tasks #11 2023-06-09 11:26:51 +02:00
b166013770 resolves #13 Website: Clear previous results 2023-06-09 11:12:43 +02:00
02fe849046 Better downloadChapter selection 2023-06-09 11:06:18 +02:00
d42393c83a Website + API ability to download specific volumes 2023-06-08 19:53:05 +02:00
5 changed files with 97 additions and 31 deletions

View File

@ -36,6 +36,7 @@
<li> <li>
<a href="#getting-started">Getting Started</a> <a href="#getting-started">Getting Started</a>
<ul> <ul>
<li><a href="#prerequisites">Usage</a></li>
<li><a href="#prerequisites">Prerequisites</a></li> <li><a href="#prerequisites">Prerequisites</a></li>
</ul> </ul>
</li> </li>
@ -109,6 +110,28 @@ Download [docker-compose.yaml](https://git.bernloehr.eu/glax/Tranga/src/branch/m
Wherever you are mounting `/usr/share/Tranga-API` you also need to mount that same path + `/imageCache` in the webserver container. Wherever you are mounting `/usr/share/Tranga-API` you also need to mount that same path + `/imageCache` in the webserver container.
### Usage
There is two ways to download Mangas:
- Downloading everything and monitor for new Chapters
- Selecting specific Volumes/Chapters
On the website you add new tasks, by selecting the blue '+' field. Next select the connector/site you want to use, and enter a search term.
After pressing 'Search', the results will be presented below - this might, depending on the result-size, take a while.
Next select the publication and a new popup will open with two options:
- "Monitor" - Download all chapters and monitor for new ones
- "Download Chapter" - Download specific chapters only
When selecting `Monitor` you will be presented with a new window and the selection of the interval you want to check for new chapters.
When selecting `Download Chapter` a list will open with all available chapters from which you can then select a range.
The syntax for selecting chapters is as follows:
- To download a single Chapter enter either the index number (the number at the very start of the line) or its absolute number like so: `c(h)(apter)[number]`, spaces are allowed.
- To download a range of chapters enter either a range of index numbers (`3-6`) or chapters (`ch 12-23`).
- For volumes the syntax is as follows: `v(ol)[number](-[number])`, again spaces allowed.
Examples: `2-12`, `c1`, `ch 2`, `chapter 3`, `v 2`, `vol3-4`, `v2c4` (note: you can only specify a single chapter with this syntax).
### Prerequisites ### Prerequisites
[.NET-Core 7.0 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/7.0) [.NET-Core 7.0 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/7.0)

View File

@ -119,21 +119,10 @@ app.MapPost("/Tasks/CreateDownloadChaptersTask", (string connectorName, string i
if (publication is null) if (publication is null)
return; return;
Chapter[] availableChapters = connector.GetChapters((Publication)publication, language??"en");; IEnumerable<Chapter> toDownload = connector.SearchChapters((Publication)publication, chapters, language ?? "en");
foreach(Chapter chapter in toDownload)
if (chapters.Contains('-'))
{
int start = Convert.ToInt32(chapters.Split('-')[0]);
int end = Convert.ToInt32(chapters.Split('-')[1]) + 1;
foreach (Chapter chapter in availableChapters[start..end])
{
taskManager.AddTask(new DownloadChapterTask(TrangaTask.Task.DownloadChapter, connectorName,
(Publication)publication, chapter, "en"));
}
}
else
taskManager.AddTask(new DownloadChapterTask(TrangaTask.Task.DownloadChapter, connectorName, taskManager.AddTask(new DownloadChapterTask(TrangaTask.Task.DownloadChapter, connectorName,
(Publication)publication, availableChapters[Convert.ToInt32(chapters)], "en")); (Publication)publication, chapter, "en"));
}); });
app.MapDelete("/Tasks/Delete", (string taskType, string? connectorName, string? publicationId) => app.MapDelete("/Tasks/Delete", (string taskType, string? connectorName, string? publicationId) =>

View File

@ -499,22 +499,7 @@ public static class Tranga_Cli
while(selectedChapters is null || selectedChapters.Length < 1) while(selectedChapters is null || selectedChapters.Length < 1)
selectedChapters = Console.ReadLine(); selectedChapters = Console.ReadLine();
if (selectedChapters.Length == 1 && selectedChapters.ToLower() == "q") return connector.SearchChapters(publication, selectedChapters);
{
Console.Clear();
Console.WriteLine("aborted.");
logger.WriteLine("Tranga_CLI", "aborted.");
return Array.Empty<Chapter>();
}
if (selectedChapters.Contains('-'))
{
int start = Convert.ToInt32(selectedChapters.Split('-')[0]);
int end = Convert.ToInt32(selectedChapters.Split('-')[1]) + 1;
return availableChapters[start..end];
}
else
return new Chapter[] { availableChapters[Convert.ToInt32(selectedChapters)] };
} }
private static Connector? SelectConnector(Connector[] connectors, Logger logger) private static Connector? SelectConnector(Connector[] connectors, Logger logger)

View File

@ -54,6 +54,72 @@ public abstract class Connector
/// <returns>Array of Chapters matching Publication and Language</returns> /// <returns>Array of Chapters matching Publication and Language</returns>
public abstract Chapter[] GetChapters(Publication publication, string language = ""); public abstract Chapter[] GetChapters(Publication publication, string language = "");
public Chapter[] SearchChapters(Publication publication, string searchTerm, string? language = null)
{
Chapter[] availableChapters = this.GetChapters(publication, language??"en");
Regex volumeRegex = new ("((v(ol)*(olume)*)+ *([0-9]+(-[0-9]+)?){1})", RegexOptions.IgnoreCase);
Regex chapterRegex = new ("((c(h)*(hapter)*)+ *([0-9]+(-[0-9]+)?){1})", RegexOptions.IgnoreCase);
Regex singleResultRegex = new("([0-9]+)", RegexOptions.IgnoreCase);
Regex rangeResultRegex = new("([0-9]+(-[0-9]+))", RegexOptions.IgnoreCase);
if (volumeRegex.IsMatch(searchTerm) && chapterRegex.IsMatch(searchTerm))
{
string volume = singleResultRegex.Match(volumeRegex.Match(searchTerm).Value).Value;
string chapter = singleResultRegex.Match(chapterRegex.Match(searchTerm).Value).Value;
return availableChapters.Where(aCh => aCh.volumeNumber is not null && aCh.chapterNumber is not null &&
aCh.volumeNumber.Equals(volume, StringComparison.InvariantCultureIgnoreCase) &&
aCh.chapterNumber.Equals(chapter, StringComparison.InvariantCultureIgnoreCase))
.ToArray();
}
else if (volumeRegex.IsMatch(searchTerm))
{
string volume = volumeRegex.Match(searchTerm).Value;
if (rangeResultRegex.IsMatch(volume))
{
string range = rangeResultRegex.Match(volume).Value;
int start = Convert.ToInt32(range.Split('-')[0]);
int end = Convert.ToInt32(range.Split('-')[1]);
return availableChapters.Where(aCh => aCh.volumeNumber is not null &&
Convert.ToInt32(aCh.volumeNumber) >= start &&
Convert.ToInt32(aCh.volumeNumber) <= end).ToArray();
}
else if(singleResultRegex.IsMatch(volume))
return availableChapters.Where(aCh =>
aCh.volumeNumber is not null &&
aCh.volumeNumber.Equals(volume, StringComparison.InvariantCultureIgnoreCase)).ToArray();
}
else if (chapterRegex.IsMatch(searchTerm))
{
string chapter = volumeRegex.Match(searchTerm).Value;
if (rangeResultRegex.IsMatch(chapter))
{
string range = rangeResultRegex.Match(chapter).Value;
int start = Convert.ToInt32(range.Split('-')[0]);
int end = Convert.ToInt32(range.Split('-')[1]);
return availableChapters.Where(aCh => aCh.chapterNumber is not null &&
Convert.ToInt32(aCh.chapterNumber) >= start &&
Convert.ToInt32(aCh.chapterNumber) <= end).ToArray();
}
else if(singleResultRegex.IsMatch(chapter))
return availableChapters.Where(aCh =>
aCh.chapterNumber is not null &&
aCh.chapterNumber.Equals(chapter, StringComparison.InvariantCultureIgnoreCase)).ToArray();
}
else
{
if (rangeResultRegex.IsMatch(searchTerm))
{
int start = Convert.ToInt32(searchTerm.Split('-')[0]);
int end = Convert.ToInt32(searchTerm.Split('-')[1]);
return availableChapters[start..(end + 1)];
}
else if(singleResultRegex.IsMatch(searchTerm))
return new [] { availableChapters[Convert.ToInt32(searchTerm)] };
}
return Array.Empty<Chapter>();
}
/// <summary> /// <summary>
/// Retrieves the Chapter (+Images) from the website. /// Retrieves the Chapter (+Images) from the website.
/// Should later call DownloadChapterImages to retrieve the individual Images of the Chapter and create .cbz archive. /// Should later call DownloadChapterImages to retrieve the individual Images of the Chapter and create .cbz archive.

View File

@ -63,7 +63,7 @@ createMonitorTaskButton.addEventListener("click", () => {
createDownloadChapterTaskButton.addEventListener("click", () => { createDownloadChapterTaskButton.addEventListener("click", () => {
HidePublicationPopup(); HidePublicationPopup();
OpenDownloadChapterTaskPopup(); OpenDownloadChapterTaskPopup();
}) });
publicationTaskStart.addEventListener("click", () => StartTaskClick()); publicationTaskStart.addEventListener("click", () => StartTaskClick());
settingApiUri.addEventListener("keypress", (event) => { settingApiUri.addEventListener("keypress", (event) => {
if(event.key === "Enter"){ if(event.key === "Enter"){
@ -156,6 +156,8 @@ function AddMonitorTask(){
} }
function OpenDownloadChapterTaskPopup(){ function OpenDownloadChapterTaskPopup(){
selectedChapters.value = "";
chapterOutput.replaceChildren();
createDownloadChaptersTask.style.display = "block"; createDownloadChaptersTask.style.display = "block";
GetChapters(toEditId, connectorSelect.value, "en").then((json) => { GetChapters(toEditId, connectorSelect.value, "en").then((json) => {
var i = 0; var i = 0;
@ -261,6 +263,7 @@ function HidePublicationPopup(){
function ShowNewTaskWindow(){ function ShowNewTaskWindow(){
selectPublication.replaceChildren(); selectPublication.replaceChildren();
searchPublicationQuery.value = "";
selectPublicationPopup.style.display = "flex"; selectPublicationPopup.style.display = "flex";
} }