mirror of
https://github.com/C9Glax/tranga.git
synced 2025-04-14 04:13:18 +02:00
Fix DownloadMangaCover, Implement Manga/Cover endpoint
This commit is contained in:
parent
4075adfe6b
commit
c679d7c677
@ -106,7 +106,7 @@ public class MangaController(PgsqlContext context) : Controller
|
||||
Image image = Image.Load(m.CoverFileNameInCache);
|
||||
using MemoryStream ms = new();
|
||||
image.Save(ms, new JpegEncoder(){Quality = 100});
|
||||
return File(ms, "image/jpeg");
|
||||
return File(ms.GetBuffer(), "image/jpeg");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -11,125 +11,21 @@ using static System.IO.UnixFileMode;
|
||||
|
||||
namespace API.Schema.Jobs;
|
||||
|
||||
public class DownloadMangaCoverJob(string chapterId, string? parentJobId = null, ICollection<string>? dependsOnJobsIds = null)
|
||||
public class DownloadMangaCoverJob(string mangaId, string? parentJobId = null, ICollection<string>? dependsOnJobsIds = null)
|
||||
: Job(TokenGen.CreateToken(typeof(DownloadMangaCoverJob)), JobType.DownloadMangaCoverJob, 0, parentJobId, dependsOnJobsIds)
|
||||
{
|
||||
[MaxLength(64)]
|
||||
public string ChapterId { get; init; } = chapterId;
|
||||
public Chapter? Chapter { get; init; }
|
||||
public string MangaId { get; init; } = mangaId;
|
||||
public Manga? Manga { get; init; }
|
||||
|
||||
protected override IEnumerable<Job> RunInternal(PgsqlContext context)
|
||||
{
|
||||
MangaConnector connector = Chapter.ParentManga?.MangaConnector ?? context.MangaConnectors.Find(context.Manga.Find(Chapter.ParentMangaId)?.MangaId)!;
|
||||
DownloadChapterImages(Chapter, connector);
|
||||
Manga? manga = Manga ?? context.Manga.Find(this.MangaId);
|
||||
if (manga is null)
|
||||
return [];
|
||||
|
||||
manga.CoverFileNameInCache = manga.SaveCoverImageToCache();
|
||||
context.SaveChanges();
|
||||
return [];
|
||||
}
|
||||
|
||||
private bool DownloadChapterImages(Chapter chapter, MangaConnector connector)
|
||||
{
|
||||
string[] imageUrls = connector.GetChapterImageUrls(Chapter);
|
||||
string saveArchiveFilePath = chapter.GetArchiveFilePath();
|
||||
|
||||
//Check if Publication Directory already exists
|
||||
string directoryPath = Path.GetDirectoryName(saveArchiveFilePath)!;
|
||||
if (!Directory.Exists(directoryPath))
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
Directory.CreateDirectory(directoryPath,
|
||||
UserRead | UserWrite | UserExecute | GroupRead | GroupWrite | GroupExecute );
|
||||
else
|
||||
Directory.CreateDirectory(directoryPath);
|
||||
|
||||
if (File.Exists(saveArchiveFilePath)) //Don't download twice. Redownload
|
||||
File.Delete(saveArchiveFilePath);
|
||||
|
||||
//Create a temporary folder to store images
|
||||
string tempFolder = Directory.CreateTempSubdirectory("trangatemp").FullName;
|
||||
|
||||
int chapterNum = 0;
|
||||
//Download all Images to temporary Folder
|
||||
if (imageUrls.Length == 0)
|
||||
{
|
||||
Directory.Delete(tempFolder, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (string imageUrl in imageUrls)
|
||||
{
|
||||
string extension = imageUrl.Split('.')[^1].Split('?')[0];
|
||||
string imagePath = Path.Join(tempFolder, $"{chapterNum++}.{extension}");
|
||||
bool status = DownloadImage(imageUrl, imagePath);
|
||||
if (status is false)
|
||||
return false;
|
||||
}
|
||||
|
||||
CopyCoverFromCacheToDownloadLocation();
|
||||
|
||||
File.WriteAllText(Path.Join(tempFolder, "ComicInfo.xml"), chapter.GetComicInfoXmlString());
|
||||
|
||||
//ZIP-it and ship-it
|
||||
ZipFile.CreateFromDirectory(tempFolder, saveArchiveFilePath);
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
File.SetUnixFileMode(saveArchiveFilePath, UserRead | UserWrite | UserExecute | GroupRead | GroupWrite | GroupExecute | OtherRead | OtherExecute);
|
||||
Directory.Delete(tempFolder, true); //Cleanup
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ProcessImage(string imagePath)
|
||||
{
|
||||
if (!TrangaSettings.bwImages && TrangaSettings.compression == 100)
|
||||
return;
|
||||
using Image image = Image.Load(imagePath);
|
||||
File.Delete(imagePath);
|
||||
if(TrangaSettings.bwImages)
|
||||
image.Mutate(i => i.ApplyProcessor(new AdaptiveThresholdProcessor()));
|
||||
image.SaveAsJpeg(imagePath, new JpegEncoder()
|
||||
{
|
||||
Quality = TrangaSettings.compression
|
||||
});
|
||||
}
|
||||
|
||||
private void CopyCoverFromCacheToDownloadLocation(int? retries = 1)
|
||||
{
|
||||
//Check if Publication already has a Folder and cover
|
||||
string publicationFolder = Chapter.ParentManga.CreatePublicationFolder();
|
||||
DirectoryInfo dirInfo = new (publicationFolder);
|
||||
if (dirInfo.EnumerateFiles().Any(info => info.Name.Contains("cover", StringComparison.InvariantCultureIgnoreCase)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string? fileInCache = Chapter.ParentManga.CoverFileNameInCache;
|
||||
if (fileInCache is null || !File.Exists(fileInCache))
|
||||
{
|
||||
if (retries > 0 && Chapter.ParentManga.CoverUrl is not null)
|
||||
{
|
||||
Chapter.ParentManga.SaveCoverImageToCache();
|
||||
CopyCoverFromCacheToDownloadLocation(--retries);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
string newFilePath = Path.Join(publicationFolder, $"cover.{Path.GetFileName(fileInCache).Split('.')[^1]}" );
|
||||
File.Copy(fileInCache, newFilePath, true);
|
||||
if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
File.SetUnixFileMode(newFilePath, GroupRead | GroupWrite | UserRead | UserWrite);
|
||||
}
|
||||
|
||||
private bool DownloadImage(string imageUrl, string savePath)
|
||||
{
|
||||
HttpDownloadClient downloadClient = new();
|
||||
RequestResult requestResult = downloadClient.MakeRequest(imageUrl, RequestType.MangaImage);
|
||||
|
||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||
return false;
|
||||
if (requestResult.result == Stream.Null)
|
||||
return false;
|
||||
|
||||
FileStream fs = new (savePath, FileMode.Create);
|
||||
requestResult.result.CopyTo(fs);
|
||||
fs.Close();
|
||||
ProcessImage(savePath);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -58,7 +58,7 @@ public class DownloadSingleChapterJob(string chapterId, string? parentJobId = nu
|
||||
return [];
|
||||
}
|
||||
|
||||
CopyCoverFromCacheToDownloadLocation(context, manga);
|
||||
CopyCoverFromCacheToDownloadLocation(manga);
|
||||
|
||||
File.WriteAllText(Path.Join(tempFolder, "ComicInfo.xml"), chapter.GetComicInfoXmlString());
|
||||
|
||||
@ -88,7 +88,7 @@ public class DownloadSingleChapterJob(string chapterId, string? parentJobId = nu
|
||||
});
|
||||
}
|
||||
|
||||
private void CopyCoverFromCacheToDownloadLocation(PgsqlContext context, Manga manga, int? retries = 1)
|
||||
private void CopyCoverFromCacheToDownloadLocation(Manga manga)
|
||||
{
|
||||
//Check if Publication already has a Folder and cover
|
||||
string publicationFolder = manga.CreatePublicationFolder();
|
||||
@ -98,18 +98,10 @@ public class DownloadSingleChapterJob(string chapterId, string? parentJobId = nu
|
||||
return;
|
||||
}
|
||||
|
||||
string? fileInCache = manga.CoverFileNameInCache;
|
||||
if (fileInCache is null || !File.Exists(fileInCache))
|
||||
{
|
||||
if (retries > 0)
|
||||
{
|
||||
manga.CoverFileNameInCache = manga.SaveCoverImageToCache();
|
||||
context.SaveChanges();
|
||||
CopyCoverFromCacheToDownloadLocation(context, manga, --retries);
|
||||
}
|
||||
|
||||
string? fileInCache = manga.CoverFileNameInCache ?? manga.SaveCoverImageToCache();
|
||||
if (fileInCache is null)
|
||||
return;
|
||||
}
|
||||
|
||||
string newFilePath = Path.Join(publicationFolder, $"cover.{Path.GetFileName(fileInCache).Split('.')[^1]}" );
|
||||
File.Copy(fileInCache, newFilePath, true);
|
||||
if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using API.MangaDownloadClients;
|
||||
@ -99,8 +99,11 @@ public class Manga
|
||||
return mangaName;
|
||||
}
|
||||
|
||||
internal string SaveCoverImageToCache()
|
||||
internal string? SaveCoverImageToCache(int retries = 3)
|
||||
{
|
||||
if(retries < 0)
|
||||
return null;
|
||||
|
||||
Regex urlRex = new (@"https?:\/\/((?:[a-zA-Z0-9-]+\.)+[a-zA-Z0-9]+)\/(?:.+\/)*(.+\.([a-zA-Z]+))");
|
||||
//https?:\/\/[a-zA-Z0-9-]+\.([a-zA-Z0-9-]+\.[a-zA-Z0-9]+)\/(?:.+\/)*(.+\.([a-zA-Z]+)) for only second level domains
|
||||
Match match = urlRex.Match(CoverUrl);
|
||||
@ -111,10 +114,14 @@ public class Manga
|
||||
return saveImagePath;
|
||||
|
||||
RequestResult coverResult = new HttpDownloadClient().MakeRequest(CoverUrl, RequestType.MangaCover);
|
||||
if (coverResult.statusCode is < HttpStatusCode.Accepted or >= HttpStatusCode.Ambiguous)
|
||||
return SaveCoverImageToCache(--retries);
|
||||
|
||||
using MemoryStream ms = new();
|
||||
coverResult.result.CopyTo(ms);
|
||||
Directory.CreateDirectory(TrangaSettings.coverImageCache);
|
||||
File.WriteAllBytes(saveImagePath, ms.ToArray());
|
||||
|
||||
return saveImagePath;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user