2025-02-01 21:58:50 +01:00
|
|
|
|
using System.ComponentModel.DataAnnotations;
|
2024-12-14 21:53:29 +01:00
|
|
|
|
using System.ComponentModel.DataAnnotations.Schema;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
using API.MangaDownloadClients;
|
|
|
|
|
using API.Schema.Jobs;
|
|
|
|
|
using API.Schema.MangaConnectors;
|
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
|
using static System.IO.UnixFileMode;
|
|
|
|
|
|
|
|
|
|
namespace API.Schema;
|
|
|
|
|
|
|
|
|
|
[PrimaryKey("MangaId")]
|
2025-01-09 01:34:03 +01:00
|
|
|
|
public class Manga
|
2024-12-14 21:53:29 +01:00
|
|
|
|
{
|
|
|
|
|
[MaxLength(64)]
|
2025-01-25 11:57:54 +01:00
|
|
|
|
public string MangaId { get; init; }
|
2024-12-14 21:53:29 +01:00
|
|
|
|
[MaxLength(64)]
|
2025-01-09 01:34:03 +01:00
|
|
|
|
public string ConnectorId { get; init; }
|
2024-12-14 21:53:29 +01:00
|
|
|
|
|
2025-01-09 01:34:03 +01:00
|
|
|
|
public string Name { get; internal set; }
|
|
|
|
|
public string Description { get; internal set; }
|
|
|
|
|
public string WebsiteUrl { get; internal set; }
|
|
|
|
|
public string CoverUrl { get; internal set; }
|
|
|
|
|
public string? CoverFileNameInCache { get; internal set; }
|
|
|
|
|
public uint Year { get; internal set; }
|
|
|
|
|
public string? OriginalLanguage { get; internal set; }
|
|
|
|
|
public MangaReleaseStatus ReleaseStatus { get; internal set; }
|
|
|
|
|
public string FolderName { get; private set; }
|
|
|
|
|
public float IgnoreChapterBefore { get; internal set; }
|
2024-12-14 21:53:29 +01:00
|
|
|
|
|
2025-01-09 01:34:03 +01:00
|
|
|
|
public string MangaConnectorId { get; private set; }
|
2025-02-01 21:58:50 +01:00
|
|
|
|
|
2025-01-09 01:34:03 +01:00
|
|
|
|
public MangaConnector? MangaConnector { get; private set; }
|
2024-12-14 21:53:29 +01:00
|
|
|
|
|
2025-01-09 01:34:03 +01:00
|
|
|
|
public ICollection<Author>? Authors { get; internal set; }
|
2024-12-14 21:53:29 +01:00
|
|
|
|
|
2025-01-09 01:34:03 +01:00
|
|
|
|
public ICollection<MangaTag>? Tags { get; internal set; }
|
2024-12-14 21:53:29 +01:00
|
|
|
|
|
2025-01-09 01:34:03 +01:00
|
|
|
|
public ICollection<Link>? Links { get; internal set; }
|
2024-12-14 21:53:29 +01:00
|
|
|
|
|
2025-01-09 01:34:03 +01:00
|
|
|
|
public ICollection<MangaAltTitle>? AltTitles { get; internal set; }
|
2024-12-16 19:25:22 +01:00
|
|
|
|
|
|
|
|
|
public Manga(string connectorId, string name, string description, string websiteUrl, string coverUrl,
|
2025-01-09 01:34:03 +01:00
|
|
|
|
string? coverFileNameInCache, uint year, string? originalLanguage, MangaReleaseStatus releaseStatus,
|
|
|
|
|
float ignoreChapterBefore, MangaConnector mangaConnector, ICollection<Author> authors,
|
|
|
|
|
ICollection<MangaTag> tags, ICollection<Link> links, ICollection<MangaAltTitle> altTitles)
|
2024-12-16 19:25:22 +01:00
|
|
|
|
: this(connectorId, name, description, websiteUrl, coverUrl, coverFileNameInCache, year, originalLanguage,
|
2025-01-09 01:34:03 +01:00
|
|
|
|
releaseStatus, ignoreChapterBefore, mangaConnector.Name)
|
2024-12-16 19:25:22 +01:00
|
|
|
|
{
|
2025-01-09 01:34:03 +01:00
|
|
|
|
this.Authors = authors;
|
|
|
|
|
this.Tags = tags;
|
|
|
|
|
this.Links = links;
|
|
|
|
|
this.AltTitles = altTitles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Manga(string connectorId, string name, string description, string websiteUrl, string coverUrl,
|
|
|
|
|
string? coverFileNameInCache, uint year, string? originalLanguage, MangaReleaseStatus releaseStatus,
|
|
|
|
|
float ignoreChapterBefore, string mangaConnectorId)
|
|
|
|
|
{
|
2025-01-31 21:24:35 +01:00
|
|
|
|
MangaId = TokenGen.CreateToken(typeof(Manga), MangaConnectorId, ConnectorId);
|
2025-01-09 01:34:03 +01:00
|
|
|
|
ConnectorId = connectorId;
|
|
|
|
|
Name = name;
|
|
|
|
|
Description = description;
|
|
|
|
|
WebsiteUrl = websiteUrl;
|
|
|
|
|
CoverUrl = coverUrl;
|
|
|
|
|
CoverFileNameInCache = coverFileNameInCache;
|
|
|
|
|
Year = year;
|
|
|
|
|
OriginalLanguage = originalLanguage;
|
|
|
|
|
ReleaseStatus = releaseStatus;
|
|
|
|
|
IgnoreChapterBefore = ignoreChapterBefore;
|
|
|
|
|
MangaConnectorId = mangaConnectorId;
|
|
|
|
|
FolderName = BuildFolderName(name);
|
2024-12-16 19:25:22 +01:00
|
|
|
|
}
|
2024-12-14 21:53:29 +01:00
|
|
|
|
|
|
|
|
|
public MoveFileOrFolderJob UpdateFolderName(string downloadLocation, string newName)
|
|
|
|
|
{
|
|
|
|
|
string oldName = this.FolderName;
|
|
|
|
|
this.FolderName = newName;
|
|
|
|
|
return new MoveFileOrFolderJob(Path.Join(downloadLocation, oldName), Path.Join(downloadLocation, this.FolderName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void UpdateWithInfo(Manga other)
|
|
|
|
|
{
|
|
|
|
|
this.Name = other.Name;
|
2025-01-09 01:34:03 +01:00
|
|
|
|
this.Year = other.Year;
|
2024-12-14 21:53:29 +01:00
|
|
|
|
this.Description = other.Description;
|
|
|
|
|
this.CoverUrl = other.CoverUrl;
|
|
|
|
|
this.OriginalLanguage = other.OriginalLanguage;
|
2024-12-16 19:25:22 +01:00
|
|
|
|
this.Authors = other.Authors;
|
|
|
|
|
this.Links = other.Links;
|
|
|
|
|
this.Tags = other.Tags;
|
|
|
|
|
this.AltTitles = other.AltTitles;
|
2024-12-14 21:53:29 +01:00
|
|
|
|
this.ReleaseStatus = other.ReleaseStatus;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string BuildFolderName(string mangaName)
|
|
|
|
|
{
|
|
|
|
|
return mangaName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal string SaveCoverImageToCache()
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
string filename = $"{match.Groups[1].Value}-{MangaId}.{match.Groups[3].Value}";
|
|
|
|
|
string saveImagePath = Path.Join(TrangaSettings.coverImageCache, filename);
|
|
|
|
|
|
|
|
|
|
if (File.Exists(saveImagePath))
|
|
|
|
|
return saveImagePath;
|
|
|
|
|
|
|
|
|
|
RequestResult coverResult = new HttpDownloadClient().MakeRequest(CoverUrl, RequestType.MangaCover);
|
|
|
|
|
using MemoryStream ms = new();
|
|
|
|
|
coverResult.result.CopyTo(ms);
|
|
|
|
|
Directory.CreateDirectory(TrangaSettings.coverImageCache);
|
|
|
|
|
File.WriteAllBytes(saveImagePath, ms.ToArray());
|
|
|
|
|
return saveImagePath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string CreatePublicationFolder()
|
|
|
|
|
{
|
|
|
|
|
string publicationFolder = Path.Join(TrangaSettings.downloadLocation, this.FolderName);
|
|
|
|
|
if(!Directory.Exists(publicationFolder))
|
|
|
|
|
Directory.CreateDirectory(publicationFolder);
|
|
|
|
|
if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
|
|
|
File.SetUnixFileMode(publicationFolder, GroupRead | GroupWrite | GroupExecute | OtherRead | OtherWrite | OtherExecute | UserRead | UserWrite | UserExecute);
|
|
|
|
|
return publicationFolder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TODO onchanges create job to update metadata files in archives, etc.
|
|
|
|
|
}
|