208 lines
7.1 KiB
C#
208 lines
7.1 KiB
C#
using MangaReader.Core.Common;
|
|
using MangaReader.Core.Metadata;
|
|
using MangaReader.Core.Sources.MangaDex.Api;
|
|
|
|
namespace MangaReader.Core.Sources.MangaDex.Metadata;
|
|
|
|
public class MangaDexMetadataProvider(IMangaDexClient mangaDexClient) : IMangaMetadataProvider
|
|
{
|
|
public string SourceId => "MangaDex";
|
|
|
|
public async Task<SourceManga?> GetMangaAsync(string url, CancellationToken cancellationToken)
|
|
{
|
|
Guid mangaGuid = GetSourceMangaGuid(url);
|
|
MangaDexResponse? mangaDexResponse = await mangaDexClient.GetMangaAsync(mangaGuid, cancellationToken);
|
|
|
|
if (mangaDexResponse == null || mangaDexResponse is not MangaDexEntityResponse mangaDexEntityResponse)
|
|
return null;
|
|
|
|
if (mangaDexEntityResponse.Data == null || mangaDexEntityResponse.Data is not MangaEntity mangaEntity)
|
|
return null;
|
|
|
|
if (mangaEntity.Attributes == null)
|
|
return null;
|
|
|
|
MangaAttributes mangaAttributes = mangaEntity.Attributes;
|
|
List<MangaDexEntity> mangaRelationships = mangaEntity.Relationships;
|
|
MangaDexResponse? mangaDexFeedResponse = await mangaDexClient.GetFeedAsync(mangaGuid, cancellationToken);
|
|
MangaDexResponse? coverArtResponse = await mangaDexClient.GetCoverArtAsync(mangaGuid, cancellationToken);
|
|
|
|
return new SourceManga()
|
|
{
|
|
Title = GetTitle(mangaAttributes),
|
|
AlternateTitles = GetAlternateTitles(mangaAttributes),
|
|
Genres = GetGenres(mangaAttributes),
|
|
Contributors = GetContributors(mangaRelationships),
|
|
Chapters = GetChapters(mangaDexFeedResponse),
|
|
CoverArt = GetCoverArt(mangaGuid, coverArtResponse)
|
|
};
|
|
}
|
|
|
|
private static Guid GetSourceMangaGuid(string url)
|
|
{
|
|
string[] parts = url.Split('/');
|
|
|
|
if (parts.Length < 5 || Guid.TryParse(parts[4], out Guid mangaGuid) == false)
|
|
{
|
|
throw new Exception("Unable to get guid from MangaDex url: " + url);
|
|
}
|
|
|
|
return mangaGuid;
|
|
}
|
|
|
|
private static string GetTitle(MangaAttributes attributes)
|
|
{
|
|
if (attributes.Title.TryGetValue("en", out string? title))
|
|
return title;
|
|
|
|
return string.Empty;
|
|
}
|
|
|
|
private static List<SourceMangaTitle> GetAlternateTitles(MangaAttributes attributes)
|
|
{
|
|
if (attributes.AltTitles == null || attributes.AltTitles.Count == 0)
|
|
return [];
|
|
|
|
Dictionary<string, Language> languageIdMap = new()
|
|
{
|
|
{ "en", Language.English },
|
|
{ "ja", Language.Japanese },
|
|
{ "ja-ro", Language.Romaji },
|
|
};
|
|
|
|
List<SourceMangaTitle> sourceMangaTitles = [];
|
|
|
|
foreach (Dictionary<string, string> alternateTitle in attributes.AltTitles)
|
|
{
|
|
foreach (string alternateTitleKey in alternateTitle.Keys)
|
|
{
|
|
if (languageIdMap.TryGetValue(alternateTitleKey, out Language language) == false)
|
|
continue;
|
|
|
|
SourceMangaTitle sourceMangaTitle = new()
|
|
{
|
|
Title = alternateTitle[alternateTitleKey],
|
|
Language = language
|
|
};
|
|
|
|
sourceMangaTitles.Add(sourceMangaTitle);
|
|
}
|
|
}
|
|
|
|
return sourceMangaTitles;
|
|
}
|
|
|
|
private static List<string> GetGenres(MangaAttributes attributes)
|
|
{
|
|
if (attributes.Tags == null || attributes.Tags.Count == 0)
|
|
return [];
|
|
|
|
List<string> tags = [];
|
|
|
|
foreach (TagEntity tagEntity in attributes.Tags)
|
|
{
|
|
if (tagEntity.Attributes == null)
|
|
continue;
|
|
|
|
if (tagEntity.Attributes.Name == null || tagEntity.Attributes.Name.Count == 0)
|
|
continue;
|
|
|
|
tags.Add(tagEntity.Attributes.Name.FirstOrDefault().Value);
|
|
}
|
|
|
|
return tags;
|
|
}
|
|
|
|
private static SourceMangaContributor[] GetContributors(List<MangaDexEntity> relationships)
|
|
{
|
|
List<SourceMangaContributor> contributors = [];
|
|
|
|
AuthorEntity[] authorEntities = [.. relationships.Where(entity => entity is AuthorEntity).Cast<AuthorEntity>()];
|
|
ArtistEntity[] artistEntities = [.. relationships.Where(entity => entity is ArtistEntity).Cast<ArtistEntity>()];
|
|
|
|
foreach (AuthorEntity authorEntity in authorEntities)
|
|
{
|
|
if (authorEntity.Attributes == null)
|
|
continue;
|
|
|
|
SourceMangaContributor contributor = new()
|
|
{
|
|
Name = authorEntity.Attributes.Name,
|
|
Role = SourceMangaContributorRole.Author
|
|
};
|
|
|
|
contributors.Add(contributor);
|
|
}
|
|
|
|
foreach (ArtistEntity artistEntity in artistEntities)
|
|
{
|
|
if (artistEntity.Attributes == null)
|
|
continue;
|
|
|
|
SourceMangaContributor contributor = new()
|
|
{
|
|
Name = artistEntity.Attributes.Name,
|
|
Role = SourceMangaContributorRole.Artist
|
|
};
|
|
|
|
contributors.Add(contributor);
|
|
}
|
|
|
|
return [.. contributors];
|
|
}
|
|
|
|
private static List<SourceMangaChapter> GetChapters(MangaDexResponse? mangaDexFeedResponse)
|
|
{
|
|
if (mangaDexFeedResponse == null || mangaDexFeedResponse is not MangaDexCollectionResponse collectionResponse)
|
|
return [];
|
|
|
|
//https://mangadex.org/chapter/46084762-855c-46dd-a7b6-66e5cd15604d
|
|
|
|
List<SourceMangaChapter> chapters = [];
|
|
ChapterEntity[] chapterEntities = [.. collectionResponse.Data.Where(entity => entity is ChapterEntity).Cast<ChapterEntity>()];
|
|
|
|
foreach (ChapterEntity chapterEntity in chapterEntities)
|
|
{
|
|
if (chapterEntity.Attributes == null || chapterEntity.Attributes.TranslatedLanguage != "en")
|
|
continue;
|
|
|
|
int? volume = int.TryParse(chapterEntity.Attributes.Volume, out var temp) ? temp : null;
|
|
|
|
if (float.TryParse(chapterEntity.Attributes.Chapter, out float chapterNumber) == false)
|
|
continue;
|
|
|
|
SourceMangaChapter chapter = new()
|
|
{
|
|
Volume = volume,
|
|
Number = chapterNumber,
|
|
Title = chapterEntity.Attributes.Title,
|
|
Url = $"https://mangadex.org/chapter/{chapterEntity.Id}"
|
|
};
|
|
|
|
chapters.Add(chapter);
|
|
}
|
|
|
|
return chapters;
|
|
}
|
|
|
|
private static string[] GetCoverArt(Guid mangaGuid, MangaDexResponse? coverArtResponse)
|
|
{
|
|
if (coverArtResponse == null || coverArtResponse is not MangaDexCollectionResponse collectionResponse)
|
|
return [];
|
|
|
|
List<string> coverArtUrls = [];
|
|
CoverArtEntity[] coverArtEntities = [.. collectionResponse.Data.Where(entity => entity is CoverArtEntity).Cast<CoverArtEntity>()];
|
|
|
|
foreach (CoverArtEntity coverArtEntity in coverArtEntities)
|
|
{
|
|
if (coverArtEntity.Attributes == null || string.IsNullOrWhiteSpace(coverArtEntity.Attributes.FileName))
|
|
continue;
|
|
|
|
string url = $"https://mangadex.org/covers/{mangaGuid}/{coverArtEntity.Attributes.FileName}";
|
|
|
|
coverArtUrls.Add(url);
|
|
}
|
|
|
|
return [.. coverArtUrls];
|
|
}
|
|
} |