From 6878d12b5c5718a798f5c4ec6b121bb2fb282605 Mon Sep 17 00:00:00 2001 From: aayush262 Date: Mon, 27 May 2024 23:09:19 +0530 Subject: [PATCH] feat: more thumbnails --- .../connections/anilist/AnilistQueries.kt | 4 ++-- .../dantotsu/connections/anilist/api/Media.kt | 15 ++++++++++++++- app/src/main/java/ani/dantotsu/media/Media.kt | 3 ++- .../dantotsu/media/anime/AnimeWatchFragment.kt | 18 ++++++++++++++++-- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt index aa6db416..480f3c7d 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistQueries.kt @@ -75,7 +75,7 @@ class AnilistQueries { media.cameFromContinue = false val query = - """{Media(id:${media.id}){id favourites popularity episodes chapters mediaListEntry{id status score(format:POINT_100)progress private notes repeat customLists updatedAt startedAt{year month day}completedAt{year month day}}reviews(perPage:3, sort:SCORE_DESC){nodes{id mediaId mediaType summary body(asHtml:true) rating ratingAmount userRating score private siteUrl createdAt updatedAt user{id name bannerImage avatar{medium large}}}}isFavourite siteUrl idMal nextAiringEpisode{episode airingAt}source countryOfOrigin format duration season seasonYear startDate{year month day}endDate{year month day}genres studios(isMain:true){nodes{id name siteUrl}}description trailer{site id}synonyms tags{name rank isMediaSpoiler}characters(sort:[ROLE,FAVOURITES_DESC],perPage:25,page:1){edges{role voiceActors { id name { first middle last full native userPreferred } image { large medium } languageV2 } node{id image{medium}name{userPreferred}isFavourite}}}relations{edges{relationType(version:2)node{id idMal mediaListEntry{progress private score(format:POINT_100)status}episodes chapters nextAiringEpisode{episode}popularity meanScore isAdult isFavourite format title{english romaji userPreferred}type status(version:2)bannerImage coverImage{large}}}}staffPreview:staff(perPage:8,sort:[RELEVANCE,ID]){edges{role node{id image{large medium}name{userPreferred}}}}recommendations(sort:RATING_DESC){nodes{mediaRecommendation{id idMal mediaListEntry{progress private score(format:POINT_100)status}episodes chapters nextAiringEpisode{episode}meanScore isAdult isFavourite format title{english romaji userPreferred}type status(version:2)bannerImage coverImage{large}}}}externalLinks{url site}}Page(page:1){pageInfo{total perPage currentPage lastPage hasNextPage}mediaList(isFollowing:true,sort:[STATUS],mediaId:${media.id}){id status score(format: POINT_100) progress progressVolumes user{id name avatar{large medium}}}}}""" + """{Media(id:${media.id}){id favourites popularity episodes chapters streamingEpisodes {title thumbnail url site} mediaListEntry{id status score(format:POINT_100)progress private notes repeat customLists updatedAt startedAt{year month day}completedAt{year month day}}reviews(perPage:3, sort:SCORE_DESC){nodes{id mediaId mediaType summary body(asHtml:true) rating ratingAmount userRating score private siteUrl createdAt updatedAt user{id name bannerImage avatar{medium large}}}}isFavourite siteUrl idMal nextAiringEpisode{episode airingAt}source countryOfOrigin format duration season seasonYear startDate{year month day}endDate{year month day}genres studios(isMain:true){nodes{id name siteUrl}}description trailer{site id}synonyms tags{name rank isMediaSpoiler}characters(sort:[ROLE,FAVOURITES_DESC],perPage:25,page:1){edges{role voiceActors { id name { first middle last full native userPreferred } image { large medium } languageV2 } node{id image{medium}name{userPreferred}isFavourite}}}relations{edges{relationType(version:2)node{id idMal mediaListEntry{progress private score(format:POINT_100)status}episodes chapters nextAiringEpisode{episode}popularity meanScore isAdult isFavourite format title{english romaji userPreferred}type status(version:2)bannerImage coverImage{large}}}}staffPreview:staff(perPage:8,sort:[RELEVANCE,ID]){edges{role node{id image{large medium}name{userPreferred}}}}recommendations(sort:RATING_DESC){nodes{mediaRecommendation{id idMal mediaListEntry{progress private score(format:POINT_100)status}episodes chapters nextAiringEpisode{episode}meanScore isAdult isFavourite format title{english romaji userPreferred}type status(version:2)bannerImage coverImage{large}}}}externalLinks{url site}}Page(page:1){pageInfo{total perPage currentPage lastPage hasNextPage}mediaList(isFollowing:true,sort:[STATUS],mediaId:${media.id}){id status score(format: POINT_100) progress progressVolumes user{id name avatar{large medium}}}}}""" runBlocking { val anilist = async { var response = executeQuery(query, force = true) @@ -90,7 +90,7 @@ class AnilistQueries { media.popularity = fetchedMedia.popularity media.startDate = fetchedMedia.startDate media.endDate = fetchedMedia.endDate - + media.streamingEpisodes = fetchedMedia.streamingEpisodes if (fetchedMedia.genres != null) { media.genres = arrayListOf() fetchedMedia.genres?.forEach { i -> diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt b/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt index 23c79045..a54e3ad8 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/api/Media.kt @@ -143,7 +143,7 @@ data class Media( @SerialName("externalLinks") var externalLinks: List?, // Data and links to legal streaming episodes on external sites - // @SerialName("streamingEpisodes") var streamingEpisodes: List?, + @SerialName("streamingEpisodes") var streamingEpisodes: List?, // The ranking of the media in a particular time span and format compared to other media // @SerialName("rankings") var rankings: List?, @@ -239,7 +239,20 @@ data class AiringSchedule( // The associate media of the airing episode @SerialName("media") var media: Media?, ) +@Serializable +data class MediaStreamingEpisode( + // The title of the episode + @SerialName("title") var title: String?, + // The thumbnail image of the episode + @SerialName("thumbnail") var thumbnail: String?, + + // The url of the episode + @SerialName("url") var url: String?, + + // The site location of the streaming episode + @SerialName("site") var site: String?, +) @Serializable data class MediaCoverImage( // The cover image url of the media at its largest size. If this size isn't available, large will be provided instead. diff --git a/app/src/main/java/ani/dantotsu/media/Media.kt b/app/src/main/java/ani/dantotsu/media/Media.kt index a935dd4a..4b9136c5 100644 --- a/app/src/main/java/ani/dantotsu/media/Media.kt +++ b/app/src/main/java/ani/dantotsu/media/Media.kt @@ -4,6 +4,7 @@ import android.graphics.Bitmap import ani.dantotsu.connections.anilist.api.FuzzyDate import ani.dantotsu.connections.anilist.api.MediaEdge import ani.dantotsu.connections.anilist.api.MediaList +import ani.dantotsu.connections.anilist.api.MediaStreamingEpisode import ani.dantotsu.connections.anilist.api.MediaType import ani.dantotsu.connections.anilist.api.Query import ani.dantotsu.media.anime.Anime @@ -76,7 +77,7 @@ data class Media( var nameMAL: String? = null, var shareLink: String? = null, var selected: Selected? = null, - + var streamingEpisodes: List? = null, var idKitsu: String? = null, var cameFromContinue: Boolean = false diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt index 32b90910..2cb5deca 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt @@ -31,6 +31,7 @@ import androidx.viewpager2.widget.ViewPager2 import ani.dantotsu.FileUrl import ani.dantotsu.R import ani.dantotsu.addons.download.DownloadAddonManager +import ani.dantotsu.connections.anilist.api.MediaStreamingEpisode import ani.dantotsu.databinding.FragmentAnimeWatchBinding import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadsManager @@ -230,6 +231,19 @@ class AnimeWatchFragment : Fragment() { val episodes = loadedEpisodes[media.selected!!.sourceIndex] if (episodes != null) { episodes.forEach { (i, episode) -> + fun getThumbnail(episodes: List): List> { + return episodes.mapNotNull { episode -> + val regex = Regex("""Episode\s*(\d+)\s*-\s*(.*)""") + val number = episode.title?.let { + val matchResult = regex.matchEntire(it) + matchResult?.destructured?.component1() + } + number?.let { number to FileUrl[episode.thumbnail] } + } + } + + val getThumbnail = getThumbnail(media.streamingEpisodes ?: emptyList()) + if (media.anime?.fillerEpisodes != null) { if (media.anime!!.fillerEpisodes!!.containsKey(i)) { episode.title = @@ -247,8 +261,8 @@ class AnimeWatchFragment : Fragment() { ) media.anime!!.kitsuEpisodes!![i]?.title ?: episode.title else episode.title ?: media.anime!!.kitsuEpisodes!![i]?.title ?: episode.title - episode.thumb = media.anime!!.kitsuEpisodes!![i]?.thumb - ?: FileUrl[media.cover] + episode.thumb = getThumbnail.find { it.first == i }?.second + ?: media.anime!!.kitsuEpisodes!![i]?.thumb ?: episode.thumb } } }