4 Commits

Author SHA1 Message Date
1b6af73a0c MangaDex nullvalue checks and allow null-fields in response
Some checks failed
Docker Image CI / build (push) Has been cancelled
2025-06-15 23:55:23 +02:00
70fe23857b Update UserAgent-String to Version 2.0 2025-06-15 23:26:30 +02:00
0027af2d36 Fix: First startup coverImageCache does not exist (on stale check) 2025-06-15 23:07:34 +02:00
1a8f70f501 Cleanup code for HttpDownloadClient and error-log 2025-06-15 23:00:01 +02:00
4 changed files with 31 additions and 32 deletions

View File

@@ -18,33 +18,28 @@ internal class HttpDownloadClient : DownloadClient
internal override RequestResult MakeRequestInternal(string url, string? referrer = null, string? clickButton = null) internal override RequestResult MakeRequestInternal(string url, string? referrer = null, string? clickButton = null)
{ {
if (clickButton is not null) if (clickButton is not null)
Log.Warn("Can not click button on static site."); Log.Warn("Client can not click button");
HttpResponseMessage? response = null; HttpResponseMessage? response = null;
while (response is null) while (response is null)
{ {
HttpRequestMessage requestMessage = new(HttpMethod.Get, url); HttpRequestMessage requestMessage = new(HttpMethod.Get, url);
if (referrer is not null) if (referrer is not null)
requestMessage.Headers.Referrer = new Uri(referrer); requestMessage.Headers.Referrer = new (referrer);
Log.Debug($"Requesting {url}"); Log.Debug($"Requesting {url}");
try try
{ {
response = Client.Send(requestMessage); response = Client.Send(requestMessage);
} }
catch (Exception e) catch (HttpRequestException e)
{ {
switch (e) Log.Error(e);
{ return new (HttpStatusCode.Unused, null, Stream.Null);
case TaskCanceledException:
return new RequestResult(HttpStatusCode.RequestTimeout, null, Stream.Null);
case HttpRequestException:
return new RequestResult(HttpStatusCode.BadRequest, null, Stream.Null);
}
} }
} }
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
{ {
return new RequestResult(response.StatusCode, null, Stream.Null); return new (response.StatusCode, null, Stream.Null);
} }
Stream stream; Stream stream;
@@ -55,7 +50,7 @@ internal class HttpDownloadClient : DownloadClient
catch (Exception e) catch (Exception e)
{ {
Log.Error(e); Log.Error(e);
return new RequestResult(HttpStatusCode.InternalServerError, null, Stream.Null); return new (HttpStatusCode.Unused, null, Stream.Null);
} }
HtmlDocument? document = null; HtmlDocument? document = null;
@@ -71,10 +66,9 @@ internal class HttpDownloadClient : DownloadClient
// Request has been redirected to another page. For example, it redirects directly to the results when there is only 1 result // Request has been redirected to another page. For example, it redirects directly to the results when there is only 1 result
if (response.RequestMessage is not null && response.RequestMessage.RequestUri is not null) if (response.RequestMessage is not null && response.RequestMessage.RequestUri is not null)
{ {
return new RequestResult(response.StatusCode, document, stream, true, return new (response.StatusCode, document, stream, true, response.RequestMessage.RequestUri.AbsoluteUri);
response.RequestMessage.RequestUri.AbsoluteUri);
} }
return new RequestResult(response.StatusCode, document, stream); return new (response.StatusCode, document, stream);
} }
} }

View File

