From 60d5714a9a8f8bf760527a9821c2e2269c2a1f22 Mon Sep 17 00:00:00 2001 From: hexated Date: Thu, 24 Nov 2022 21:44:35 +0700 Subject: [PATCH] added tracker into Otakudesu & Kuramanime --- KuramanimeProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/KuramanimeProvider.kt | 49 ++++++++++++-- OtakudesuProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/OtakudesuProvider.kt | 67 ++++++++++++++----- 4 files changed, 98 insertions(+), 22 deletions(-) diff --git a/KuramanimeProvider/build.gradle.kts b/KuramanimeProvider/build.gradle.kts index 984e72da..3b160652 100644 --- a/KuramanimeProvider/build.gradle.kts +++ b/KuramanimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 3 +version = 4 cloudstream { diff --git a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt index 49cbcee4..572878a5 100644 --- a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt +++ b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt @@ -1,6 +1,9 @@ package com.hexated +import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.utils.ExtractorLink @@ -24,6 +27,14 @@ class KuramanimeProvider : MainAPI() { ) companion object { + private const val jikanAPI = "https://api.jikan.moe/v4" + + fun getType(t: String): TvType { + return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA + else if (t.contains("Movie", true)) TvType.AnimeMovie + else TvType.Anime + } + fun getStatus(t: String): ShowStatus { return when (t) { "Selesai Tayang" -> ShowStatus.Completed @@ -90,9 +101,8 @@ class KuramanimeProvider : MainAPI() { val title = document.selectFirst(".anime__details__title > h3")!!.text().trim() val poster = document.selectFirst(".anime__details__pic")?.attr("data-setbg") - val tags = - document.select("div.anime__details__widget > div > div:nth-child(2) > ul > li:nth-child(1)") - .text().trim().replace("Genre: ", "").split(", ") + val tags = document.select("div.anime__details__widget > div > div:nth-child(2) > ul > li:nth-child(1)") + .text().trim().replace("Genre: ", "").split(", ") val year = Regex("[^0-9]").replace( document.select("div.anime__details__widget > div > div:nth-child(1) > ul > li:nth-child(5)") @@ -102,8 +112,17 @@ class KuramanimeProvider : MainAPI() { document.select("div.anime__details__widget > div > div:nth-child(1) > ul > li:nth-child(3)") .text().trim().replace("Status: ", "") ) + val type = document.selectFirst("div.col-lg-6.col-md-6 ul li:contains(Tipe:) a")?.text()?.lowercase() ?: "tv" val description = document.select(".anime__details__text > p").text().trim() + val malId = app.get("${jikanAPI}/anime?q=$title&start_date=${year}&type=$type&limit=1") + .parsedSafe()?.data?.firstOrNull()?.mal_id + val anilistId = app.post( + "https://graphql.anilist.co/", data = mapOf( + "query" to "{Media(idMal:$malId,type:ANIME){id}}", + ) + ).parsedSafe()?.data?.media?.id + val episodes = Jsoup.parse(document.select("#episodeLists").attr("data-content")).select("a").map { val name = it.text().trim() @@ -122,13 +141,15 @@ class KuramanimeProvider : MainAPI() { } } - return newAnimeLoadResponse(title, url, TvType.Anime) { + return newAnimeLoadResponse(title, url, getType(type)) { engName = title posterUrl = poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status plot = description + addMalId(malId?.toIntOrNull()) + addAniListId(anilistId?.toIntOrNull()) this.tags = tags this.recommendations = recommendations } @@ -191,4 +212,24 @@ class KuramanimeProvider : MainAPI() { return true } + data class Data( + @JsonProperty("mal_id") val mal_id: String? = null, + ) + + data class JikanResponse( + @JsonProperty("data") val data: ArrayList? = arrayListOf(), + ) + + private data class IdAni( + @JsonProperty("id") val id: String? = null, + ) + + private data class MediaAni( + @JsonProperty("Media") val media: IdAni? = null, + ) + + private data class DataAni( + @JsonProperty("data") val data: MediaAni? = null, + ) + } \ No newline at end of file diff --git a/OtakudesuProvider/build.gradle.kts b/OtakudesuProvider/build.gradle.kts index 1933d08d..00e70778 100644 --- a/OtakudesuProvider/build.gradle.kts +++ b/OtakudesuProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt index 3620feae..8857f63c 100644 --- a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt +++ b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt @@ -2,6 +2,8 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink @@ -23,11 +25,12 @@ class OtakudesuProvider : MainAPI() { ) companion object { -// private val interceptor = CloudflareKiller() + // private val interceptor = CloudflareKiller() + private const val jikanAPI = "https://api.jikan.moe/v4" fun getType(t: String): TvType { - return if (t.contains("OVA") || t.contains("Special")) TvType.OVA - else if (t.contains("Movie")) TvType.AnimeMovie + return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA + else if (t.contains("Movie", true)) TvType.AnimeMovie else TvType.Anime } @@ -49,7 +52,8 @@ class OtakudesuProvider : MainAPI() { page: Int, request: MainPageRequest ): HomePageResponse { - val document = app.get(request.data + page + val document = app.get( + request.data + page // , interceptor = interceptor ).document val home = document.select("div.venz > ul > li").mapNotNull { @@ -74,7 +78,8 @@ class OtakudesuProvider : MainAPI() { override suspend fun search(query: String): List { val link = "$mainUrl/?s=$query&post_type=anime" - val document = app.get(link + val document = app.get( + link // , interceptor = interceptor ).document @@ -91,7 +96,8 @@ class OtakudesuProvider : MainAPI() { override suspend fun load(url: String): LoadResponse { - val document = app.get(url + val document = app.get( + url // , interceptor = interceptor ).document @@ -99,10 +105,9 @@ class OtakudesuProvider : MainAPI() { ?.replace(":", "")?.trim().toString() val poster = document.selectFirst("div.fotoanime > img")?.attr("src") val tags = document.select("div.infozingle > p:nth-child(11) > span > a").map { it.text() } - val type = getType( - document.selectFirst("div.infozingle > p:nth-child(5) > span")?.ownText() - ?.replace(":", "")?.trim().toString() - ) + val type = document.selectFirst("div.infozingle > p:nth-child(5) > span")?.ownText() + ?.replace(":", "")?.trim() ?: "tv" + val year = Regex("\\d, ([0-9]*)").find( document.select("div.infozingle > p:nth-child(9) > span").text() )?.groupValues?.get(1)?.toIntOrNull() @@ -112,13 +117,20 @@ class OtakudesuProvider : MainAPI() { .trim() ) val description = document.select("div.sinopc > p").text() + val malId = app.get("${jikanAPI}/anime?q=$title&start_date=${year}&type=$type&limit=1") + .parsedSafe()?.data?.firstOrNull()?.mal_id + val anilistId = app.post( + "https://graphql.anilist.co/", data = mapOf( + "query" to "{Media(idMal:$malId,type:ANIME){id}}", + ) + ).parsedSafe()?.data?.media?.id val episodes = document.select("div.episodelist")[1].select("ul > li").mapNotNull { - val name = Regex("(Episode\\s?[0-9]+)").find( - it.selectFirst("a")?.text().toString() - )?.groupValues?.getOrNull(0) ?: it.selectFirst("a")?.text() + val name = it.selectFirst("a")?.text() ?: return@mapNotNull null + val episode = Regex("Episode\\s?([0-9]+)").find(name)?.groupValues?.getOrNull(0) + ?: it.selectFirst("a")?.text() val link = fixUrl(it.selectFirst("a")!!.attr("href")) - Episode(link, name) + Episode(link, name, episode = episode?.toIntOrNull()) }.reversed() val recommendations = @@ -132,7 +144,7 @@ class OtakudesuProvider : MainAPI() { } } - return newAnimeLoadResponse(title, url, type) { + return newAnimeLoadResponse(title, url, getType(type)) { engName = title posterUrl = poster this.year = year @@ -140,6 +152,8 @@ class OtakudesuProvider : MainAPI() { showStatus = status plot = description this.tags = tags + addMalId(malId?.toIntOrNull()) + addAniListId(anilistId?.toIntOrNull()) this.recommendations = recommendations // posterHeaders = interceptor.getCookieHeaders(url).toMap() } @@ -163,7 +177,8 @@ class OtakudesuProvider : MainAPI() { callback: (ExtractorLink) -> Unit ): Boolean { - val document = app.get(data + val document = app.get( + data // , interceptor = interceptor ).document val scriptData = document.select("script").last()?.data() @@ -215,4 +230,24 @@ class OtakudesuProvider : MainAPI() { return true } + data class Data( + @JsonProperty("mal_id") val mal_id: String? = null, + ) + + data class JikanResponse( + @JsonProperty("data") val data: ArrayList? = arrayListOf(), + ) + + private data class IdAni( + @JsonProperty("id") val id: String? = null, + ) + + private data class MediaAni( + @JsonProperty("Media") val media: IdAni? = null, + ) + + private data class DataAni( + @JsonProperty("data") val data: MediaAni? = null, + ) + } \ No newline at end of file