Compare commits
No commits in common. "9b2a6de8412ef0cb837cc4a186b361f3336ea7ac" and "1f24a2349dc03ea0aaf74743f2183dd91573736b" have entirely different histories.
9b2a6de841
...
1f24a2349d
@ -20,28 +20,20 @@ public readonly struct Chapter : IComparable
|
|||||||
|
|
||||||
private static readonly Regex LegalCharacters = new (@"([A-z]*[0-9]* *\.*-*,*\]*\[*'*\'*\)*\(*~*!*)*");
|
private static readonly Regex LegalCharacters = new (@"([A-z]*[0-9]* *\.*-*,*\]*\[*'*\'*\)*\(*~*!*)*");
|
||||||
private static readonly Regex IllegalStrings = new(@"Vol(ume)?.?", RegexOptions.IgnoreCase);
|
private static readonly Regex IllegalStrings = new(@"Vol(ume)?.?", RegexOptions.IgnoreCase);
|
||||||
private static readonly Regex Digits = new(@"[0-9\.]*");
|
|
||||||
public Chapter(Manga parentManga, string? name, string? volumeNumber, string chapterNumber, string url)
|
public Chapter(Manga parentManga, string? name, string? volumeNumber, string chapterNumber, string url)
|
||||||
{
|
{
|
||||||
this.parentManga = parentManga;
|
this.parentManga = parentManga;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.volumeNumber = volumeNumber is not null ? string.Concat(Digits.Matches(volumeNumber).Select(x => x.Value)) : "0";
|
this.volumeNumber = volumeNumber ?? "0";
|
||||||
this.chapterNumber = string.Concat(Digits.Matches(chapterNumber).Select(x => x.Value));
|
this.chapterNumber = chapterNumber;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
|
||||||
string chapterVolNumStr;
|
|
||||||
if (volumeNumber is not null && volumeNumber.Length > 0)
|
|
||||||
chapterVolNumStr = $"Vol.{volumeNumber} Ch.{chapterNumber}";
|
|
||||||
else
|
|
||||||
chapterVolNumStr = $"Ch.{chapterNumber}";
|
|
||||||
|
|
||||||
if (name is not null && name.Length > 0)
|
string chapterName = string.Concat(LegalCharacters.Matches(name ?? ""));
|
||||||
{
|
string volStr = volumeNumber is not null ? $"Vol.{volumeNumber} " : "";
|
||||||
string chapterName = IllegalStrings.Replace(string.Concat(LegalCharacters.Matches(name)), "");
|
string chNumberStr = $"Ch.{chapterNumber} ";
|
||||||
this.fileName = $"{chapterVolNumStr} - {chapterName}";
|
string chNameStr = chapterName.Length > 0 ? $"- {chapterName}" : "";
|
||||||
}
|
chNameStr = IllegalStrings.Replace(chNameStr, "");
|
||||||
else
|
this.fileName = $"{volStr}{chNumberStr}{chNameStr}";
|
||||||
this.fileName = chapterVolNumStr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@ -89,20 +81,23 @@ public readonly struct Chapter : IComparable
|
|||||||
/// <returns>true if chapter is present</returns>
|
/// <returns>true if chapter is present</returns>
|
||||||
internal bool CheckChapterIsDownloaded(string downloadLocation)
|
internal bool CheckChapterIsDownloaded(string downloadLocation)
|
||||||
{
|
{
|
||||||
|
string newFilePath = GetArchiveFilePath(downloadLocation);
|
||||||
if (!Directory.Exists(Path.Join(downloadLocation, parentManga.folderName)))
|
if (!Directory.Exists(Path.Join(downloadLocation, parentManga.folderName)))
|
||||||
return false;
|
return false;
|
||||||
FileInfo[] archives = new DirectoryInfo(Path.Join(downloadLocation, parentManga.folderName)).GetFiles();
|
FileInfo[] archives = new DirectoryInfo(Path.Join(downloadLocation, parentManga.folderName)).GetFiles();
|
||||||
Regex volChRex = new(@"(?:Vol(?:ume)?\.([0-9]+)\D*)?Ch(?:apter)?\.([0-9]+(?:\.[0-9]+)*)");
|
Regex chapterInfoRex = new(@"Ch\.[0-9.]+");
|
||||||
|
Regex chapterRex = new(@"[0-9]+(\.[0-9]+)?");
|
||||||
|
|
||||||
|
if (File.Exists(newFilePath))
|
||||||
|
return true;
|
||||||
|
|
||||||
Chapter t = this;
|
string cn = this.chapterNumber;
|
||||||
return archives.Select(archive => archive.Name).Any(archiveFileName =>
|
if (archives.FirstOrDefault(archive => chapterRex.Match(chapterInfoRex.Match(archive.Name).Value).Value == cn) is { } path)
|
||||||
{
|
{
|
||||||
Match m = volChRex.Match(archiveFileName);
|
File.Move(path.FullName, newFilePath);
|
||||||
string archiveVolNum = m.Groups[1].Success ? m.Groups[1].Value : "0";
|
return true;
|
||||||
string archiveChNum = m.Groups[2].Value;
|
}
|
||||||
return archiveVolNum == t.volumeNumber &&
|
return false;
|
||||||
archiveChNum == t.chapterNumber;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates full file path of chapter-archive
|
/// Creates full file path of chapter-archive
|
||||||
|
@ -38,9 +38,6 @@ public class JobJsonConverter : JsonConverter
|
|||||||
jo.GetValue("parentJobId")!.Value<string?>());
|
jo.GetValue("parentJobId")!.Value<string?>());
|
||||||
}else if ((jo.ContainsKey("jobType") && jo["jobType"]!.Value<byte>() == (byte)Job.JobType.DownloadNewChaptersJob) || jo.ContainsKey("translatedLanguage"))//TODO change to jobType
|
}else if ((jo.ContainsKey("jobType") && jo["jobType"]!.Value<byte>() == (byte)Job.JobType.DownloadNewChaptersJob) || jo.ContainsKey("translatedLanguage"))//TODO change to jobType
|
||||||
{
|
{
|
||||||
DateTime lastExecution = jo.GetValue("lastExecution") is {} le
|
|
||||||
? le.ToObject<DateTime>()
|
|
||||||
: DateTime.UnixEpoch; //TODO do null checks on all variables
|
|
||||||
return new DownloadNewChapters(this._clone,
|
return new DownloadNewChapters(this._clone,
|
||||||
jo.GetValue("mangaConnector")!.ToObject<MangaConnector>(JsonSerializer.Create(new JsonSerializerSettings()
|
jo.GetValue("mangaConnector")!.ToObject<MangaConnector>(JsonSerializer.Create(new JsonSerializerSettings()
|
||||||
{
|
{
|
||||||
@ -50,7 +47,7 @@ public class JobJsonConverter : JsonConverter
|
|||||||
}
|
}
|
||||||
}))!,
|
}))!,
|
||||||
jo.GetValue("manga")!.ToObject<Manga>(),
|
jo.GetValue("manga")!.ToObject<Manga>(),
|
||||||
lastExecution,
|
jo.GetValue("lastExecution")!.ToObject<DateTime>(),
|
||||||
jo.GetValue("recurring")!.Value<bool>(),
|
jo.GetValue("recurring")!.Value<bool>(),
|
||||||
jo.GetValue("recurrenceTime")!.ToObject<TimeSpan?>(),
|
jo.GetValue("recurrenceTime")!.ToObject<TimeSpan?>(),
|
||||||
jo.GetValue("parentJobId")!.Value<string?>());
|
jo.GetValue("parentJobId")!.Value<string?>());
|
||||||
|
@ -7,10 +7,12 @@ namespace Tranga.MangaConnectors;
|
|||||||
|
|
||||||
public class Bato : MangaConnector
|
public class Bato : MangaConnector
|
||||||
{
|
{
|
||||||
|
|
||||||
public Bato(GlobalBase clone) : base(clone, "Bato")
|
public Bato(GlobalBase clone) : base(clone, "Bato")
|
||||||
{
|
{
|
||||||
this.downloadClient = new HttpDownloadClient(clone);
|
this.downloadClient = new HttpDownloadClient(clone, new Dictionary<byte, int>()
|
||||||
|
{
|
||||||
|
{1, 60}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Manga[] GetManga(string publicationTitle = "")
|
public override Manga[] GetManga(string publicationTitle = "")
|
||||||
@ -19,7 +21,7 @@ public class Bato : MangaConnector
|
|||||||
string sanitizedTitle = string.Join(' ', Regex.Matches(publicationTitle, "[A-z]*").Where(m => m.Value.Length > 0)).ToLower();
|
string sanitizedTitle = string.Join(' ', Regex.Matches(publicationTitle, "[A-z]*").Where(m => m.Value.Length > 0)).ToLower();
|
||||||
string requestUrl = $"https://bato.to/v3x-search?word={sanitizedTitle}&lang=en";
|
string requestUrl = $"https://bato.to/v3x-search?word={sanitizedTitle}&lang=en";
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Manga>();
|
return Array.Empty<Manga>();
|
||||||
|
|
||||||
@ -41,7 +43,8 @@ public class Bato : MangaConnector
|
|||||||
|
|
||||||
public override Manga? GetMangaFromUrl(string url)
|
public override Manga? GetMangaFromUrl(string url)
|
||||||
{
|
{
|
||||||
RequestResult requestResult = downloadClient.MakeRequest(url, RequestType.MangaInfo);
|
RequestResult requestResult =
|
||||||
|
downloadClient.MakeRequest(url, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return null;
|
return null;
|
||||||
if (requestResult.htmlDocument is null)
|
if (requestResult.htmlDocument is null)
|
||||||
@ -86,7 +89,7 @@ public class Bato : MangaConnector
|
|||||||
|
|
||||||
string posterUrl = document.DocumentNode.SelectNodes("//img")
|
string posterUrl = document.DocumentNode.SelectNodes("//img")
|
||||||
.First(child => child.GetAttributeValue("data-hk", "") == "0-1-0").GetAttributeValue("src", "").Replace("&", "&");
|
.First(child => child.GetAttributeValue("data-hk", "") == "0-1-0").GetAttributeValue("src", "").Replace("&", "&");
|
||||||
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, RequestType.MangaCover);
|
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, 1);
|
||||||
|
|
||||||
List<HtmlNode> genreNodes = document.DocumentNode.SelectSingleNode("//b[text()='Genres:']/..").SelectNodes("span").ToList();
|
List<HtmlNode> genreNodes = document.DocumentNode.SelectSingleNode("//b[text()='Genres:']/..").SelectNodes("span").ToList();
|
||||||
string[] tags = genreNodes.Select(node => node.FirstChild.InnerText).ToArray();
|
string[] tags = genreNodes.Select(node => node.FirstChild.InnerText).ToArray();
|
||||||
@ -126,7 +129,7 @@ public class Bato : MangaConnector
|
|||||||
string requestUrl = $"https://bato.to/title/{manga.publicationId}";
|
string requestUrl = $"https://bato.to/title/{manga.publicationId}";
|
||||||
// Leaving this in for verification if the page exists
|
// Leaving this in for verification if the page exists
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Chapter>();
|
return Array.Empty<Chapter>();
|
||||||
|
|
||||||
@ -138,7 +141,7 @@ public class Bato : MangaConnector
|
|||||||
|
|
||||||
private List<Chapter> ParseChaptersFromHtml(Manga manga, string mangaUrl)
|
private List<Chapter> ParseChaptersFromHtml(Manga manga, string mangaUrl)
|
||||||
{
|
{
|
||||||
RequestResult result = downloadClient.MakeRequest(mangaUrl, RequestType.Default);
|
RequestResult result = downloadClient.MakeRequest(mangaUrl, 1);
|
||||||
if ((int)result.statusCode < 200 || (int)result.statusCode >= 300 || result.htmlDocument is null)
|
if ((int)result.statusCode < 200 || (int)result.statusCode >= 300 || result.htmlDocument is null)
|
||||||
{
|
{
|
||||||
Log("Failed to load site");
|
Log("Failed to load site");
|
||||||
@ -181,7 +184,7 @@ public class Bato : MangaConnector
|
|||||||
string requestUrl = chapter.url;
|
string requestUrl = chapter.url;
|
||||||
// Leaving this in to check if the page exists
|
// Leaving this in to check if the page exists
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
{
|
{
|
||||||
progressToken?.Cancel();
|
progressToken?.Cancel();
|
||||||
@ -193,13 +196,13 @@ public class Bato : MangaConnector
|
|||||||
string comicInfoPath = Path.GetTempFileName();
|
string comicInfoPath = Path.GetTempFileName();
|
||||||
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
||||||
|
|
||||||
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, "https://mangakatana.com/", progressToken:progressToken);
|
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, "https://mangakatana.com/", progressToken:progressToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string[] ParseImageUrlsFromHtml(string mangaUrl)
|
private string[] ParseImageUrlsFromHtml(string mangaUrl)
|
||||||
{
|
{
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(mangaUrl, RequestType.Default);
|
downloadClient.MakeRequest(mangaUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
{
|
{
|
||||||
return Array.Empty<string>();
|
return Array.Empty<string>();
|
||||||
|
@ -53,7 +53,7 @@ internal class ChromiumDownloadClient : DownloadClient
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChromiumDownloadClient(GlobalBase clone) : base(clone)
|
public ChromiumDownloadClient(GlobalBase clone, Dictionary<byte, int> rateLimitRequestsPerMinute) : base(clone, rateLimitRequestsPerMinute)
|
||||||
{
|
{
|
||||||
this.browser = DownloadBrowser().Result;
|
this.browser = DownloadBrowser().Result;
|
||||||
}
|
}
|
||||||
|
@ -5,29 +5,37 @@ namespace Tranga.MangaConnectors;
|
|||||||
|
|
||||||
internal abstract class DownloadClient : GlobalBase
|
internal abstract class DownloadClient : GlobalBase
|
||||||
{
|
{
|
||||||
private readonly Dictionary<RequestType, DateTime> _lastExecutedRateLimit;
|
private readonly Dictionary<byte, DateTime> _lastExecutedRateLimit;
|
||||||
|
private readonly Dictionary<byte, TimeSpan> _rateLimit;
|
||||||
|
|
||||||
protected DownloadClient(GlobalBase clone) : base(clone)
|
protected DownloadClient(GlobalBase clone, Dictionary<byte, int> rateLimitRequestsPerMinute) : base(clone)
|
||||||
{
|
{
|
||||||
this._lastExecutedRateLimit = new();
|
this._lastExecutedRateLimit = new();
|
||||||
|
_rateLimit = new();
|
||||||
|
foreach (KeyValuePair<byte, int> limit in rateLimitRequestsPerMinute)
|
||||||
|
_rateLimit.Add(limit.Key, TimeSpan.FromMinutes(1).Divide(limit.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetCustomRequestLimit(byte requestType, int limit)
|
||||||
|
{
|
||||||
|
if (_rateLimit.ContainsKey(requestType))
|
||||||
|
_rateLimit[requestType] = TimeSpan.FromMinutes(1).Divide(limit);
|
||||||
|
else
|
||||||
|
_rateLimit.Add(requestType, TimeSpan.FromMinutes(1).Divide(limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
public RequestResult MakeRequest(string url, RequestType requestType, string? referrer = null, string? clickButton = null)
|
public RequestResult MakeRequest(string url, byte requestType, string? referrer = null, string? clickButton = null)
|
||||||
{
|
{
|
||||||
if (!settings.requestLimits.ContainsKey(requestType))
|
if (_rateLimit.TryGetValue(requestType, out TimeSpan value))
|
||||||
|
_lastExecutedRateLimit.TryAdd(requestType, DateTime.Now.Subtract(value));
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Log("RequestType not configured for rate-limit.");
|
Log("RequestType not configured for rate-limit.");
|
||||||
return new RequestResult(HttpStatusCode.NotAcceptable, null, Stream.Null);
|
return new RequestResult(HttpStatusCode.NotAcceptable, null, Stream.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rateLimit = settings.userAgent == TrangaSettings.DefaultUserAgent
|
TimeSpan rateLimitTimeout = _rateLimit[requestType]
|
||||||
? TrangaSettings.DefaultRequestLimits[requestType]
|
.Subtract(DateTime.Now.Subtract(_lastExecutedRateLimit[requestType]));
|
||||||
: settings.requestLimits[requestType];
|
|
||||||
|
|
||||||
TimeSpan timeBetweenRequests = TimeSpan.FromMinutes(1).Divide(rateLimit);
|
|
||||||
_lastExecutedRateLimit.TryAdd(requestType, DateTime.Now.Subtract(timeBetweenRequests));
|
|
||||||
|
|
||||||
TimeSpan rateLimitTimeout = timeBetweenRequests.Subtract(DateTime.Now.Subtract(_lastExecutedRateLimit[requestType]));
|
|
||||||
|
|
||||||
if (rateLimitTimeout > TimeSpan.Zero)
|
if (rateLimitTimeout > TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,8 @@ internal class HttpDownloadClient : DownloadClient
|
|||||||
Timeout = TimeSpan.FromSeconds(10)
|
Timeout = TimeSpan.FromSeconds(10)
|
||||||
};
|
};
|
||||||
|
|
||||||
public HttpDownloadClient(GlobalBase clone) : base(clone)
|
|
||||||
|
public HttpDownloadClient(GlobalBase clone, Dictionary<byte, int> rateLimitRequestsPerMinute) : base(clone, rateLimitRequestsPerMinute)
|
||||||
{
|
{
|
||||||
Client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", settings.userAgent);
|
Client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", settings.userAgent);
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ public abstract class MangaConnector : GlobalBase
|
|||||||
/// <param name="fullPath"></param>
|
/// <param name="fullPath"></param>
|
||||||
/// <param name="requestType">RequestType for Rate-Limit</param>
|
/// <param name="requestType">RequestType for Rate-Limit</param>
|
||||||
/// <param name="referrer">referrer used in html request header</param>
|
/// <param name="referrer">referrer used in html request header</param>
|
||||||
private HttpStatusCode DownloadImage(string imageUrl, string fullPath, RequestType requestType, string? referrer = null)
|
private HttpStatusCode DownloadImage(string imageUrl, string fullPath, byte requestType, string? referrer = null)
|
||||||
{
|
{
|
||||||
RequestResult requestResult = downloadClient.MakeRequest(imageUrl, requestType, referrer);
|
RequestResult requestResult = downloadClient.MakeRequest(imageUrl, requestType, referrer);
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ public abstract class MangaConnector : GlobalBase
|
|||||||
return requestResult.statusCode;
|
return requestResult.statusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HttpStatusCode DownloadChapterImages(string[] imageUrls, string saveArchiveFilePath, RequestType requestType, string? comicInfoPath = null, string? referrer = null, ProgressToken? progressToken = null)
|
protected HttpStatusCode DownloadChapterImages(string[] imageUrls, string saveArchiveFilePath, byte requestType, string? comicInfoPath = null, string? referrer = null, ProgressToken? progressToken = null)
|
||||||
{
|
{
|
||||||
if (progressToken?.cancellationRequested ?? false)
|
if (progressToken?.cancellationRequested ?? false)
|
||||||
return HttpStatusCode.RequestTimeout;
|
return HttpStatusCode.RequestTimeout;
|
||||||
@ -274,7 +274,7 @@ public abstract class MangaConnector : GlobalBase
|
|||||||
return HttpStatusCode.OK;
|
return HttpStatusCode.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string SaveCoverImageToCache(string url, RequestType requestType)
|
protected string SaveCoverImageToCache(string url, byte requestType)
|
||||||
{
|
{
|
||||||
string filetype = url.Split('/')[^1].Split('?')[0].Split('.')[^1];
|
string filetype = url.Split('/')[^1].Split('?')[0].Split('.')[^1];
|
||||||
string filename = $"{DateTime.Now.Ticks.ToString()}.{filetype}";
|
string filename = $"{DateTime.Now.Ticks.ToString()}.{filetype}";
|
||||||
|
@ -7,9 +7,25 @@ using JsonSerializer = System.Text.Json.JsonSerializer;
|
|||||||
namespace Tranga.MangaConnectors;
|
namespace Tranga.MangaConnectors;
|
||||||
public class MangaDex : MangaConnector
|
public class MangaDex : MangaConnector
|
||||||
{
|
{
|
||||||
|
private enum RequestType : byte
|
||||||
|
{
|
||||||
|
Manga,
|
||||||
|
Feed,
|
||||||
|
AtHomeServer,
|
||||||
|
CoverUrl,
|
||||||
|
Author,
|
||||||
|
}
|
||||||
|
|
||||||
public MangaDex(GlobalBase clone) : base(clone, "MangaDex")
|
public MangaDex(GlobalBase clone) : base(clone, "MangaDex")
|
||||||
{
|
{
|
||||||
this.downloadClient = new HttpDownloadClient(clone);
|
this.downloadClient = new HttpDownloadClient(clone, new Dictionary<byte, int>()
|
||||||
|
{
|
||||||
|
{(byte)RequestType.Manga, 250},
|
||||||
|
{(byte)RequestType.Feed, 250},
|
||||||
|
{(byte)RequestType.AtHomeServer, 40},
|
||||||
|
{(byte)RequestType.CoverUrl, 250},
|
||||||
|
{(byte)RequestType.Author, 250}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Manga[] GetManga(string publicationTitle = "")
|
public override Manga[] GetManga(string publicationTitle = "")
|
||||||
@ -25,7 +41,7 @@ public class MangaDex : MangaConnector
|
|||||||
//Request next Page
|
//Request next Page
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(
|
downloadClient.MakeRequest(
|
||||||
$"https://api.mangadex.org/manga?limit={limit}&title={publicationTitle}&offset={offset}", RequestType.MangaInfo);
|
$"https://api.mangadex.org/manga?limit={limit}&title={publicationTitle}&offset={offset}", (byte)RequestType.Manga);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
break;
|
break;
|
||||||
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
||||||
@ -59,7 +75,7 @@ public class MangaDex : MangaConnector
|
|||||||
public override Manga? GetMangaFromId(string publicationId)
|
public override Manga? GetMangaFromId(string publicationId)
|
||||||
{
|
{
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest($"https://api.mangadex.org/manga/{publicationId}", RequestType.MangaInfo);
|
downloadClient.MakeRequest($"https://api.mangadex.org/manga/{publicationId}", (byte)RequestType.Manga);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return null;
|
return null;
|
||||||
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
||||||
@ -133,7 +149,7 @@ public class MangaDex : MangaConnector
|
|||||||
string? coverUrl = GetCoverUrl(publicationId, posterId);
|
string? coverUrl = GetCoverUrl(publicationId, posterId);
|
||||||
string? coverCacheName = null;
|
string? coverCacheName = null;
|
||||||
if (coverUrl is not null)
|
if (coverUrl is not null)
|
||||||
coverCacheName = SaveCoverImageToCache(coverUrl, RequestType.MangaCover);
|
coverCacheName = SaveCoverImageToCache(coverUrl, (byte)RequestType.AtHomeServer);
|
||||||
|
|
||||||
List<string> authors = GetAuthors(authorIds);
|
List<string> authors = GetAuthors(authorIds);
|
||||||
|
|
||||||
@ -200,7 +216,7 @@ public class MangaDex : MangaConnector
|
|||||||
//Request next "Page"
|
//Request next "Page"
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(
|
downloadClient.MakeRequest(
|
||||||
$"https://api.mangadex.org/manga/{manga.publicationId}/feed?limit={limit}&offset={offset}&translatedLanguage%5B%5D={language}", RequestType.MangaDexFeed);
|
$"https://api.mangadex.org/manga/{manga.publicationId}/feed?limit={limit}&offset={offset}&translatedLanguage%5B%5D={language}", (byte)RequestType.Feed);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
break;
|
break;
|
||||||
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
||||||
@ -252,7 +268,7 @@ public class MangaDex : MangaConnector
|
|||||||
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
||||||
//Request URLs for Chapter-Images
|
//Request URLs for Chapter-Images
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest($"https://api.mangadex.org/at-home/server/{chapter.url}?forcePort443=false'", RequestType.MangaDexImage);
|
downloadClient.MakeRequest($"https://api.mangadex.org/at-home/server/{chapter.url}?forcePort443=false'", (byte)RequestType.AtHomeServer);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
{
|
{
|
||||||
progressToken?.Cancel();
|
progressToken?.Cancel();
|
||||||
@ -277,7 +293,7 @@ public class MangaDex : MangaConnector
|
|||||||
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
||||||
|
|
||||||
//Download Chapter-Images
|
//Download Chapter-Images
|
||||||
return DownloadChapterImages(imageUrls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, progressToken:progressToken);
|
return DownloadChapterImages(imageUrls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), (byte)RequestType.AtHomeServer, comicInfoPath, progressToken:progressToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string? GetCoverUrl(string publicationId, string? posterId)
|
private string? GetCoverUrl(string publicationId, string? posterId)
|
||||||
@ -291,7 +307,7 @@ public class MangaDex : MangaConnector
|
|||||||
|
|
||||||
//Request information where to download Cover
|
//Request information where to download Cover
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest($"https://api.mangadex.org/cover/{posterId}", RequestType.MangaCover);
|
downloadClient.MakeRequest($"https://api.mangadex.org/cover/{posterId}", (byte)RequestType.CoverUrl);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return null;
|
return null;
|
||||||
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
||||||
@ -312,7 +328,7 @@ public class MangaDex : MangaConnector
|
|||||||
foreach (string authorId in authorIds)
|
foreach (string authorId in authorIds)
|
||||||
{
|
{
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest($"https://api.mangadex.org/author/{authorId}", RequestType.MangaDexAuthor);
|
downloadClient.MakeRequest($"https://api.mangadex.org/author/{authorId}", (byte)RequestType.Author);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return ret;
|
return ret;
|
||||||
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
JsonObject? result = JsonSerializer.Deserialize<JsonObject>(requestResult.result);
|
||||||
|
@ -9,7 +9,10 @@ public class MangaKatana : MangaConnector
|
|||||||
{
|
{
|
||||||
public MangaKatana(GlobalBase clone) : base(clone, "MangaKatana")
|
public MangaKatana(GlobalBase clone) : base(clone, "MangaKatana")
|
||||||
{
|
{
|
||||||
this.downloadClient = new HttpDownloadClient(clone);
|
this.downloadClient = new HttpDownloadClient(clone, new Dictionary<byte, int>()
|
||||||
|
{
|
||||||
|
{1, 60}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Manga[] GetManga(string publicationTitle = "")
|
public override Manga[] GetManga(string publicationTitle = "")
|
||||||
@ -18,7 +21,7 @@ public class MangaKatana : MangaConnector
|
|||||||
string sanitizedTitle = string.Join('_', Regex.Matches(publicationTitle, "[A-z]*").Where(m => m.Value.Length > 0)).ToLower();
|
string sanitizedTitle = string.Join('_', Regex.Matches(publicationTitle, "[A-z]*").Where(m => m.Value.Length > 0)).ToLower();
|
||||||
string requestUrl = $"https://mangakatana.com/?search={sanitizedTitle}&search_by=book_name";
|
string requestUrl = $"https://mangakatana.com/?search={sanitizedTitle}&search_by=book_name";
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Manga>();
|
return Array.Empty<Manga>();
|
||||||
|
|
||||||
@ -44,7 +47,7 @@ public class MangaKatana : MangaConnector
|
|||||||
public override Manga? GetMangaFromUrl(string url)
|
public override Manga? GetMangaFromUrl(string url)
|
||||||
{
|
{
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(url, RequestType.MangaInfo);
|
downloadClient.MakeRequest(url, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return null;
|
return null;
|
||||||
return ParseSinglePublicationFromHtml(requestResult.result, url.Split('/')[^1]);
|
return ParseSinglePublicationFromHtml(requestResult.result, url.Split('/')[^1]);
|
||||||
@ -128,7 +131,7 @@ public class MangaKatana : MangaConnector
|
|||||||
string posterUrl = document.DocumentNode.SelectSingleNode("//*[@id='single_book']/div[1]/div").Descendants("img").First()
|
string posterUrl = document.DocumentNode.SelectSingleNode("//*[@id='single_book']/div[1]/div").Descendants("img").First()
|
||||||
.GetAttributes().First(a => a.Name == "src").Value;
|
.GetAttributes().First(a => a.Name == "src").Value;
|
||||||
|
|
||||||
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, RequestType.MangaCover);
|
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, 1);
|
||||||
|
|
||||||
string description = document.DocumentNode.SelectSingleNode("//*[@id='single_book']/div[3]/p").InnerText;
|
string description = document.DocumentNode.SelectSingleNode("//*[@id='single_book']/div[3]/p").InnerText;
|
||||||
while (description.StartsWith('\n'))
|
while (description.StartsWith('\n'))
|
||||||
@ -155,7 +158,7 @@ public class MangaKatana : MangaConnector
|
|||||||
string requestUrl = $"https://mangakatana.com/manga/{manga.publicationId}";
|
string requestUrl = $"https://mangakatana.com/manga/{manga.publicationId}";
|
||||||
// Leaving this in for verification if the page exists
|
// Leaving this in for verification if the page exists
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Chapter>();
|
return Array.Empty<Chapter>();
|
||||||
|
|
||||||
@ -207,7 +210,7 @@ public class MangaKatana : MangaConnector
|
|||||||
string requestUrl = chapter.url;
|
string requestUrl = chapter.url;
|
||||||
// Leaving this in to check if the page exists
|
// Leaving this in to check if the page exists
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
{
|
{
|
||||||
progressToken?.Cancel();
|
progressToken?.Cancel();
|
||||||
@ -219,7 +222,7 @@ public class MangaKatana : MangaConnector
|
|||||||
string comicInfoPath = Path.GetTempFileName();
|
string comicInfoPath = Path.GetTempFileName();
|
||||||
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
||||||
|
|
||||||
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, "https://mangakatana.com/", progressToken:progressToken);
|
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, "https://mangakatana.com/", progressToken:progressToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string[] ParseImageUrlsFromHtml(string mangaUrl)
|
private string[] ParseImageUrlsFromHtml(string mangaUrl)
|
||||||
|
@ -9,7 +9,10 @@ public class MangaLife : MangaConnector
|
|||||||
{
|
{
|
||||||
public MangaLife(GlobalBase clone) : base(clone, "Manga4Life")
|
public MangaLife(GlobalBase clone) : base(clone, "Manga4Life")
|
||||||
{
|
{
|
||||||
this.downloadClient = new ChromiumDownloadClient(clone);
|
this.downloadClient = new ChromiumDownloadClient(clone, new Dictionary<byte, int>()
|
||||||
|
{
|
||||||
|
{ 1, 60 }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Manga[] GetManga(string publicationTitle = "")
|
public override Manga[] GetManga(string publicationTitle = "")
|
||||||
@ -18,7 +21,7 @@ public class MangaLife : MangaConnector
|
|||||||
string sanitizedTitle = WebUtility.UrlEncode(publicationTitle);
|
string sanitizedTitle = WebUtility.UrlEncode(publicationTitle);
|
||||||
string requestUrl = $"https://manga4life.com/search/?name={sanitizedTitle}";
|
string requestUrl = $"https://manga4life.com/search/?name={sanitizedTitle}";
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Manga>();
|
return Array.Empty<Manga>();
|
||||||
|
|
||||||
@ -36,10 +39,10 @@ public class MangaLife : MangaConnector
|
|||||||
|
|
||||||
public override Manga? GetMangaFromUrl(string url)
|
public override Manga? GetMangaFromUrl(string url)
|
||||||
{
|
{
|
||||||
Regex publicationIdRex = new(@"https:\/\/(www\.)?manga4life.com\/manga\/(.*)(\/.*)*");
|
Regex publicationIdRex = new(@"https:\/\/manga4life.com\/manga\/(.*)(\/.*)*");
|
||||||
string publicationId = publicationIdRex.Match(url).Groups[2].Value;
|
string publicationId = publicationIdRex.Match(url).Groups[1].Value;
|
||||||
|
|
||||||
RequestResult requestResult = this.downloadClient.MakeRequest(url, RequestType.MangaInfo);
|
RequestResult requestResult = this.downloadClient.MakeRequest(url, 1);
|
||||||
if(requestResult.htmlDocument is not null)
|
if(requestResult.htmlDocument is not null)
|
||||||
return ParseSinglePublicationFromHtml(requestResult.htmlDocument, publicationId);
|
return ParseSinglePublicationFromHtml(requestResult.htmlDocument, publicationId);
|
||||||
return null;
|
return null;
|
||||||
@ -78,7 +81,7 @@ public class MangaLife : MangaConnector
|
|||||||
|
|
||||||
HtmlNode posterNode = document.DocumentNode.SelectSingleNode("//div[@class='BoxBody']//div[@class='row']//img");
|
HtmlNode posterNode = document.DocumentNode.SelectSingleNode("//div[@class='BoxBody']//div[@class='row']//img");
|
||||||
string posterUrl = posterNode.GetAttributeValue("src", "");
|
string posterUrl = posterNode.GetAttributeValue("src", "");
|
||||||
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, RequestType.MangaCover);
|
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, 1);
|
||||||
|
|
||||||
HtmlNode titleNode = document.DocumentNode.SelectSingleNode("//div[@class='BoxBody']//div[@class='row']//h1");
|
HtmlNode titleNode = document.DocumentNode.SelectSingleNode("//div[@class='BoxBody']//div[@class='row']//h1");
|
||||||
string sortName = titleNode.InnerText;
|
string sortName = titleNode.InnerText;
|
||||||
@ -130,7 +133,7 @@ public class MangaLife : MangaConnector
|
|||||||
public override Chapter[] GetChapters(Manga manga, string language="en")
|
public override Chapter[] GetChapters(Manga manga, string language="en")
|
||||||
{
|
{
|
||||||
Log($"Getting chapters {manga}");
|
Log($"Getting chapters {manga}");
|
||||||
RequestResult result = downloadClient.MakeRequest($"https://manga4life.com/manga/{manga.publicationId}", RequestType.Default, clickButton:"[class*='ShowAllChapters']");
|
RequestResult result = downloadClient.MakeRequest($"https://manga4life.com/manga/{manga.publicationId}", 1, clickButton:"[class*='ShowAllChapters']");
|
||||||
if ((int)result.statusCode < 200 || (int)result.statusCode >= 300 || result.htmlDocument is null)
|
if ((int)result.statusCode < 200 || (int)result.statusCode >= 300 || result.htmlDocument is null)
|
||||||
{
|
{
|
||||||
return Array.Empty<Chapter>();
|
return Array.Empty<Chapter>();
|
||||||
@ -139,7 +142,7 @@ public class MangaLife : MangaConnector
|
|||||||
HtmlNodeCollection chapterNodes = result.htmlDocument.DocumentNode.SelectNodes(
|
HtmlNodeCollection chapterNodes = result.htmlDocument.DocumentNode.SelectNodes(
|
||||||
"//a[contains(concat(' ',normalize-space(@class),' '),' ChapterLink ')]");
|
"//a[contains(concat(' ',normalize-space(@class),' '),' ChapterLink ')]");
|
||||||
string[] urls = chapterNodes.Select(node => node.GetAttributeValue("href", "")).ToArray();
|
string[] urls = chapterNodes.Select(node => node.GetAttributeValue("href", "")).ToArray();
|
||||||
Regex urlRex = new (@"-chapter-([0-9\\.]+)(-index-([0-9\\.]+))?");
|
Regex urlRex = new Regex(@"-chapter-([0-9\\.]+)(-index-([0-9\\.]+))?");
|
||||||
|
|
||||||
List<Chapter> chapters = new();
|
List<Chapter> chapters = new();
|
||||||
foreach (string url in urls)
|
foreach (string url in urls)
|
||||||
@ -176,7 +179,7 @@ public class MangaLife : MangaConnector
|
|||||||
|
|
||||||
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
||||||
|
|
||||||
RequestResult requestResult = this.downloadClient.MakeRequest(chapter.url, RequestType.Default);
|
RequestResult requestResult = this.downloadClient.MakeRequest(chapter.url, 1);
|
||||||
if (requestResult.htmlDocument is null)
|
if (requestResult.htmlDocument is null)
|
||||||
{
|
{
|
||||||
progressToken?.Cancel();
|
progressToken?.Cancel();
|
||||||
@ -194,6 +197,6 @@ public class MangaLife : MangaConnector
|
|||||||
string comicInfoPath = Path.GetTempFileName();
|
string comicInfoPath = Path.GetTempFileName();
|
||||||
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
||||||
|
|
||||||
return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, progressToken:progressToken);
|
return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, progressToken:progressToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,7 +9,10 @@ public class Manganato : MangaConnector
|
|||||||
{
|
{
|
||||||
public Manganato(GlobalBase clone) : base(clone, "Manganato")
|
public Manganato(GlobalBase clone) : base(clone, "Manganato")
|
||||||
{
|
{
|
||||||
this.downloadClient = new HttpDownloadClient(clone);
|
this.downloadClient = new HttpDownloadClient(clone, new Dictionary<byte, int>()
|
||||||
|
{
|
||||||
|
{1, 60}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Manga[] GetManga(string publicationTitle = "")
|
public override Manga[] GetManga(string publicationTitle = "")
|
||||||
@ -18,7 +21,7 @@ public class Manganato : MangaConnector
|
|||||||
string sanitizedTitle = string.Join('_', Regex.Matches(publicationTitle, "[A-z]*").Where(str => str.Length > 0)).ToLower();
|
string sanitizedTitle = string.Join('_', Regex.Matches(publicationTitle, "[A-z]*").Where(str => str.Length > 0)).ToLower();
|
||||||
string requestUrl = $"https://manganato.com/search/story/{sanitizedTitle}";
|
string requestUrl = $"https://manganato.com/search/story/{sanitizedTitle}";
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Manga>();
|
return Array.Empty<Manga>();
|
||||||
|
|
||||||
@ -59,7 +62,7 @@ public class Manganato : MangaConnector
|
|||||||
public override Manga? GetMangaFromUrl(string url)
|
public override Manga? GetMangaFromUrl(string url)
|
||||||
{
|
{
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(url, RequestType.MangaInfo);
|
downloadClient.MakeRequest(url, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -118,7 +121,7 @@ public class Manganato : MangaConnector
|
|||||||
string posterUrl = document.DocumentNode.Descendants("span").First(s => s.HasClass("info-image")).Descendants("img").First()
|
string posterUrl = document.DocumentNode.Descendants("span").First(s => s.HasClass("info-image")).Descendants("img").First()
|
||||||
.GetAttributes().First(a => a.Name == "src").Value;
|
.GetAttributes().First(a => a.Name == "src").Value;
|
||||||
|
|
||||||
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, RequestType.MangaCover);
|
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, 1);
|
||||||
|
|
||||||
string description = document.DocumentNode.Descendants("div").First(d => d.HasClass("panel-story-info-description"))
|
string description = document.DocumentNode.Descendants("div").First(d => d.HasClass("panel-story-info-description"))
|
||||||
.InnerText.Replace("Description :", "");
|
.InnerText.Replace("Description :", "");
|
||||||
@ -140,7 +143,7 @@ public class Manganato : MangaConnector
|
|||||||
Log($"Getting chapters {manga}");
|
Log($"Getting chapters {manga}");
|
||||||
string requestUrl = $"https://chapmanganato.com/{manga.publicationId}";
|
string requestUrl = $"https://chapmanganato.com/{manga.publicationId}";
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Chapter>();
|
return Array.Empty<Chapter>();
|
||||||
|
|
||||||
@ -189,7 +192,7 @@ public class Manganato : MangaConnector
|
|||||||
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
||||||
string requestUrl = chapter.url;
|
string requestUrl = chapter.url;
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
{
|
{
|
||||||
progressToken?.Cancel();
|
progressToken?.Cancel();
|
||||||
@ -207,7 +210,7 @@ public class Manganato : MangaConnector
|
|||||||
string comicInfoPath = Path.GetTempFileName();
|
string comicInfoPath = Path.GetTempFileName();
|
||||||
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
||||||
|
|
||||||
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, "https://chapmanganato.com/", progressToken:progressToken);
|
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, "https://chapmanganato.com/", progressToken:progressToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string[] ParseImageUrlsFromHtml(HtmlDocument document)
|
private string[] ParseImageUrlsFromHtml(HtmlDocument document)
|
||||||
|
@ -12,7 +12,10 @@ public class Mangasee : MangaConnector
|
|||||||
{
|
{
|
||||||
public Mangasee(GlobalBase clone) : base(clone, "Mangasee")
|
public Mangasee(GlobalBase clone) : base(clone, "Mangasee")
|
||||||
{
|
{
|
||||||
this.downloadClient = new ChromiumDownloadClient(clone);
|
this.downloadClient = new ChromiumDownloadClient(clone, new Dictionary<byte, int>()
|
||||||
|
{
|
||||||
|
{ 1, 60 }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct SearchResult
|
private struct SearchResult
|
||||||
@ -27,7 +30,7 @@ public class Mangasee : MangaConnector
|
|||||||
Log($"Searching Publications. Term=\"{publicationTitle}\"");
|
Log($"Searching Publications. Term=\"{publicationTitle}\"");
|
||||||
string requestUrl = "https://mangasee123.com/_search.php";
|
string requestUrl = "https://mangasee123.com/_search.php";
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
{
|
{
|
||||||
Log($"Failed to retrieve search: {requestResult.statusCode}");
|
Log($"Failed to retrieve search: {requestResult.statusCode}");
|
||||||
@ -118,8 +121,8 @@ public class Mangasee : MangaConnector
|
|||||||
Regex publicationIdRex = new(@"https:\/\/mangasee123.com\/manga\/(.*)(\/.*)*");
|
Regex publicationIdRex = new(@"https:\/\/mangasee123.com\/manga\/(.*)(\/.*)*");
|
||||||
string publicationId = publicationIdRex.Match(url).Groups[1].Value;
|
string publicationId = publicationIdRex.Match(url).Groups[1].Value;
|
||||||
|
|
||||||
RequestResult requestResult = this.downloadClient.MakeRequest(url, RequestType.MangaInfo);
|
RequestResult requestResult = this.downloadClient.MakeRequest(url, 1);
|
||||||
if((int)requestResult.statusCode < 300 && (int)requestResult.statusCode >= 200 && requestResult.htmlDocument is not null)
|
if(requestResult.htmlDocument is not null)
|
||||||
return ParseSinglePublicationFromHtml(requestResult.htmlDocument, publicationId);
|
return ParseSinglePublicationFromHtml(requestResult.htmlDocument, publicationId);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -133,7 +136,7 @@ public class Mangasee : MangaConnector
|
|||||||
|
|
||||||
HtmlNode posterNode = document.DocumentNode.SelectSingleNode("//div[@class='BoxBody']//div[@class='row']//img");
|
HtmlNode posterNode = document.DocumentNode.SelectSingleNode("//div[@class='BoxBody']//div[@class='row']//img");
|
||||||
string posterUrl = posterNode.GetAttributeValue("src", "");
|
string posterUrl = posterNode.GetAttributeValue("src", "");
|
||||||
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, RequestType.MangaCover);
|
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, 1);
|
||||||
|
|
||||||
HtmlNode titleNode = document.DocumentNode.SelectSingleNode("//div[@class='BoxBody']//div[@class='row']//h1");
|
HtmlNode titleNode = document.DocumentNode.SelectSingleNode("//div[@class='BoxBody']//div[@class='row']//h1");
|
||||||
string sortName = titleNode.InnerText;
|
string sortName = titleNode.InnerText;
|
||||||
@ -191,15 +194,13 @@ public class Mangasee : MangaConnector
|
|||||||
XDocument doc = XDocument.Load($"https://mangasee123.com/rss/{manga.publicationId}.xml");
|
XDocument doc = XDocument.Load($"https://mangasee123.com/rss/{manga.publicationId}.xml");
|
||||||
XElement[] chapterItems = doc.Descendants("item").ToArray();
|
XElement[] chapterItems = doc.Descendants("item").ToArray();
|
||||||
List<Chapter> chapters = new();
|
List<Chapter> chapters = new();
|
||||||
Regex chVolRex = new(@".*chapter-([0-9\.]+)(?:-index-([0-9\.]+))?.*");
|
|
||||||
foreach (XElement chapter in chapterItems)
|
foreach (XElement chapter in chapterItems)
|
||||||
{
|
{
|
||||||
|
string volumeNumber = "1";
|
||||||
string url = chapter.Descendants("link").First().Value;
|
string url = chapter.Descendants("link").First().Value;
|
||||||
Match m = chVolRex.Match(url);
|
string chapterNumber = Regex.Match(url, @"-chapter-([0-9\.]+)").Groups[1].ToString();
|
||||||
string? volumeNumber = m.Groups[2].Success ? m.Groups[2].Value : "1";
|
|
||||||
string chapterNumber = m.Groups[1].Value;
|
|
||||||
|
|
||||||
url = string.Concat(Regex.Match(url, @"(.*)-page-[0-9]+(\.html)").Groups.Values.Select(v => v.Value));
|
url = url.Replace(Regex.Match(url,"(-page-[0-9])").Value,"");
|
||||||
chapters.Add(new Chapter(manga, "", volumeNumber, chapterNumber, url));
|
chapters.Add(new Chapter(manga, "", volumeNumber, chapterNumber, url));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +232,7 @@ public class Mangasee : MangaConnector
|
|||||||
|
|
||||||
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
||||||
|
|
||||||
RequestResult requestResult = this.downloadClient.MakeRequest(chapter.url, RequestType.Default);
|
RequestResult requestResult = this.downloadClient.MakeRequest(chapter.url, 1);
|
||||||
if (requestResult.htmlDocument is null)
|
if (requestResult.htmlDocument is null)
|
||||||
{
|
{
|
||||||
progressToken?.Cancel();
|
progressToken?.Cancel();
|
||||||
@ -249,6 +250,6 @@ public class Mangasee : MangaConnector
|
|||||||
string comicInfoPath = Path.GetTempFileName();
|
string comicInfoPath = Path.GetTempFileName();
|
||||||
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
||||||
|
|
||||||
return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, progressToken:progressToken);
|
return DownloadChapterImages(urls.ToArray(), chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, progressToken:progressToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,7 +9,10 @@ public class Mangaworld: MangaConnector
|
|||||||
{
|
{
|
||||||
public Mangaworld(GlobalBase clone) : base(clone, "Mangaworld")
|
public Mangaworld(GlobalBase clone) : base(clone, "Mangaworld")
|
||||||
{
|
{
|
||||||
this.downloadClient = new HttpDownloadClient(clone);
|
this.downloadClient = new HttpDownloadClient(clone, new Dictionary<byte, int>()
|
||||||
|
{
|
||||||
|
{1, 60}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Manga[] GetManga(string publicationTitle = "")
|
public override Manga[] GetManga(string publicationTitle = "")
|
||||||
@ -18,7 +21,7 @@ public class Mangaworld: MangaConnector
|
|||||||
string sanitizedTitle = string.Join(' ', Regex.Matches(publicationTitle, "[A-z]*").Where(str => str.Length > 0)).ToLower();
|
string sanitizedTitle = string.Join(' ', Regex.Matches(publicationTitle, "[A-z]*").Where(str => str.Length > 0)).ToLower();
|
||||||
string requestUrl = $"https://www.mangaworld.ac/archive?keyword={sanitizedTitle}";
|
string requestUrl = $"https://www.mangaworld.ac/archive?keyword={sanitizedTitle}";
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Manga>();
|
return Array.Empty<Manga>();
|
||||||
|
|
||||||
@ -59,14 +62,14 @@ public class Mangaworld: MangaConnector
|
|||||||
public override Manga? GetMangaFromUrl(string url)
|
public override Manga? GetMangaFromUrl(string url)
|
||||||
{
|
{
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(url, RequestType.MangaInfo);
|
downloadClient.MakeRequest(url, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (requestResult.htmlDocument is null)
|
if (requestResult.htmlDocument is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Regex idRex = new (@"https:\/\/www\.mangaworld\.[a-z]{0,63}\/manga\/([0-9]+\/[0-9A-z\-]+).*");
|
Regex idRex = new (@"https:\/\/www\.mangaworld\.[a-z]{0,63}\/manga\/([0-9]+\/[0-9A-z\-]+)");
|
||||||
string id = idRex.Match(url).Groups[1].Value;
|
string id = idRex.Match(url).Groups[1].Value;
|
||||||
return ParseSinglePublicationFromHtml(requestResult.htmlDocument, id);
|
return ParseSinglePublicationFromHtml(requestResult.htmlDocument, id);
|
||||||
}
|
}
|
||||||
@ -84,19 +87,19 @@ public class Mangaworld: MangaConnector
|
|||||||
|
|
||||||
HtmlNode metadata = infoNode.Descendants().First(d => d.HasClass("meta-data"));
|
HtmlNode metadata = infoNode.Descendants().First(d => d.HasClass("meta-data"));
|
||||||
|
|
||||||
HtmlNode altTitlesNode = metadata.SelectSingleNode("//span[text()='Titoli alternativi: ' or text()='Titolo alternativo: ']/..").ChildNodes[1];
|
HtmlNode altTitlesNode = metadata.SelectSingleNode("//span[text()='Titoli alternativi: ']/..").ChildNodes[1];
|
||||||
|
|
||||||
string[] alts = altTitlesNode.InnerText.Split(", ");
|
string[] alts = altTitlesNode.InnerText.Split(", ");
|
||||||
for(int i = 0; i < alts.Length; i++)
|
for(int i = 0; i < alts.Length; i++)
|
||||||
altTitles.Add(i.ToString(), alts[i]);
|
altTitles.Add(i.ToString(), alts[i]);
|
||||||
|
|
||||||
HtmlNode genresNode =
|
HtmlNode genresNode =
|
||||||
metadata.SelectSingleNode("//span[text()='Generi: ' or text()='Genero: ']/..");
|
metadata.SelectSingleNode("//span[text()='Generi: ']/..");
|
||||||
HashSet<string> tags = genresNode.SelectNodes("a").Select(node => node.InnerText).ToHashSet();
|
HashSet<string> tags = genresNode.SelectNodes("a").Select(node => node.InnerText).ToHashSet();
|
||||||
|
|
||||||
HtmlNode authorsNode =
|
HtmlNode authorsNode =
|
||||||
metadata.SelectSingleNode("//span[text()='Autore: ' or text()='Autori: ']/..");
|
metadata.SelectSingleNode("//span[text()='Autore: ']/..");
|
||||||
string[] authors = authorsNode.SelectNodes("a").Select(node => node.InnerText).ToArray();
|
string[] authors = new[] { authorsNode.SelectNodes("a").First().InnerText };
|
||||||
|
|
||||||
string status = metadata.SelectSingleNode("//span[text()='Stato: ']/..").SelectNodes("a").First().InnerText;
|
string status = metadata.SelectSingleNode("//span[text()='Stato: ']/..").SelectNodes("a").First().InnerText;
|
||||||
// ReSharper disable 5 times StringLiteralTypo
|
// ReSharper disable 5 times StringLiteralTypo
|
||||||
@ -111,7 +114,7 @@ public class Mangaworld: MangaConnector
|
|||||||
|
|
||||||
string posterUrl = document.DocumentNode.SelectSingleNode("//img[@class='rounded']").GetAttributeValue("src", "");
|
string posterUrl = document.DocumentNode.SelectSingleNode("//img[@class='rounded']").GetAttributeValue("src", "");
|
||||||
|
|
||||||
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, RequestType.MangaCover);
|
string coverFileNameInCache = SaveCoverImageToCache(posterUrl, 1);
|
||||||
|
|
||||||
string description = document.DocumentNode.SelectSingleNode("//div[@id='noidungm']").InnerText;
|
string description = document.DocumentNode.SelectSingleNode("//div[@id='noidungm']").InnerText;
|
||||||
|
|
||||||
@ -129,7 +132,7 @@ public class Mangaworld: MangaConnector
|
|||||||
Log($"Getting chapters {manga}");
|
Log($"Getting chapters {manga}");
|
||||||
string requestUrl = $"https://www.mangaworld.ac/manga/{manga.publicationId}";
|
string requestUrl = $"https://www.mangaworld.ac/manga/{manga.publicationId}";
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
return Array.Empty<Chapter>();
|
return Array.Empty<Chapter>();
|
||||||
|
|
||||||
@ -188,7 +191,7 @@ public class Mangaworld: MangaConnector
|
|||||||
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
Log($"Retrieving chapter-info {chapter} {chapterParentManga}");
|
||||||
string requestUrl = $"{chapter.url}?style=list";
|
string requestUrl = $"{chapter.url}?style=list";
|
||||||
RequestResult requestResult =
|
RequestResult requestResult =
|
||||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
downloadClient.MakeRequest(requestUrl, 1);
|
||||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||||
{
|
{
|
||||||
progressToken?.Cancel();
|
progressToken?.Cancel();
|
||||||
@ -206,7 +209,7 @@ public class Mangaworld: MangaConnector
|
|||||||
string comicInfoPath = Path.GetTempFileName();
|
string comicInfoPath = Path.GetTempFileName();
|
||||||
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
File.WriteAllText(comicInfoPath, chapter.GetComicInfoXmlString());
|
||||||
|
|
||||||
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), RequestType.MangaImage, comicInfoPath, "https://www.mangaworld.bz/", progressToken:progressToken);
|
return DownloadChapterImages(imageUrls, chapter.GetArchiveFilePath(settings.downloadLocation), 1, comicInfoPath, "https://www.mangaworld.bz/", progressToken:progressToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string[] ParseImageUrlsFromHtml(HtmlDocument document)
|
private string[] ParseImageUrlsFromHtml(HtmlDocument document)
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
namespace Tranga.MangaConnectors;
|
|
||||||
|
|
||||||
public enum RequestType : byte
|
|
||||||
{
|
|
||||||
Default = 0,
|
|
||||||
MangaDexFeed = 1,
|
|
||||||
MangaImage = 2,
|
|
||||||
MangaCover = 3,
|
|
||||||
MangaDexAuthor = 4,
|
|
||||||
MangaDexImage = 5,
|
|
||||||
MangaInfo = 6
|
|
||||||
}
|
|
@ -399,19 +399,16 @@ public class Server : GlobalBase
|
|||||||
case "Settings/customRequestLimit":
|
case "Settings/customRequestLimit":
|
||||||
if (!requestVariables.TryGetValue("requestType", out string? requestTypeStr) ||
|
if (!requestVariables.TryGetValue("requestType", out string? requestTypeStr) ||
|
||||||
!requestVariables.TryGetValue("requestsPerMinute", out string? requestsPerMinuteStr) ||
|
!requestVariables.TryGetValue("requestsPerMinute", out string? requestsPerMinuteStr) ||
|
||||||
!Enum.TryParse(requestTypeStr, out RequestType requestType) ||
|
!requestVariables.TryGetValue("connector", out connectorName) ||
|
||||||
!int.TryParse(requestsPerMinuteStr, out int requestsPerMinute))
|
!byte.TryParse(requestTypeStr, out byte requestType) ||
|
||||||
|
!int.TryParse(requestsPerMinuteStr, out int requestsPerMinute) ||
|
||||||
|
!_parent.TryGetConnector(connectorName, out connector))
|
||||||
{
|
{
|
||||||
SendResponse(HttpStatusCode.BadRequest, response);
|
SendResponse(HttpStatusCode.BadRequest, response);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
connector!.downloadClient.SetCustomRequestLimit(requestType, requestsPerMinute);
|
||||||
if (settings.requestLimits.ContainsKey(requestType))
|
SendResponse(HttpStatusCode.Accepted, response);
|
||||||
{
|
|
||||||
settings.requestLimits[requestType] = requestsPerMinute;
|
|
||||||
SendResponse(HttpStatusCode.Accepted, response);
|
|
||||||
}else
|
|
||||||
SendResponse(HttpStatusCode.BadRequest, response);
|
|
||||||
break;
|
break;
|
||||||
case "NotificationConnectors/Update":
|
case "NotificationConnectors/Update":
|
||||||
if (!requestVariables.TryGetValue("notificationConnector", out string? notificationConnectorStr) ||
|
if (!requestVariables.TryGetValue("notificationConnector", out string? notificationConnectorStr) ||
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Tranga.LibraryConnectors;
|
using Tranga.LibraryConnectors;
|
||||||
using Tranga.MangaConnectors;
|
|
||||||
using Tranga.NotificationConnectors;
|
using Tranga.NotificationConnectors;
|
||||||
using static System.IO.UnixFileMode;
|
using static System.IO.UnixFileMode;
|
||||||
|
|
||||||
@ -14,26 +13,15 @@ public class TrangaSettings
|
|||||||
public string workingDirectory { get; private set; }
|
public string workingDirectory { get; private set; }
|
||||||
public int apiPortNumber { get; init; }
|
public int apiPortNumber { get; init; }
|
||||||
public string styleSheet { get; private set; }
|
public string styleSheet { get; private set; }
|
||||||
public string userAgent { get; set; } = DefaultUserAgent;
|
|
||||||
|
public string userAgent { get; set; } =
|
||||||
|
$"Tranga ({Enum.GetName(Environment.OSVersion.Platform)}; {(Environment.Is64BitOperatingSystem ? "x64" : "")}) / 1.0";
|
||||||
[JsonIgnore] public string settingsFilePath => Path.Join(workingDirectory, "settings.json");
|
[JsonIgnore] public string settingsFilePath => Path.Join(workingDirectory, "settings.json");
|
||||||
[JsonIgnore] public string libraryConnectorsFilePath => Path.Join(workingDirectory, "libraryConnectors.json");
|
[JsonIgnore] public string libraryConnectorsFilePath => Path.Join(workingDirectory, "libraryConnectors.json");
|
||||||
[JsonIgnore] public string notificationConnectorsFilePath => Path.Join(workingDirectory, "notificationConnectors.json");
|
[JsonIgnore] public string notificationConnectorsFilePath => Path.Join(workingDirectory, "notificationConnectors.json");
|
||||||
[JsonIgnore] public string jobsFolderPath => Path.Join(workingDirectory, "jobs");
|
[JsonIgnore] public string jobsFolderPath => Path.Join(workingDirectory, "jobs");
|
||||||
[JsonIgnore] public string coverImageCache => Path.Join(workingDirectory, "imageCache");
|
[JsonIgnore] public string coverImageCache => Path.Join(workingDirectory, "imageCache");
|
||||||
[JsonIgnore] internal static readonly string DefaultUserAgent = $"Tranga ({Enum.GetName(Environment.OSVersion.Platform)}; {(Environment.Is64BitOperatingSystem ? "x64" : "")}) / 1.0";
|
public ushort? version { get; set; }
|
||||||
public ushort? version { get; set; } = 1;
|
|
||||||
[JsonIgnore]internal static readonly Dictionary<RequestType, int> DefaultRequestLimits = new ()
|
|
||||||
{
|
|
||||||
{RequestType.MangaInfo, 250},
|
|
||||||
{RequestType.MangaDexFeed, 250},
|
|
||||||
{RequestType.MangaDexImage, 40},
|
|
||||||
{RequestType.MangaImage, 60},
|
|
||||||
{RequestType.MangaCover, 250},
|
|
||||||
{RequestType.MangaDexAuthor, 250},
|
|
||||||
{RequestType.Default, 60}
|
|
||||||
};
|
|
||||||
|
|
||||||
public Dictionary<RequestType, int> requestLimits { get; set; } = DefaultRequestLimits;
|
|
||||||
|
|
||||||
public TrangaSettings(string? downloadLocation = null, string? workingDirectory = null, int? apiPortNumber = null)
|
public TrangaSettings(string? downloadLocation = null, string? workingDirectory = null, int? apiPortNumber = null)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user