@@ -226,22 +226,25 @@ public class MangaDex : MangaConnector
private Manga ParseMangaFromJToken(JToken jToken) private Manga ParseMangaFromJToken(JToken jToken)
{ {
string? id = jToken.Value<string>("id"); string? id = jToken.Value<string>("id");
if(id is null)
throw new Exception("jToken was not in expected format");
JObject? attributes = jToken["attributes"] as JObject; JObject? attributes = jToken["attributes"] as JObject;
string? name = attributes?["title"]?.Value<string>("en") ?? attributes?["title"]?.First?.First?.Value<string>(); if(attributes is null)
string? description = attributes?["description"]?.Value<string>("en")??attributes?["description"]?.First?.First?.Value<string>(); throw new Exception("jToken was not in expected format");
string? status = attributes?["status"]?.Value<string>(); string? name = attributes["title"]?.Value<string>("en") ?? attributes["title"]?.First?.First?.Value<string>();
uint? year = attributes?["year"]?.Value<uint?>(); string description = attributes["description"]?.Value<string>("en")??attributes["description"]?.First?.First?.Value<string>()??"";
string? originalLanguage = attributes?["originalLanguage"]?.Value<string>(); string? status = attributes["status"]?.Value<string>();
JArray? altTitlesJArray = attributes?["altTitles"] as JArray; uint? year = attributes["year"]?.Value<uint?>();
JArray? tagsJArray = attributes?["tags"] as JArray; string? originalLanguage = attributes["originalLanguage"]?.Value<string>();
JArray? altTitlesJArray = attributes.TryGetValue("altTitles", out JToken? altTitlesArray) ? altTitlesArray as JArray : null;
JArray? tagsJArray = attributes.TryGetValue("tags", out JToken? tagsArray) ? tagsArray as JArray : null;
JArray? relationships = jToken["relationships"] as JArray; JArray? relationships = jToken["relationships"] as JArray;
string? coverFileName = if (name is null || status is null || relationships is null)
relationships?.FirstOrDefault(r => r["type"]?.Value<string>() == "cover_art")?["attributes"]?.Value<string>("fileName"); throw new Exception("jToken was not in expected format");
if (id is null || attributes is null || name is null || description is null || status is null || string? coverFileName = relationships.FirstOrDefault(r => r["type"]?.Value<string>() == "cover_art")?["attributes"]?.Value<string>("fileName");
altTitlesJArray is null || tagsJArray is null || relationships is null || coverFileName is null) if(coverFileName is null)
throw new Exception("jToken was not in expected format"); throw new Exception("jToken was not in expected format");
List<Link> links = attributes["links"]? List<Link> links = attributes["links"]?
@@ -276,7 +279,7 @@ public class MangaDex : MangaConnector
return new Link(key, url); return new Link(key, url);
}).ToList()!; }).ToList()!;
List<MangaAltTitle> altTitles = altTitlesJArray List<MangaAltTitle> altTitles = (altTitlesJArray??[])
.Select(t => .Select(t =>
{ {
JObject? j = t as JObject; JObject? j = t as JObject;
@@ -286,7 +289,7 @@ public class MangaDex : MangaConnector
return new MangaAltTitle(p.Name, p.Value.ToString()); return new MangaAltTitle(p.Name, p.Value.ToString());
}).Where(x => x is not null).ToList()!; }).Where(x => x is not null).ToList()!;
List<MangaTag> tags = tagsJArray List<MangaTag> tags = (tagsJArray??[])
.Where(t => t.Value<string>("type") == "tag") .Where(t => t.Value<string>("type") == "tag")
.Select(t => t["attributes"]?["name"]?.Value<string>("en")??t["attributes"]?["name"]?.First?.First?.Value<string>()) .Select(t => t["attributes"]?["name"]?.Value<string>("en")??t["attributes"]?["name"]?.First?.First?.Value<string>())
.Select(str => str is not null ? new MangaTag(str) : null) .Select(str => str is not null ? new MangaTag(str) : null)

View File

@@ -34,7 +34,9 @@ public static class Tranga
internal static void RemoveStaleFiles(PgsqlContext context) internal static void RemoveStaleFiles(PgsqlContext context)
{ {
Log.Info($"Removing stale files..."); Log.Info("Removing stale files...");
if (!Directory.Exists(TrangaSettings.coverImageCache))
return;
string[] usedFiles = context.Mangas.Select(m => m.CoverFileNameInCache).Where(s => s != null).ToArray()!; string[] usedFiles = context.Mangas.Select(m => m.CoverFileNameInCache).Where(s => s != null).ToArray()!;
string[] extraneousFiles = new DirectoryInfo(TrangaSettings.coverImageCache).GetFiles() string[] extraneousFiles = new DirectoryInfo(TrangaSettings.coverImageCache).GetFiles()
.Where(f => usedFiles.Contains(f.FullName) == false) .Where(f => usedFiles.Contains(f.FullName) == false)

View File

@@ -11,7 +11,7 @@ public static class TrangaSettings
public static string downloadLocation { get; private set; } = (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/Manga" : Path.Join(Directory.GetCurrentDirectory(), "Downloads")); public static string downloadLocation { get; private set; } = (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/Manga" : Path.Join(Directory.GetCurrentDirectory(), "Downloads"));
public static string workingDirectory { get; private set; } = Path.Join(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/usr/share" : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "tranga-api"); public static string workingDirectory { get; private set; } = Path.Join(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/usr/share" : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "tranga-api");
[JsonIgnore] [JsonIgnore]
internal static readonly string DefaultUserAgent = $"Tranga ({Enum.GetName(Environment.OSVersion.Platform)}; {(Environment.Is64BitOperatingSystem ? "x64" : "")}) / 1.0"; internal static readonly string DefaultUserAgent = $"Tranga ({Enum.GetName(Environment.OSVersion.Platform)}; {(Environment.Is64BitOperatingSystem ? "x64" : "")}) / 2.0";
public static string userAgent { get; private set; } = DefaultUserAgent; public static string userAgent { get; private set; } = DefaultUserAgent;
public static int compression{ get; private set; } = 40; public static int compression{ get; private set; } = 40;
public static bool bwImages { get; private set; } = false; public static bool bwImages { get; private set; } = false;