mirror of
https://github.com/C9Glax/tranga.git
synced 2025-06-15 15:57:54 +02:00
[postgres-Server-V2] feat: Convert chapterNumeber to string
This commit is contained in:
@ -7,6 +7,6 @@ namespace API.Schema;
|
||||
public class Author(string authorName)
|
||||
{
|
||||
[MaxLength(64)]
|
||||
public string AuthorId { get; init; } = TokenGen.CreateToken(typeof(Author), 64);
|
||||
public string AuthorId { get; init; } = TokenGen.CreateToken(typeof(Author), authorName);
|
||||
public string AuthorName { get; init; } = authorName;
|
||||
}
|
@ -8,71 +8,84 @@ namespace API.Schema;
|
||||
[PrimaryKey("ChapterId")]
|
||||
public class Chapter : IComparable<Chapter>
|
||||
{
|
||||
[MaxLength(64)]
|
||||
public string ChapterId { get; init; } = TokenGen.CreateToken(typeof(Chapter), 64);
|
||||
public Chapter(Manga parentManga, string url, string chapterNumber, int? volumeNumber = null, string? title = null)
|
||||
: this(parentManga.MangaId, url, chapterNumber, volumeNumber, title)
|
||||
{
|
||||
ParentManga = parentManga;
|
||||
ArchiveFileName = BuildArchiveFileName();
|
||||
}
|
||||
|
||||
public Chapter(string parentMangaId, string url, string chapterNumber,
|
||||
int? volumeNumber = null, string? title = null)
|
||||
{
|
||||
ChapterId = TokenGen.CreateToken(typeof(Chapter), string.Join(parentMangaId, volumeNumber ?? 0, chapterNumber));
|
||||
ParentMangaId = parentMangaId;
|
||||
Url = url;
|
||||
ChapterNumber = chapterNumber;
|
||||
VolumeNumber = volumeNumber;
|
||||
Title = title;
|
||||
}
|
||||
|
||||
[MaxLength(64)] public string ChapterId { get; init; }
|
||||
|
||||
public int? VolumeNumber { get; private set; }
|
||||
public ChapterNumber ChapterNumber { get; private set; }
|
||||
|
||||
[MaxLength(10)] public string ChapterNumber { get; private set; }
|
||||
|
||||
public string Url { get; internal set; }
|
||||
public string? Title { get; private set; }
|
||||
public string ArchiveFileName { get; private set; }
|
||||
public bool Downloaded { get; internal set; } = false;
|
||||
|
||||
|
||||
public string ParentMangaId { get; internal set; }
|
||||
public Manga? ParentManga { get; init; }
|
||||
|
||||
public Chapter(Manga parentManga, string url, ChapterNumber chapterNumber, int? volumeNumber = null, string? title = null)
|
||||
: this(parentManga.MangaId, url, chapterNumber, volumeNumber, title)
|
||||
public int CompareTo(Chapter? other)
|
||||
{
|
||||
this.ParentManga = parentManga;
|
||||
}
|
||||
|
||||
public Chapter(string parentMangaId, string url, ChapterNumber chapterNumber,
|
||||
int? volumeNumber = null, string? title = null)
|
||||
{
|
||||
this.ParentMangaId = parentMangaId;
|
||||
this.Url = url;
|
||||
this.ChapterNumber = chapterNumber;
|
||||
this.VolumeNumber = volumeNumber;
|
||||
this.Title = title;
|
||||
this.ArchiveFileName = BuildArchiveFileName();
|
||||
if (other is not { } otherChapter)
|
||||
throw new ArgumentException($"{other} can not be compared to {this}");
|
||||
return VolumeNumber?.CompareTo(otherChapter.VolumeNumber) switch
|
||||
{
|
||||
< 0 => -1,
|
||||
> 0 => 1,
|
||||
_ => CompareChapterNumbers(ChapterNumber, otherChapter.ChapterNumber)
|
||||
};
|
||||
}
|
||||
|
||||
public MoveFileOrFolderJob? UpdateChapterNumber(ChapterNumber chapterNumber)
|
||||
public MoveFileOrFolderJob? UpdateChapterNumber(string chapterNumber)
|
||||
{
|
||||
this.ChapterNumber = chapterNumber;
|
||||
ChapterNumber = chapterNumber;
|
||||
return UpdateArchiveFileName();
|
||||
}
|
||||
|
||||
public MoveFileOrFolderJob? UpdateVolumeNumber(int? volumeNumber)
|
||||
{
|
||||
this.VolumeNumber = volumeNumber;
|
||||
VolumeNumber = volumeNumber;
|
||||
return UpdateArchiveFileName();
|
||||
}
|
||||
|
||||
public MoveFileOrFolderJob? UpdateTitle(string? title)
|
||||
{
|
||||
this.Title = title;
|
||||
Title = title;
|
||||
return UpdateArchiveFileName();
|
||||
}
|
||||
|
||||
private string BuildArchiveFileName()
|
||||
{
|
||||
return $"{this.ParentManga.Name} - Vol.{this.VolumeNumber ?? 0} Ch.{this.ChapterNumber}{(this.Title is null ? "" : $" - {this.Title}")}.cbz";
|
||||
return
|
||||
$"{ParentManga.Name} - Vol.{VolumeNumber ?? 0} Ch.{ChapterNumber}{(Title is null ? "" : $" - {Title}")}.cbz";
|
||||
}
|
||||
|
||||
private MoveFileOrFolderJob? UpdateArchiveFileName()
|
||||
{
|
||||
string oldPath = GetArchiveFilePath();
|
||||
this.ArchiveFileName = BuildArchiveFileName();
|
||||
if (Downloaded)
|
||||
{
|
||||
return new MoveFileOrFolderJob(oldPath, GetArchiveFilePath());
|
||||
}
|
||||
ArchiveFileName = BuildArchiveFileName();
|
||||
if (Downloaded) return new MoveFileOrFolderJob(oldPath, GetArchiveFilePath());
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates full file path of chapter-archive
|
||||
/// Creates full file path of chapter-archive
|
||||
/// </summary>
|
||||
/// <returns>Filepath</returns>
|
||||
internal string GetArchiveFilePath()
|
||||
@ -86,27 +99,35 @@ public class Chapter : IComparable<Chapter>
|
||||
return File.Exists(path);
|
||||
}
|
||||
|
||||
public int CompareTo(Chapter? other)
|
||||
private static int CompareChapterNumbers(string ch1, string ch2)
|
||||
{
|
||||
if(other is not { } otherChapter)
|
||||
throw new ArgumentException($"{other} can not be compared to {this}");
|
||||
return this.VolumeNumber?.CompareTo(otherChapter.VolumeNumber) switch
|
||||
int[] ch1Arr = ch1.Split('.').Select(c => int.Parse(c)).ToArray();
|
||||
int[] ch2Arr = ch2.Split('.').Select(c => int.Parse(c)).ToArray();
|
||||
|
||||
int i = 0, j = 0;
|
||||
|
||||
while (i < ch1Arr.Length && j < ch2Arr.Length)
|
||||
{
|
||||
<0 => -1,
|
||||
>0 => 1,
|
||||
_ => this.ChapterNumber.CompareTo(otherChapter.ChapterNumber)
|
||||
};
|
||||
if (ch1Arr[i] < ch2Arr[j])
|
||||
return -1;
|
||||
if (ch1Arr[i] > ch2Arr[j])
|
||||
return 1;
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
internal string GetComicInfoXmlString()
|
||||
{
|
||||
XElement comicInfo = new XElement("ComicInfo",
|
||||
XElement comicInfo = new("ComicInfo",
|
||||
new XElement("Tags", string.Join(',', ParentManga.Tags.Select(tag => tag.Tag))),
|
||||
new XElement("LanguageISO", ParentManga.OriginalLanguage),
|
||||
new XElement("Title", this.Title),
|
||||
new XElement("Title", Title),
|
||||
new XElement("Writer", string.Join(',', ParentManga.Authors.Select(author => author.AuthorName))),
|
||||
new XElement("Volume", this.VolumeNumber),
|
||||
new XElement("Number", this.ChapterNumber)
|
||||
new XElement("Volume", VolumeNumber),
|
||||
new XElement("Number", ChapterNumber)
|
||||
);
|
||||
return comicInfo.ToString();
|
||||
}
|
||||
|
@ -1,305 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace API.Schema;
|
||||
|
||||
public readonly struct ChapterNumber : INumber<ChapterNumber>
|
||||
{
|
||||
private readonly uint[] _numbers;
|
||||
private readonly bool _naN;
|
||||
|
||||
private ChapterNumber(uint[] numbers, bool naN = false)
|
||||
{
|
||||
this._numbers = numbers;
|
||||
this._naN = naN;
|
||||
}
|
||||
|
||||
public ChapterNumber(string number)
|
||||
{
|
||||
if (!CanParse(number))
|
||||
{
|
||||
this._numbers = [];
|
||||
this._naN = true;
|
||||
}
|
||||
this._numbers = number.Split('.').Select(uint.Parse).ToArray();
|
||||
}
|
||||
|
||||
public ChapterNumber(float number) : this(number.ToString("F")) {}
|
||||
|
||||
public ChapterNumber(double number) : this((float)number) {}
|
||||
|
||||
public ChapterNumber(uint number)
|
||||
{
|
||||
this._numbers = [number];
|
||||
this._naN = false;
|
||||
}
|
||||
|
||||
public ChapterNumber(int number)
|
||||
{
|
||||
if (int.IsNegative(number))
|
||||
{
|
||||
this._numbers = [];
|
||||
this._naN = true;
|
||||
}
|
||||
this._numbers = [(uint)number];
|
||||
this._naN = false;
|
||||
}
|
||||
|
||||
public int CompareTo(ChapterNumber other)
|
||||
{
|
||||
byte index = 0;
|
||||
do
|
||||
{
|
||||
if (this._numbers[index] < other._numbers[index])
|
||||
return -1;
|
||||
else if (this._numbers[index] > other._numbers[index])
|
||||
return 1;
|
||||
}while(index < this._numbers.Length && index < other._numbers.Length);
|
||||
|
||||
if (index >= this._numbers.Length && index >= other._numbers.Length)
|
||||
return 0;
|
||||
else if (index >= this._numbers.Length)
|
||||
return -1;
|
||||
else if (index >= other._numbers.Length)
|
||||
return 1;
|
||||
throw new UnreachableException();
|
||||
}
|
||||
|
||||
private static readonly Regex Pattern = new(@"[0-9]+(?:\.[0-9]+)*");
|
||||
public static bool CanParse(string? number) => number is not null && Pattern.Match(number).Length == number.Length && number.Length > 0;
|
||||
|
||||
public bool Equals(ChapterNumber other) => CompareTo(other) == 0;
|
||||
|
||||
public string ToString(string? format, IFormatProvider? formatProvider)
|
||||
{
|
||||
return string.Join('.', _numbers);
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is ChapterNumber other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(_numbers, _naN);
|
||||
}
|
||||
|
||||
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
if(obj is ChapterNumber other)
|
||||
return CompareTo(other);
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
public static ChapterNumber Parse(string s, IFormatProvider? provider)
|
||||
{
|
||||
if(!CanParse(s))
|
||||
throw new FormatException($"Invalid ChapterNumber-String: {s}");
|
||||
return new ChapterNumber(s);
|
||||
}
|
||||
|
||||
public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out ChapterNumber result)
|
||||
{
|
||||
result = new ChapterNumber([], true);;
|
||||
if (!CanParse(s))
|
||||
return false;
|
||||
if (s is null)
|
||||
return false;
|
||||
result = new ChapterNumber(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ChapterNumber Parse(ReadOnlySpan<char> s, IFormatProvider? provider) => Parse(s.ToString(), provider);
|
||||
|
||||
public static bool TryParse(ReadOnlySpan<char> s, IFormatProvider? provider, out ChapterNumber result) => TryParse(s.ToString(), provider, out result);
|
||||
|
||||
public static ChapterNumber operator +(ChapterNumber left, ChapterNumber right)
|
||||
{
|
||||
if (IsNaN(left) || IsNaN(right))
|
||||
return new ChapterNumber([], true);
|
||||
int size = left._numbers.Length > right._numbers.Length ? left._numbers.Length : right._numbers.Length;
|
||||
uint[] numbers = new uint[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if(left._numbers.Length < i)
|
||||
numbers[i] = right._numbers[i];
|
||||
else if(right._numbers.Length < i)
|
||||
numbers[i] = left._numbers[i];
|
||||
else
|
||||
numbers[i] = left._numbers[i] + right._numbers[i];
|
||||
}
|
||||
return new ChapterNumber(numbers);
|
||||
}
|
||||
|
||||
private static bool BothNotNaN(ChapterNumber left, ChapterNumber right) => !IsNaN(left) && !IsNaN(right);
|
||||
|
||||
public static ChapterNumber AdditiveIdentity => Zero;
|
||||
|
||||
public static bool operator ==(ChapterNumber left, ChapterNumber right) => BothNotNaN(left, right) && left.Equals(right);
|
||||
|
||||
public static bool operator !=(ChapterNumber left, ChapterNumber right) => !(left == right);
|
||||
|
||||
public static bool operator >(ChapterNumber left, ChapterNumber right) => BothNotNaN(left, right) && left.CompareTo(right) > 0;
|
||||
|
||||
public static bool operator >=(ChapterNumber left, ChapterNumber right) => BothNotNaN(left, right) && left.CompareTo(right) >= 0;
|
||||
|
||||
public static bool operator <(ChapterNumber left, ChapterNumber right) => BothNotNaN(left, right) && left.CompareTo(right) < 0;
|
||||
|
||||
public static bool operator <=(ChapterNumber left, ChapterNumber right) => BothNotNaN(left, right) && left.CompareTo(right) <= 0;
|
||||
|
||||
public static ChapterNumber operator %(ChapterNumber left, ChapterNumber right) => throw new ArithmeticException();
|
||||
|
||||
public static ChapterNumber operator +(ChapterNumber value) => throw new InvalidOperationException();
|
||||
|
||||
public static ChapterNumber operator --(ChapterNumber value)
|
||||
{
|
||||
if (IsNaN(value))
|
||||
return value;
|
||||
uint[] numbers = value._numbers;
|
||||
numbers[0]--;
|
||||
return new ChapterNumber(numbers);
|
||||
}
|
||||
|
||||
public static ChapterNumber operator /(ChapterNumber left, ChapterNumber right) => throw new InvalidOperationException();
|
||||
|
||||
public static ChapterNumber operator ++(ChapterNumber value)
|
||||
{
|
||||
if (IsNaN(value))
|
||||
return value;
|
||||
uint[] numbers = value._numbers;
|
||||
numbers[0]++;
|
||||
return new ChapterNumber(numbers);
|
||||
}
|
||||
|
||||
public static ChapterNumber MultiplicativeIdentity => One;
|
||||
public static ChapterNumber operator *(ChapterNumber left, ChapterNumber right) => throw new InvalidOperationException();
|
||||
|
||||
public static ChapterNumber operator -(ChapterNumber left, ChapterNumber right) => throw new InvalidOperationException();
|
||||
|
||||
public static ChapterNumber operator -(ChapterNumber value) => throw new InvalidOperationException();
|
||||
|
||||
public static ChapterNumber Abs(ChapterNumber value) => value;
|
||||
|
||||
public static bool IsCanonical(ChapterNumber value) => true;
|
||||
|
||||
public static bool IsComplexNumber(ChapterNumber value) => false;
|
||||
|
||||
public static bool IsEvenInteger(ChapterNumber value) => IsInteger(value) && uint.IsEvenInteger(value._numbers[0]);
|
||||
|
||||
public static bool IsFinite(ChapterNumber value) => true;
|
||||
|
||||
public static bool IsImaginaryNumber(ChapterNumber value) => false;
|
||||
|
||||
public static bool IsInfinity(ChapterNumber value) => false;
|
||||
|
||||
public static bool IsInteger(ChapterNumber value) => !IsNaN(value) && value._numbers.Length == 1;
|
||||
|
||||
public static bool IsNaN(ChapterNumber value) => value._naN;
|
||||
|
||||
public static bool IsNegative(ChapterNumber value) => false;
|
||||
|
||||
public static bool IsNegativeInfinity(ChapterNumber value) => false;
|
||||
|
||||
public static bool IsNormal(ChapterNumber value) => true;
|
||||
|
||||
public static bool IsOddInteger(ChapterNumber value) => false;
|
||||
|
||||
public static bool IsPositive(ChapterNumber value) => true;
|
||||
|
||||
public static bool IsPositiveInfinity(ChapterNumber value) => false;
|
||||
|
||||
public static bool IsRealNumber(ChapterNumber value) => false;
|
||||
|
||||
public static bool IsSubnormal(ChapterNumber value) => false;
|
||||
|
||||
public static bool IsZero(ChapterNumber value) => value._numbers.All(n => n == 0);
|
||||
|
||||
public static ChapterNumber MaxMagnitude(ChapterNumber x, ChapterNumber y)
|
||||
{
|
||||
if(IsNaN(x))
|
||||
return new ChapterNumber([], true);
|
||||
if (IsNaN(y))
|
||||
return new ChapterNumber([], true);
|
||||
return x >= y ? x : y;
|
||||
}
|
||||
|
||||
public static ChapterNumber MaxMagnitudeNumber(ChapterNumber x, ChapterNumber y)
|
||||
{
|
||||
if (IsNaN(x))
|
||||
return y;
|
||||
if (IsNaN(y))
|
||||
return x;
|
||||
return x >= y ? x : y;
|
||||
}
|
||||
|
||||
public static ChapterNumber MinMagnitude(ChapterNumber x, ChapterNumber y)
|
||||
{
|
||||
if(IsNaN(x))
|
||||
return new ChapterNumber([], true);
|
||||
if (IsNaN(y))
|
||||
return new ChapterNumber([], true);
|
||||
return x <= y ? x : y;
|
||||
}
|
||||
|
||||
public static ChapterNumber MinMagnitudeNumber(ChapterNumber x, ChapterNumber y)
|
||||
{
|
||||
if (IsNaN(x))
|
||||
return y;
|
||||
if (IsNaN(y))
|
||||
return x;
|
||||
return x <= y ? x : y;
|
||||
}
|
||||
|
||||
public static ChapterNumber Parse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider? provider) => throw new NotImplementedException();
|
||||
|
||||
public static ChapterNumber Parse(string s, NumberStyles style, IFormatProvider? provider) => throw new NotImplementedException();
|
||||
|
||||
public static bool TryConvertFromChecked<TOther>(TOther value, out ChapterNumber result) where TOther : INumberBase<TOther>
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static bool TryConvertFromSaturating<TOther>(TOther value, out ChapterNumber result) where TOther : INumberBase<TOther>
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static bool TryConvertFromTruncating<TOther>(TOther value, out ChapterNumber result) where TOther : INumberBase<TOther>
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static bool TryConvertToChecked<TOther>(ChapterNumber value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase<TOther>
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static bool TryConvertToSaturating<TOther>(ChapterNumber value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase<TOther>
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static bool TryConvertToTruncating<TOther>(ChapterNumber value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase<TOther>
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider? provider, out ChapterNumber result)
|
||||
=> TryParse(s.ToString(), style, provider, out result);
|
||||
|
||||
public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out ChapterNumber result)
|
||||
=> TryParse(s, provider, out result);
|
||||
|
||||
public static ChapterNumber One => new(1);
|
||||
public static int Radix => 10;
|
||||
public static ChapterNumber Zero => new(0);
|
||||
}
|
@ -12,7 +12,7 @@ using static System.IO.UnixFileMode;
|
||||
namespace API.Schema.Jobs;
|
||||
|
||||
public class DownloadMangaCoverJob(string chapterId, string? parentJobId = null, ICollection<string>? dependsOnJobsIds = null)
|
||||
: Job(TokenGen.CreateToken(typeof(DownloadMangaCoverJob), 64), JobType.DownloadMangaCoverJob, 0, parentJobId, dependsOnJobsIds)
|
||||
: Job(TokenGen.CreateToken(typeof(DownloadMangaCoverJob), ""), JobType.DownloadMangaCoverJob, 0, parentJobId, dependsOnJobsIds)
|
||||
{
|
||||
[MaxLength(64)]
|
||||
public string ChapterId { get; init; } = chapterId;
|
||||
|
@ -4,7 +4,7 @@ using API.Schema.MangaConnectors;
|
||||
namespace API.Schema.Jobs;
|
||||
|
||||
public class DownloadNewChaptersJob(ulong recurrenceMs, string mangaId, string? parentJobId = null, ICollection<string>? dependsOnJobsIds = null)
|
||||
: Job(TokenGen.CreateToken(typeof(DownloadNewChaptersJob), 64), JobType.DownloadNewChaptersJob, recurrenceMs, parentJobId, dependsOnJobsIds)
|
||||
: Job(TokenGen.CreateToken(typeof(DownloadNewChaptersJob), ""), JobType.DownloadNewChaptersJob, recurrenceMs, parentJobId, dependsOnJobsIds)
|
||||
{
|
||||
[MaxLength(64)]
|
||||
public string MangaId { get; init; } = mangaId;
|
||||
|
@ -12,7 +12,7 @@ using static System.IO.UnixFileMode;
|
||||
namespace API.Schema.Jobs;
|
||||
|
||||
public class DownloadSingleChapterJob(string chapterId, string? parentJobId = null, ICollection<string>? dependsOnJobsIds = null)
|
||||
: Job(TokenGen.CreateToken(typeof(DownloadSingleChapterJob), 64), JobType.DownloadSingleChapterJob, 0, parentJobId, dependsOnJobsIds)
|
||||
: Job(TokenGen.CreateToken(typeof(DownloadSingleChapterJob), ""), JobType.DownloadSingleChapterJob, 0, parentJobId, dependsOnJobsIds)
|
||||
{
|
||||
[MaxLength(64)]
|
||||
public string ChapterId { get; init; } = chapterId;
|
||||
|
@ -1,7 +1,7 @@
|
||||
namespace API.Schema.Jobs;
|
||||
|
||||
public class MoveFileOrFolderJob(string fromLocation, string toLocation, string? parentJobId = null, ICollection<string>? dependsOnJobsIds = null)
|
||||
: Job(TokenGen.CreateToken(typeof(MoveFileOrFolderJob), 64), JobType.MoveFileOrFolderJob, 0, parentJobId, dependsOnJobsIds)
|
||||
: Job(TokenGen.CreateToken(typeof(MoveFileOrFolderJob), ""), JobType.MoveFileOrFolderJob, 0, parentJobId, dependsOnJobsIds)
|
||||
{
|
||||
public string FromLocation { get; init; } = fromLocation;
|
||||
public string ToLocation { get; init; } = toLocation;
|
||||
|
@ -1,9 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using API.Schema.MangaConnectors;
|
||||
|
||||
namespace API.Schema.Jobs;
|
||||
|
||||
public class UpdateMetadataJob(ulong recurrenceMs, string mangaId, string? parentJobId = null, ICollection<string>? dependsOnJobsIds = null)
|
||||
: Job(TokenGen.CreateToken(typeof(UpdateMetadataJob), 64), JobType.UpdateMetaDataJob, recurrenceMs, parentJobId, dependsOnJobsIds)
|
||||
: Job(TokenGen.CreateToken(typeof(UpdateMetadataJob), ""), JobType.UpdateMetaDataJob, recurrenceMs, parentJobId, dependsOnJobsIds)
|
||||
{
|
||||
[MaxLength(64)]
|
||||
public string MangaId { get; init; } = mangaId;
|
||||
|
@ -6,7 +6,7 @@ namespace API.Schema.LibraryConnectors;
|
||||
public class Kavita : LibraryConnector
|
||||
{
|
||||
|
||||
public Kavita(string baseUrl, string auth) : base(TokenGen.CreateToken(typeof(Kavita), 64), LibraryType.Kavita, baseUrl, auth)
|
||||
public Kavita(string baseUrl, string auth) : base(TokenGen.CreateToken(typeof(Kavita), baseUrl), LibraryType.Kavita, baseUrl, auth)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ namespace API.Schema.LibraryConnectors;
|
||||
|
||||
public class Komga : LibraryConnector
|
||||
{
|
||||
public Komga(string baseUrl, string auth) : base(TokenGen.CreateToken(typeof(Komga), 64), LibraryType.Komga,
|
||||
public Komga(string baseUrl, string auth) : base(TokenGen.CreateToken(typeof(Komga), baseUrl), LibraryType.Komga,
|
||||
baseUrl, auth)
|
||||
{
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ namespace API.Schema;
|
||||
public class Link(string linkProvider, string linkUrl)
|
||||
{
|
||||
[MaxLength(64)]
|
||||
public string LinkId { get; init; } = TokenGen.CreateToken(typeof(Link), 64);
|
||||
public string LinkId { get; init; } = TokenGen.CreateToken(typeof(Link), string.Join(linkProvider, linkUrl));
|
||||
public string LinkProvider { get; init; } = linkProvider;
|
||||
public string LinkUrl { get; init; } = linkUrl;
|
||||
|
||||
|
@ -14,7 +14,7 @@ namespace API.Schema;
|
||||
public class Manga
|
||||
{
|
||||
[MaxLength(64)]
|
||||
public string MangaId { get; init; } = TokenGen.CreateToken(typeof(Manga), 64);
|
||||
public string MangaId { get; init; }
|
||||
[MaxLength(64)]
|
||||
public string ConnectorId { get; init; }
|
||||
|
||||
@ -57,6 +57,7 @@ public class Manga
|
||||
string? coverFileNameInCache, uint year, string? originalLanguage, MangaReleaseStatus releaseStatus,
|
||||
float ignoreChapterBefore, string mangaConnectorId)
|
||||
{
|
||||
MangaId = TokenGen.CreateToken(typeof(Manga), string.Join(MangaConnectorId, ConnectorId));
|
||||
ConnectorId = connectorId;
|
||||
Name = name;
|
||||
Description = description;
|
||||
|
@ -8,7 +8,7 @@ namespace API.Schema;
|
||||
public class MangaAltTitle(string language, string title)
|
||||
{
|
||||
[MaxLength(64)]
|
||||
public string AltTitleId { get; init; } = TokenGen.CreateToken("AltTitle", 64);
|
||||
public string AltTitleId { get; init; } = TokenGen.CreateToken("AltTitle", string.Join(language, title));
|
||||
[MaxLength(8)]
|
||||
public string Language { get; init; } = language;
|
||||
public string Title { get; set; } = title;
|
||||
|
@ -152,9 +152,7 @@ public class AsuraToon : MangaConnector
|
||||
string chapterUrl = chapterInfo.GetAttributeValue("href", "");
|
||||
|
||||
Match match = infoRex.Match(chapterInfo.InnerText);
|
||||
if(!ChapterNumber.CanParse(match.Groups[1].Value))
|
||||
continue;
|
||||
ChapterNumber chapterNumber = new(match.Groups[1].Value);
|
||||
string chapterNumber = new(match.Groups[1].Value);
|
||||
string? chapterName = match.Groups[2].Success && match.Groups[2].Length > 1 ? match.Groups[2].Value : null;
|
||||
string url = $"https://asuracomic.net/series/{chapterUrl}";
|
||||
try
|
||||
|
@ -159,9 +159,7 @@ public class Bato : MangaConnector
|
||||
Match match = numberRex.Match(chapterUrl);
|
||||
string id = match.Groups[1].Value;
|
||||
int? volumeNumber = match.Groups[2].Success ? int.Parse(match.Groups[2].Value) : null;
|
||||
if(ChapterNumber.CanParse(match.Groups[3].Value))
|
||||
continue;
|
||||
ChapterNumber chapterNumber = new(match.Groups[3].Value);
|
||||
string chapterNumber = new(match.Groups[3].Value);
|
||||
string url = $"https://bato.to{chapterUrl}?load=2";
|
||||
try
|
||||
{
|
||||
|
@ -229,9 +229,7 @@ public class MangaDex : MangaConnector
|
||||
? attributes["chapter"]!.GetValue<string>()
|
||||
: null;
|
||||
|
||||
if(chapterNumStr is null || ChapterNumber.CanParse(chapterNumStr))
|
||||
continue;
|
||||
ChapterNumber chapterNumber = new(chapterNumStr);
|
||||
string chapterNumber = new(chapterNumStr);
|
||||
|
||||
|
||||
if (attributes.ContainsKey("pages") && attributes["pages"] is not null &&
|
||||
|
@ -128,9 +128,7 @@ public class MangaHere : MangaConnector
|
||||
Match rexMatch = chapterRex.Match(url);
|
||||
|
||||
int? volumeNumber = rexMatch.Groups[1].Value == "TBD" ? null : int.Parse(rexMatch.Groups[1].Value);
|
||||
if(!ChapterNumber.CanParse(rexMatch.Groups[2].Value))
|
||||
continue;
|
||||
ChapterNumber chapterNumber = new(rexMatch.Groups[2].Value);
|
||||
string chapterNumber = new(rexMatch.Groups[2].Value);
|
||||
string fullUrl = $"https://www.mangahere.cc{url}";
|
||||
|
||||
try
|
||||
|
@ -185,9 +185,8 @@ public class MangaKatana : MangaConnector
|
||||
.GetAttributeValue("href", "");
|
||||
|
||||
int? volumeNumber = volumeRex.IsMatch(url) ? int.Parse(volumeRex.Match(url).Groups[1].Value) : null;
|
||||
if(!ChapterNumber.CanParse(chapterNumRex.Match(url).Groups[1].Value))
|
||||
continue;
|
||||
ChapterNumber chapterNumber = new(chapterNumRex.Match(url).Groups[1].Value);
|
||||
|
||||
string chapterNumber = new(chapterNumRex.Match(url).Groups[1].Value);
|
||||
string chapterName = chapterNameRex.Match(fullString).Groups[1].Value;
|
||||
try
|
||||
{
|
||||
|
@ -151,9 +151,8 @@ public class MangaLife : MangaConnector
|
||||
? int.Parse(rexMatch.Groups[3].Value)
|
||||
: null;
|
||||
|
||||
if(!ChapterNumber.CanParse(rexMatch.Groups[1].Value))
|
||||
continue;
|
||||
ChapterNumber chapterNumber = new(rexMatch.Groups[1].Value);
|
||||
|
||||
string chapterNumber = new(rexMatch.Groups[1].Value);
|
||||
string fullUrl = $"https://manga4life.com{url}";
|
||||
fullUrl = fullUrl.Replace(Regex.Match(url,"(-page-[0-9])").Value,"");
|
||||
try
|
||||
|
@ -181,9 +181,7 @@ public class Manganato : MangaConnector
|
||||
int? volumeNumber = volRex.IsMatch(fullString)
|
||||
? int.Parse(volRex.Match(fullString).Groups[1].Value)
|
||||
: null;
|
||||
if(!ChapterNumber.CanParse(chapterRex.Match(url).Groups[1].Value))
|
||||
continue;
|
||||
ChapterNumber chapterNumber = new(chapterRex.Match(url).Groups[1].Value);
|
||||
string chapterNumber = new(chapterRex.Match(url).Groups[1].Value);
|
||||
string chapterName = nameRex.Match(fullString).Groups[3].Value;
|
||||
try
|
||||
{
|
||||
|
@ -158,9 +158,8 @@ public class Mangaworld : MangaConnector
|
||||
{
|
||||
|
||||
string numberStr = chapterRex.Match(chNode.SelectSingleNode("a").SelectSingleNode("span").InnerText).Groups[1].Value;
|
||||
if(!ChapterNumber.CanParse(numberStr))
|
||||
continue;
|
||||
ChapterNumber chapterNumber = new(numberStr);
|
||||
|
||||
string chapterNumber = new(numberStr);
|
||||
string url = chNode.SelectSingleNode("a").GetAttributeValue("href", "");
|
||||
string id = idRex.Match(chNode.SelectSingleNode("a").GetAttributeValue("href", "")).Groups[1].Value;
|
||||
try
|
||||
@ -178,9 +177,8 @@ public class Mangaworld : MangaConnector
|
||||
foreach (HtmlNode chNode in chaptersWrapper.SelectNodes("div").Where(node => node.HasClass("chapter")))
|
||||
{
|
||||
string numberStr = chapterRex.Match(chNode.SelectSingleNode("a").SelectSingleNode("span").InnerText).Groups[1].Value;
|
||||
if(!ChapterNumber.CanParse(numberStr))
|
||||
continue;
|
||||
ChapterNumber chapterNumber = new(numberStr);
|
||||
|
||||
string chapterNumber = new(numberStr);
|
||||
string url = chNode.SelectSingleNode("a").GetAttributeValue("href", "");
|
||||
string id = idRex.Match(chNode.SelectSingleNode("a").GetAttributeValue("href", "")).Groups[1].Value;
|
||||
try
|
||||
|
@ -148,9 +148,7 @@ public class ManhuaPlus : MangaConnector
|
||||
{
|
||||
Match rexMatch = urlRex.Match(url);
|
||||
|
||||
if(!ChapterNumber.CanParse(rexMatch.Groups[1].Value))
|
||||
continue;
|
||||
ChapterNumber chapterNumber = new(rexMatch.Groups[1].Value);
|
||||
string chapterNumber = new(rexMatch.Groups[1].Value);
|
||||
string fullUrl = url;
|
||||
try
|
||||
{
|
||||
|
@ -157,7 +157,7 @@ public class Weebcentral : MangaConnector
|
||||
|
||||
public override Chapter[] GetChapters(Manga manga, string language = "en")
|
||||
{
|
||||
var requestUrl = $"{_baseUrl}/series/{manga.MangaId}/full-chapter-list";
|
||||
var requestUrl = $"{_baseUrl}/series/{manga.ConnectorId}/full-chapter-list";
|
||||
var requestResult =
|
||||
downloadClient.MakeRequest(requestUrl, RequestType.Default);
|
||||
if ((int)requestResult.statusCode < 200 || (int)requestResult.statusCode >= 300)
|
||||
@ -182,7 +182,7 @@ public class Weebcentral : MangaConnector
|
||||
var url = elem.GetAttributeValue("href", "") ?? "Undefined";
|
||||
|
||||
if (!url.StartsWith("https://") && !url.StartsWith("http://"))
|
||||
return new Chapter(manga, "undefined", new ChapterNumber(-1), null, null);
|
||||
return new Chapter(manga, "undefined", "-1", null, null);
|
||||
|
||||
var idMatch = idRex.Match(url);
|
||||
var id = idMatch.Success ? idMatch.Groups[1].Value : null;
|
||||
@ -192,12 +192,13 @@ public class Weebcentral : MangaConnector
|
||||
|
||||
var chapterNumberMatch = chapterRex.Match(chapterNode);
|
||||
|
||||
if(!chapterNumberMatch.Success || !ChapterNumber.CanParse(chapterNumberMatch.Groups[1].Value))
|
||||
return new Chapter(manga, "undefined", new ChapterNumber(-1), null, null);
|
||||
ChapterNumber chapterNumber = new(chapterNumberMatch.Groups[1].Value);
|
||||
if(!chapterNumberMatch.Success)
|
||||
return new Chapter(manga, "undefined", "-1", null, null);
|
||||
|
||||
return new Chapter(manga, url, chapterNumber, null, null);
|
||||
}).Where(elem => elem.ChapterNumber < ChapterNumber.Zero && elem.Url != "undefined").ToList();
|
||||
string chapterNumber = new(chapterNumberMatch.Groups[1].Value);
|
||||
var chapter = new Chapter(manga, url, chapterNumber, null, null);
|
||||
return chapter;
|
||||
}).Where(elem => elem.ChapterNumber.CompareTo("-1") != 0 && elem.Url != "undefined").ToList();
|
||||
|
||||
ret.Reverse();
|
||||
return ret;
|
||||
|
@ -7,7 +7,7 @@ namespace API.Schema;
|
||||
public class Notification(string title, string message = "", NotificationUrgency urgency = NotificationUrgency.Normal, DateTime? date = null)
|
||||
{
|
||||
[MaxLength(64)]
|
||||
public string NotificationId { get; init; } = TokenGen.CreateToken("Notification", 64);
|
||||
public string NotificationId { get; init; } = TokenGen.CreateToken("Notification", "");
|
||||
|
||||
public NotificationUrgency Urgency { get; init; } = urgency;
|
||||
|
||||
|
@ -4,7 +4,7 @@ using Newtonsoft.Json;
|
||||
namespace API.Schema.NotificationConnectors;
|
||||
|
||||
public class Gotify(string endpoint, string appToken)
|
||||
: NotificationConnector(TokenGen.CreateToken(typeof(Gotify), 64), NotificationConnectorType.Gotify)
|
||||
: NotificationConnector(TokenGen.CreateToken(typeof(Gotify), endpoint), NotificationConnectorType.Gotify)
|
||||
{
|
||||
public string Endpoint { get; init; } = endpoint;
|
||||
public string AppToken { get; init; } = appToken;
|
||||
|
@ -4,7 +4,7 @@ using Newtonsoft.Json;
|
||||
namespace API.Schema.NotificationConnectors;
|
||||
|
||||
public class Lunasea(string id)
|
||||
: NotificationConnector(TokenGen.CreateToken(typeof(Lunasea), 64), NotificationConnectorType.LunaSea)
|
||||
: NotificationConnector(TokenGen.CreateToken(typeof(Lunasea), id), NotificationConnectorType.LunaSea)
|
||||
{
|
||||
public string Id { get; init; } = id;
|
||||
public override void SendNotification(string title, string notificationText)
|
||||
|
@ -11,7 +11,7 @@ public class Ntfy : NotificationConnector
|
||||
public string Auth { get; init; }
|
||||
public string Topic { get; init; }
|
||||
|
||||
public Ntfy(string endpoint, string auth, string topic): base(TokenGen.CreateToken(typeof(Ntfy), 64), NotificationConnectorType.Ntfy)
|
||||
public Ntfy(string endpoint, string auth, string topic): base(TokenGen.CreateToken(typeof(Ntfy), endpoint), NotificationConnectorType.Ntfy)
|
||||
{
|
||||
Endpoint = endpoint;
|
||||
Auth = auth;
|
||||
|
Reference in New Issue
Block a user