mirror of
https://github.com/C9Glax/tranga.git
synced 2025-09-10 11:58:19 +02:00
Resize Covers on download
This commit is contained in:
18
API/Constants.cs
Normal file
18
API/Constants.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using SixLabors.ImageSharp;
|
||||||
|
|
||||||
|
namespace API;
|
||||||
|
|
||||||
|
public struct Constants
|
||||||
|
{
|
||||||
|
public const string TRANGA =
|
||||||
|
"\n\n" +
|
||||||
|
" _______ v2\n" +
|
||||||
|
"|_ _|.----..---.-..-----..-----..---.-.\n" +
|
||||||
|
" | | | _|| _ || || _ || _ |\n" +
|
||||||
|
" |___| |__| |___._||__|__||___ ||___._|\n" +
|
||||||
|
" |_____| \n\n";
|
||||||
|
|
||||||
|
public static readonly Size ImageSmSize = new (225, 320);
|
||||||
|
public static readonly Size ImageMdSize = new (450, 640);
|
||||||
|
public static readonly Size ImageLgSize = new (900, 1280);
|
||||||
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
using API.Controllers.DTOs;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using API.Controllers.DTOs;
|
||||||
using API.Schema.MangaContext;
|
using API.Schema.MangaContext;
|
||||||
using API.Workers;
|
using API.Workers;
|
||||||
using Asp.Versioning;
|
using Asp.Versioning;
|
||||||
@@ -7,10 +8,6 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using SixLabors.ImageSharp;
|
|
||||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
|
||||||
using SixLabors.ImageSharp.Processing;
|
|
||||||
using SixLabors.ImageSharp.Processing.Processors.Transforms;
|
|
||||||
using static Microsoft.AspNetCore.Http.StatusCodes;
|
using static Microsoft.AspNetCore.Http.StatusCodes;
|
||||||
using AltTitle = API.Controllers.DTOs.AltTitle;
|
using AltTitle = API.Controllers.DTOs.AltTitle;
|
||||||
using Author = API.Controllers.DTOs.Author;
|
using Author = API.Controllers.DTOs.Author;
|
||||||
@@ -190,54 +187,49 @@ public class MangaController(MangaContext context) : Controller
|
|||||||
/// Returns Cover of <see cref="Manga"/> with <paramref name="MangaId"/>
|
/// Returns Cover of <see cref="Manga"/> with <paramref name="MangaId"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="MangaId"><see cref="Manga"/>.Key</param>
|
/// <param name="MangaId"><see cref="Manga"/>.Key</param>
|
||||||
/// <param name="width">If <paramref name="width"/> is provided, <paramref name="height"/> needs to also be provided</param>
|
/// <param name="CoverSize">Size of the cover returned
|
||||||
/// <param name="height">If <paramref name="height"/> is provided, <paramref name="width"/> needs to also be provided</param>
|
/// <br /> - <see cref="CoverSize.Small"/> <see cref="Constants.ImageSmSize"/>
|
||||||
|
/// <br /> - <see cref="CoverSize.Medium"/> <see cref="Constants.ImageMdSize"/>
|
||||||
|
/// <br /> - <see cref="CoverSize.Large"/> <see cref="Constants.ImageLgSize"/>
|
||||||
|
/// </param>
|
||||||
/// <response code="200">JPEG Image</response>
|
/// <response code="200">JPEG Image</response>
|
||||||
/// <response code="204">Cover not loaded</response>
|
/// <response code="204">Cover not loaded</response>
|
||||||
/// <response code="400">The formatting-request was invalid</response>
|
|
||||||
/// <response code="404"><see cref="Manga"/> with <paramref name="MangaId"/> not found</response>
|
/// <response code="404"><see cref="Manga"/> with <paramref name="MangaId"/> not found</response>
|
||||||
/// <response code="503">Retry later, downloading cover</response>
|
/// <response code="503">Retry later, downloading cover</response>
|
||||||
[HttpGet("{MangaId}/Cover")]
|
[HttpGet("{MangaId}/Cover/{CoverSize?}")]
|
||||||
[ProducesResponseType<byte[]>(Status200OK,"image/jpeg")]
|
[ProducesResponseType<FileContentResult>(Status200OK,"image/jpeg")]
|
||||||
[ProducesResponseType(Status204NoContent)]
|
[ProducesResponseType(Status204NoContent)]
|
||||||
[ProducesResponseType(Status400BadRequest)]
|
[ProducesResponseType(Status400BadRequest)]
|
||||||
[ProducesResponseType<string>(Status404NotFound, "text/plain")]
|
[ProducesResponseType<string>(Status404NotFound, "text/plain")]
|
||||||
[ProducesResponseType(Status503ServiceUnavailable)]
|
[ProducesResponseType(Status503ServiceUnavailable)]
|
||||||
public async Task<Results<FileContentHttpResult, NoContent, BadRequest, NotFound<string>, StatusCodeHttpResult>> GetCover (string MangaId, [FromQuery]int? width, [FromQuery]int? height)
|
public async Task<Results<FileContentHttpResult, NoContent, BadRequest, NotFound<string>, StatusCodeHttpResult>> GetCover (string MangaId, CoverSize? CoverSize = null)
|
||||||
{
|
{
|
||||||
if (await context.Mangas.FirstOrDefaultAsync(m => m.Key == MangaId, HttpContext.RequestAborted) is not { } manga)
|
if (await context.Mangas.FirstOrDefaultAsync(m => m.Key == MangaId, HttpContext.RequestAborted) is not { } manga)
|
||||||
return TypedResults.NotFound(nameof(MangaId));
|
return TypedResults.NotFound(nameof(MangaId));
|
||||||
|
|
||||||
if (!System.IO.File.Exists(manga.CoverFileNameInCache))
|
string cache = CoverSize switch
|
||||||
|
{
|
||||||
|
MangaController.CoverSize.Small => TrangaSettings.coverImageCacheSmall,
|
||||||
|
MangaController.CoverSize.Medium => TrangaSettings.coverImageCacheMedium,
|
||||||
|
MangaController.CoverSize.Large => TrangaSettings.coverImageCacheLarge,
|
||||||
|
_ => TrangaSettings.coverImageCacheOriginal
|
||||||
|
};
|
||||||
|
|
||||||
|
if (await manga.GetCoverImage(cache, HttpContext.RequestAborted) is not { } data)
|
||||||
{
|
{
|
||||||
if (Tranga.GetRunningWorkers().Any(worker => worker is DownloadCoverFromMangaconnectorWorker w && context.MangaConnectorToManga.Find(w.MangaConnectorIdId)?.ObjId == MangaId))
|
if (Tranga.GetRunningWorkers().Any(worker => worker is DownloadCoverFromMangaconnectorWorker w && context.MangaConnectorToManga.Find(w.MangaConnectorIdId)?.ObjId == MangaId))
|
||||||
{
|
{
|
||||||
Response.Headers.Append("Retry-After", $"{Tranga.Settings.WorkCycleTimeoutMs * 2 / 1000:D}");
|
Response.Headers.Append("Retry-After", $"{Tranga.Settings.WorkCycleTimeoutMs * 2 / 1000:D}");
|
||||||
return TypedResults.StatusCode(Status503ServiceUnavailable);
|
return TypedResults.StatusCode(Status503ServiceUnavailable);
|
||||||
}
|
}
|
||||||
else
|
return TypedResults.NoContent();
|
||||||
return TypedResults.NoContent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Image image = await Image.LoadAsync(manga.CoverFileNameInCache, HttpContext.RequestAborted);
|
DateTime lastModified = data.fileInfo.LastWriteTime;
|
||||||
|
|
||||||
if (width is { } w && height is { } h)
|
|
||||||
{
|
|
||||||
if (width < 10 || height < 10 || width > 65535 || height > 65535)
|
|
||||||
return TypedResults.BadRequest();
|
|
||||||
image.Mutate(i => i.ApplyProcessor(new ResizeProcessor(new ResizeOptions()
|
|
||||||
{
|
|
||||||
Mode = ResizeMode.Max,
|
|
||||||
Size = new Size(w, h)
|
|
||||||
}, image.Size)));
|
|
||||||
}
|
|
||||||
|
|
||||||
using MemoryStream ms = new();
|
|
||||||
await image.SaveAsync(ms, new JpegEncoder(){Quality = 100}, HttpContext.RequestAborted);
|
|
||||||
DateTime lastModified = new FileInfo(manga.CoverFileNameInCache).LastWriteTime;
|
|
||||||
HttpContext.Response.Headers.CacheControl = "public";
|
HttpContext.Response.Headers.CacheControl = "public";
|
||||||
return TypedResults.File(ms.GetBuffer(), "image/jpeg", lastModified: new DateTimeOffset(lastModified), entityTag: EntityTagHeaderValue.Parse($"\"{lastModified.Ticks}\""));
|
return TypedResults.Bytes(data.stream.ToArray(), "image/jpeg", lastModified: new DateTimeOffset(lastModified), entityTag: EntityTagHeaderValue.Parse($"\"{lastModified.Ticks}\""));
|
||||||
}
|
}
|
||||||
|
public enum CoverSize { Original, Large, Medium, Small }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns all <see cref="Chapter"/> of <see cref="Manga"/> with <paramref name="MangaId"/>
|
/// Returns all <see cref="Chapter"/> of <see cref="Manga"/> with <paramref name="MangaId"/>
|
||||||
|
@@ -6,6 +6,9 @@ using API.Schema.MangaContext;
|
|||||||
using log4net;
|
using log4net;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
|
||||||
namespace API.MangaConnectors;
|
namespace API.MangaConnectors;
|
||||||
|
|
||||||
@@ -43,8 +46,8 @@ public abstract class MangaConnector(string name, string[] supportedLanguages, s
|
|||||||
Regex urlRex = new (@"https?:\/\/((?:[a-zA-Z0-9-]+\.)+[a-zA-Z0-9]+)\/(?:.+\/)*(.+\.([a-zA-Z]+))");
|
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
|
//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(mangaId.Obj.CoverUrl);
|
Match match = urlRex.Match(mangaId.Obj.CoverUrl);
|
||||||
string filename = $"{match.Groups[1].Value}-{mangaId.Key}.{match.Groups[3].Value}";
|
string filename = $"{match.Groups[1].Value}-{mangaId.ObjId}.{mangaId.MangaConnectorName}.{match.Groups[3].Value}";
|
||||||
string saveImagePath = Path.Join(TrangaSettings.coverImageCache, filename);
|
string saveImagePath = Path.Join(TrangaSettings.coverImageCacheOriginal, filename);
|
||||||
|
|
||||||
if (File.Exists(saveImagePath))
|
if (File.Exists(saveImagePath))
|
||||||
return saveImagePath;
|
return saveImagePath;
|
||||||
@@ -53,11 +56,36 @@ public abstract class MangaConnector(string name, string[] supportedLanguages, s
|
|||||||
if ((int)coverResult.statusCode < 200 || (int)coverResult.statusCode >= 300)
|
if ((int)coverResult.statusCode < 200 || (int)coverResult.statusCode >= 300)
|
||||||
return SaveCoverImageToCache(mangaId, --retries);
|
return SaveCoverImageToCache(mangaId, --retries);
|
||||||
|
|
||||||
using MemoryStream ms = new();
|
try
|
||||||
coverResult.result.CopyTo(ms);
|
{
|
||||||
Directory.CreateDirectory(TrangaSettings.coverImageCache);
|
using MemoryStream ms = new();
|
||||||
File.WriteAllBytes(saveImagePath, ms.ToArray());
|
coverResult.result.CopyTo(ms);
|
||||||
|
byte[] imageBytes = ms.ToArray();
|
||||||
|
Directory.CreateDirectory(TrangaSettings.coverImageCacheOriginal);
|
||||||
|
File.WriteAllBytes(saveImagePath, imageBytes);
|
||||||
|
|
||||||
return saveImagePath;
|
using Image image = Image.Load(imageBytes);
|
||||||
|
Directory.CreateDirectory(TrangaSettings.coverImageCacheLarge);
|
||||||
|
using Image large = image.Clone(x => x.Resize(new ResizeOptions
|
||||||
|
{ Size = Constants.ImageLgSize, Mode = ResizeMode.Max }));
|
||||||
|
large.SaveAsJpeg(Path.Join(TrangaSettings.coverImageCacheLarge, filename), new (){ Quality = 40 });
|
||||||
|
|
||||||
|
Directory.CreateDirectory(TrangaSettings.coverImageCacheMedium);
|
||||||
|
using Image medium = image.Clone(x => x.Resize(new ResizeOptions
|
||||||
|
{ Size = Constants.ImageMdSize, Mode = ResizeMode.Max }));
|
||||||
|
medium.SaveAsJpeg(Path.Join(TrangaSettings.coverImageCacheMedium, filename), new (){ Quality = 40 });
|
||||||
|
|
||||||
|
Directory.CreateDirectory(TrangaSettings.coverImageCacheSmall);
|
||||||
|
using Image small = image.Clone(x => x.Resize(new ResizeOptions
|
||||||
|
{ Size = Constants.ImageSmSize, Mode = ResizeMode.Max }));
|
||||||
|
small.SaveAsJpeg(Path.Join(TrangaSettings.coverImageCacheSmall, filename), new (){ Quality = 40 });
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return filename;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -4,6 +4,10 @@ using System.Runtime.InteropServices;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using API.Workers;
|
using API.Workers;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using SixLabors.ImageSharp.Processing.Processors.Transforms;
|
||||||
using static System.IO.UnixFileMode;
|
using static System.IO.UnixFileMode;
|
||||||
|
|
||||||
namespace API.Schema.MangaContext;
|
namespace API.Schema.MangaContext;
|
||||||
@@ -155,6 +159,18 @@ public class Manga : Identifiable
|
|||||||
return newJobs.ToArray();
|
return newJobs.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<(MemoryStream stream, FileInfo fileInfo)?> GetCoverImage(string cachePath, CancellationToken ct)
|
||||||
|
{
|
||||||
|
string fullPath = Path.Join(cachePath, CoverFileNameInCache);
|
||||||
|
if (!File.Exists(fullPath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
FileInfo fileInfo = new(fullPath);
|
||||||
|
MemoryStream stream = new (await File.ReadAllBytesAsync(fullPath, ct));
|
||||||
|
|
||||||
|
return (stream, fileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString() => $"{base.ToString()} {Name}";
|
public override string ToString() => $"{base.ToString()} {Name}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,16 +15,6 @@ namespace API;
|
|||||||
|
|
||||||
public static class Tranga
|
public static class Tranga
|
||||||
{
|
{
|
||||||
|
|
||||||
// ReSharper disable once InconsistentNaming
|
|
||||||
private const string TRANGA =
|
|
||||||
"\n\n" +
|
|
||||||
" _______ v2\n" +
|
|
||||||
"|_ _|.----..---.-..-----..-----..---.-.\n" +
|
|
||||||
" | | | _|| _ || || _ || _ |\n" +
|
|
||||||
" |___| |__| |___._||__|__||___ ||___._|\n" +
|
|
||||||
" |_____| \n\n";
|
|
||||||
|
|
||||||
private static IServiceProvider? ServiceProvider;
|
private static IServiceProvider? ServiceProvider;
|
||||||
|
|
||||||
private static readonly ILog Log = LogManager.GetLogger(typeof(Tranga));
|
private static readonly ILog Log = LogManager.GetLogger(typeof(Tranga));
|
||||||
@@ -45,7 +35,7 @@ public static class Tranga
|
|||||||
{
|
{
|
||||||
XmlConfigurator.ConfigureAndWatch(loggerConfigFile);
|
XmlConfigurator.ConfigureAndWatch(loggerConfigFile);
|
||||||
Log.Info("Logger Configured.");
|
Log.Info("Logger Configured.");
|
||||||
Log.Info(TRANGA);
|
Log.Info(Constants.TRANGA);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void AddDefaultWorkers()
|
internal static void AddDefaultWorkers()
|
||||||
|
@@ -11,8 +11,11 @@ public struct TrangaSettings()
|
|||||||
public static string workingDirectory => Path.Join(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/usr/share" : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "tranga-api");
|
public static string workingDirectory => Path.Join(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/usr/share" : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "tranga-api");
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public static string settingsFilePath => Path.Join(workingDirectory, "settings.json");
|
public static string settingsFilePath => Path.Join(workingDirectory, "settings.json");
|
||||||
[JsonIgnore]
|
[JsonIgnore] public static string coverImageCache => Path.Join(workingDirectory, "imageCache");
|
||||||
public static string coverImageCache => Path.Join(workingDirectory, "imageCache");
|
[JsonIgnore] public static string coverImageCacheOriginal => Path.Join(coverImageCache, "original");
|
||||||
|
[JsonIgnore] public static string coverImageCacheLarge => Path.Join(coverImageCache, "large");
|
||||||
|
[JsonIgnore] public static string coverImageCacheMedium => Path.Join(coverImageCache, "medium");
|
||||||
|
[JsonIgnore] public static string coverImageCacheSmall => Path.Join(coverImageCache, "small");
|
||||||
public string DownloadLocation => RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/Manga" : Path.Join(Directory.GetCurrentDirectory(), "Manga");
|
public string DownloadLocation => RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/Manga" : Path.Join(Directory.GetCurrentDirectory(), "Manga");
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
internal static readonly string DefaultUserAgent = $"Tranga/2.0 ({Enum.GetName(Environment.OSVersion.Platform)}; {(Environment.Is64BitOperatingSystem ? "x64" : "")})";
|
internal static readonly string DefaultUserAgent = $"Tranga/2.0 ({Enum.GetName(Environment.OSVersion.Platform)}; {(Environment.Is64BitOperatingSystem ? "x64" : "")})";
|
||||||
|
@@ -200,18 +200,19 @@ public class DownloadChapterFromMangaconnectorWorker(MangaConnectorId<Chapter> c
|
|||||||
|
|
||||||
Log.Info($"Copying cover to {publicationFolder}");
|
Log.Info($"Copying cover to {publicationFolder}");
|
||||||
await DbContext.Entry(mangaConnectorId).Navigation(nameof(MangaConnectorId<Manga>.Obj)).LoadAsync(CancellationToken);
|
await DbContext.Entry(mangaConnectorId).Navigation(nameof(MangaConnectorId<Manga>.Obj)).LoadAsync(CancellationToken);
|
||||||
string? fileInCache = manga.CoverFileNameInCache ?? mangaConnector.SaveCoverImageToCache(mangaConnectorId);
|
string? coverFileNameInCache = manga.CoverFileNameInCache ?? mangaConnector.SaveCoverImageToCache(mangaConnectorId);
|
||||||
if (fileInCache is null)
|
if (coverFileNameInCache is null)
|
||||||
{
|
{
|
||||||
Log.Error($"File {fileInCache} does not exist");
|
Log.Error($"File {coverFileNameInCache} does not exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string newFilePath = Path.Join(publicationFolder, $"cover.{Path.GetFileName(fileInCache).Split('.')[^1]}" );
|
string fullCoverPath = Path.Join(TrangaSettings.coverImageCacheOriginal, coverFileNameInCache);
|
||||||
File.Copy(fileInCache, newFilePath, true);
|
string newFilePath = Path.Join(publicationFolder, $"cover.{Path.GetFileName(coverFileNameInCache).Split('.')[^1]}" );
|
||||||
|
File.Copy(fullCoverPath, newFilePath, true);
|
||||||
if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
File.SetUnixFileMode(newFilePath, GroupRead | GroupWrite | UserRead | UserWrite | OtherRead | OtherWrite);
|
File.SetUnixFileMode(newFilePath, GroupRead | GroupWrite | UserRead | UserWrite | OtherRead | OtherWrite);
|
||||||
Log.Debug($"Copied cover from {fileInCache} to {newFilePath}");
|
Log.Debug($"Copied cover from {fullCoverPath} to {newFilePath}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool DownloadImage(string imageUrl, string savePath)
|
private bool DownloadImage(string imageUrl, string savePath)
|
||||||
|
@@ -11,11 +11,22 @@ public class CleanupMangaCoversWorker(TimeSpan? interval = null, IEnumerable<Bas
|
|||||||
protected override Task<BaseWorker[]> DoWorkInternal()
|
protected override Task<BaseWorker[]> DoWorkInternal()
|
||||||
{
|
{
|
||||||
Log.Info("Removing stale files...");
|
Log.Info("Removing stale files...");
|
||||||
if (!Directory.Exists(TrangaSettings.coverImageCache))
|
|
||||||
return new Task<BaseWorker[]>(() => []);
|
|
||||||
string[] usedFiles = DbContext.Mangas.Select(m => m.CoverFileNameInCache).Where(s => s != null).ToArray()!;
|
string[] usedFiles = DbContext.Mangas.Select(m => m.CoverFileNameInCache).Where(s => s != null).ToArray()!;
|
||||||
string[] extraneousFiles = new DirectoryInfo(TrangaSettings.coverImageCache).GetFiles()
|
CleanupImageCache(usedFiles, TrangaSettings.coverImageCacheOriginal);
|
||||||
.Where(f => usedFiles.Contains(f.FullName) == false)
|
CleanupImageCache(usedFiles, TrangaSettings.coverImageCacheLarge);
|
||||||
|
CleanupImageCache(usedFiles, TrangaSettings.coverImageCacheMedium);
|
||||||
|
CleanupImageCache(usedFiles, TrangaSettings.coverImageCacheSmall);
|
||||||
|
return new Task<BaseWorker[]>(() => []);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CleanupImageCache(string[] retainFilenames, string imageCachePath)
|
||||||
|
{
|
||||||
|
DirectoryInfo directory = new(imageCachePath);
|
||||||
|
if (!directory.Exists)
|
||||||
|
return;
|
||||||
|
string[] extraneousFiles = directory
|
||||||
|
.GetFiles()
|
||||||
|
.Where(f => retainFilenames.Contains(f.Name) == false)
|
||||||
.Select(f => f.FullName)
|
.Select(f => f.FullName)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
foreach (string path in extraneousFiles)
|
foreach (string path in extraneousFiles)
|
||||||
@@ -23,6 +34,5 @@ public class CleanupMangaCoversWorker(TimeSpan? interval = null, IEnumerable<Bas
|
|||||||
Log.Info($"Deleting {path}");
|
Log.Info($"Deleting {path}");
|
||||||
File.Delete(path);
|
File.Delete(path);
|
||||||
}
|
}
|
||||||
return new Task<BaseWorker[]>(() => []);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user