From 7f83b0e73eeee445d186d5ba297b09c8c8e7ae57 Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 14 Jan 2023 16:40:35 +0700 Subject: [PATCH] several fix --- AnimeIndoProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/AnimeIndoProvider.kt | 56 +++++---- AnimeSailProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/AnimeSailProvider.kt | 57 +++++---- Gomunimeis/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Gomunimeis.kt | 73 +++++++----- KuramanimeProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/KuramanimeProvider.kt | 65 +++++----- KuronimeProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/KuronimeProvider.kt | 57 +++++---- Loklok/build.gradle.kts | 2 +- Loklok/src/main/kotlin/com/hexated/Loklok.kt | 81 +++++++------ NeonimeProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/NeonimeProvider.kt | 74 ++++++------ NontonAnimeIDProvider/build.gradle.kts | 2 +- .../com/hexated/NontonAnimeIDProvider.kt | 71 ++++++----- OploverzProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/OploverzProvider.kt | 61 +++++----- OtakudesuProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/OtakudesuProvider.kt | 59 +++++---- Samehadaku/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Samehadaku.kt | 56 +++++---- .../main/kotlin/com/hexated/SoraExtractor.kt | 7 +- .../src/main/kotlin/com/hexated/SoraUtils.kt | 112 ++++++++++-------- 24 files changed, 479 insertions(+), 372 deletions(-) diff --git a/AnimeIndoProvider/build.gradle.kts b/AnimeIndoProvider/build.gradle.kts index 38b00640..dcce6f01 100644 --- a/AnimeIndoProvider/build.gradle.kts +++ b/AnimeIndoProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 5 +version = 6 cloudstream { diff --git a/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt b/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt index b5581e4a..2764b8d4 100644 --- a/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt +++ b/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt @@ -27,8 +27,6 @@ class AnimeIndoProvider : 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 @@ -147,13 +145,7 @@ class AnimeIndoProvider : MainAPI() { val status = getStatus(document.selectFirst("div.info-content > div.spe > span:nth-child(1)")!!.ownText().trim()) val description = document.select("div[itemprop=description] > 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 (malId, anilistId, image, cover) = getTracker(title, type, year) val trailer = document.selectFirst("div.player-embed iframe")?.attr("src") val episodes = document.select("div.lstepsiode.listeps ul li").mapNotNull { val header = it.selectFirst("span.lchx > a") ?: return@mapNotNull null @@ -164,13 +156,14 @@ class AnimeIndoProvider : MainAPI() { return newAnimeLoadResponse(title, url, getType(type)) { engName = title - posterUrl = poster + posterUrl = image ?: poster + backgroundPosterUrl = cover ?: image ?: poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status plot = description this.tags = tags - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) addTrailer(trailer) } @@ -199,24 +192,41 @@ class AnimeIndoProvider : MainAPI() { return true } - data class Data( - @JsonProperty("mal_id") val mal_id: String? = null, + private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { + val res = app.get("https://api.consumet.org/meta/anilist/$title") + .parsedSafe()?.results?.find { media -> + (media.title?.english.equals(title, true) || media.title?.romaji.equals( + title, + true + )) || (media.type.equals(type, true) && media.releaseDate == year) + } + return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) + } + + data class Tracker( + val malId: Int? = null, + val aniId: String? = null, + val image: String? = null, + val cover: String? = null, ) - data class JikanResponse( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), + data class Title( + @JsonProperty("romaji") val romaji: String? = null, + @JsonProperty("english") val english: String? = null, ) - private data class IdAni( - @JsonProperty("id") val id: String? = null, + data class Results( + @JsonProperty("id") val aniId: String? = null, + @JsonProperty("malId") val malId: Int? = null, + @JsonProperty("title") val title: Title? = null, + @JsonProperty("releaseDate") val releaseDate: Int? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("image") val image: String? = null, + @JsonProperty("cover") val cover: String? = null, ) - private data class MediaAni( - @JsonProperty("Media") val media: IdAni? = null, - ) - - private data class DataAni( - @JsonProperty("data") val data: MediaAni? = null, + data class AniSearch( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) diff --git a/AnimeSailProvider/build.gradle.kts b/AnimeSailProvider/build.gradle.kts index 3541b33f..803ab6be 100644 --- a/AnimeSailProvider/build.gradle.kts +++ b/AnimeSailProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt b/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt index aa8d8c05..1d089b08 100644 --- a/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt +++ b/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt @@ -26,8 +26,6 @@ class AnimeSailProvider : 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 @@ -111,16 +109,11 @@ class AnimeSailProvider : MainAPI() { val title = document.selectFirst("h1.entry-title")?.text().toString() .replace("Subtitle Indonesia", "").trim() + val poster = document.selectFirst("div.entry-content > img")?.attr("src") val type = document.select("tbody th:contains(Tipe)").next().text().lowercase() val year = document.select("tbody th:contains(Dirilis)").next().text().trim().toIntOrNull() - 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 (malId, anilistId, image, cover) = getTracker(title, type, year) val episodes = document.select("ul.daftar > li").map { val episode = Regex("Episode\\s?([0-9]+)").find( @@ -131,7 +124,8 @@ class AnimeSailProvider : MainAPI() { }.reversed() return newAnimeLoadResponse(title, url, getType(type)) { - posterUrl = document.selectFirst("div.entry-content > img")?.attr("src") + posterUrl = image ?: poster + backgroundPosterUrl = cover ?: image ?: poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = @@ -139,7 +133,7 @@ class AnimeSailProvider : MainAPI() { plot = document.selectFirst("div.entry-content > p")?.text() this.tags = document.select("tbody th:contains(Genre)").next().select("a").map { it.text() } - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) } } @@ -208,24 +202,41 @@ class AnimeSailProvider : MainAPI() { return true } - data class Data( - @JsonProperty("mal_id") val mal_id: String? = null, + private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { + val res = app.get("https://api.consumet.org/meta/anilist/$title") + .parsedSafe()?.results?.find { media -> + (media.title?.english.equals(title, true) || media.title?.romaji.equals( + title, + true + )) || (media.type.equals(type, true) && media.releaseDate == year) + } + return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) + } + + data class Tracker( + val malId: Int? = null, + val aniId: String? = null, + val image: String? = null, + val cover: String? = null, ) - data class JikanResponse( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), + data class Title( + @JsonProperty("romaji") val romaji: String? = null, + @JsonProperty("english") val english: String? = null, ) - private data class IdAni( - @JsonProperty("id") val id: String? = null, + data class Results( + @JsonProperty("id") val aniId: String? = null, + @JsonProperty("malId") val malId: Int? = null, + @JsonProperty("title") val title: Title? = null, + @JsonProperty("releaseDate") val releaseDate: Int? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("image") val image: String? = null, + @JsonProperty("cover") val cover: String? = null, ) - private data class MediaAni( - @JsonProperty("Media") val media: IdAni? = null, - ) - - private data class DataAni( - @JsonProperty("data") val data: MediaAni? = null, + data class AniSearch( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) } \ No newline at end of file diff --git a/Gomunimeis/build.gradle.kts b/Gomunimeis/build.gradle.kts index 9db143ab..61970d23 100644 --- a/Gomunimeis/build.gradle.kts +++ b/Gomunimeis/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 2 +version = 3 cloudstream { diff --git a/Gomunimeis/src/main/kotlin/com/hexated/Gomunimeis.kt b/Gomunimeis/src/main/kotlin/com/hexated/Gomunimeis.kt index 03834fb5..a99907c3 100644 --- a/Gomunimeis/src/main/kotlin/com/hexated/Gomunimeis.kt +++ b/Gomunimeis/src/main/kotlin/com/hexated/Gomunimeis.kt @@ -23,7 +23,6 @@ class Gomunimeis : MainAPI() { ) companion object { - private const val jikanAPI = "https://api.jikan.moe/v4" private const val mainImageUrl = "https://upload.anoboy.live" fun getType(t: String): TvType { @@ -101,15 +100,7 @@ class Gomunimeis : MainAPI() { )?.groupValues?.get(1)?.toIntOrNull() val status = getStatus(document.selectFirst(".spe > span")!!.ownText()) val description = document.select("div[itemprop = description] > 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 (malId, anilistId, image, cover) = getTracker(title, type, year) val episodes = document.select(".eplister > ul > li").map { val episode = Regex("Episode\\s?([0-9]+)").find( it.select(".epl-title").text() @@ -120,11 +111,12 @@ class Gomunimeis : MainAPI() { return newAnimeLoadResponse(title, url, getType(type)) { engName = title - posterUrl = poster + posterUrl = image ?: poster + backgroundPosterUrl = cover ?: image ?: poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) plot = description this.tags = tags @@ -151,6 +143,43 @@ class Gomunimeis : MainAPI() { return true } + private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { + val res = app.get("https://api.consumet.org/meta/anilist/$title") + .parsedSafe()?.results?.find { media -> + (media.title?.english.equals(title, true) || media.title?.romaji.equals( + title, + true + )) || (media.type.equals(type, true) && media.releaseDate == year) + } + return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) + } + + data class Tracker( + val malId: Int? = null, + val aniId: String? = null, + val image: String? = null, + val cover: String? = null, + ) + + data class Title( + @JsonProperty("romaji") val romaji: String? = null, + @JsonProperty("english") val english: String? = null, + ) + + data class Results( + @JsonProperty("id") val aniId: String? = null, + @JsonProperty("malId") val malId: Int? = null, + @JsonProperty("title") val title: Title? = null, + @JsonProperty("releaseDate") val releaseDate: Int? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("image") val image: String? = null, + @JsonProperty("cover") val cover: String? = null, + ) + + data class AniSearch( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), + ) + data class Streamsb( @JsonProperty("link") val link: String?, ) @@ -175,24 +204,4 @@ class Gomunimeis : MainAPI() { @JsonProperty("salt") val salt: String?, ) - 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/KuramanimeProvider/build.gradle.kts b/KuramanimeProvider/build.gradle.kts index e4eb4e4d..a9afa697 100644 --- a/KuramanimeProvider/build.gradle.kts +++ b/KuramanimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 6 +version = 7 cloudstream { diff --git a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt index e79b0153..0c11909f 100644 --- a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt +++ b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt @@ -5,12 +5,12 @@ 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 import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.Jsoup import org.jsoup.nodes.Element +import java.util.ArrayList class KuramanimeProvider : MainAPI() { override var mainUrl = "https://kuramanime.net" @@ -27,8 +27,6 @@ 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 @@ -76,9 +74,9 @@ class KuramanimeProvider : MainAPI() { val href = getProperAnimeLink(fixUrl(this.selectFirst("a")!!.attr("href"))) val title = this.selectFirst("h5 a")?.text() ?: return null val posterUrl = fixUrl(this.select("div.product__item__pic.set-bg").attr("data-setbg")) - val episode = Regex("([0-9*])\\s?/").find( - this.select("div.ep span").text() - )?.groupValues?.getOrNull(1)?.toIntOrNull() + val episode = this.select("div.ep span").text().let { + Regex("Ep\\s([0-9]+)\\s/").find(it)?.groupValues?.getOrNull(1)?.toIntOrNull() + } return newAnimeSearchResponse(title, href, TvType.Anime) { this.posterUrl = posterUrl @@ -114,14 +112,7 @@ class KuramanimeProvider : MainAPI() { ) 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 (malId, anilistId, image, cover) = getTracker(title, type, year) val episodes = mutableListOf() @@ -148,12 +139,13 @@ class KuramanimeProvider : MainAPI() { return newAnimeLoadResponse(title, url, getType(type)) { engName = title - posterUrl = poster + posterUrl = image ?: poster + backgroundPosterUrl = cover ?: image ?: poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status plot = description - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) this.tags = tags this.recommendations = recommendations @@ -217,24 +209,41 @@ class KuramanimeProvider : MainAPI() { return true } - data class Data( - @JsonProperty("mal_id") val mal_id: String? = null, + private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { + val res = app.get("https://api.consumet.org/meta/anilist/$title") + .parsedSafe()?.results?.find { media -> + (media.title?.english.equals(title, true) || media.title?.romaji.equals( + title, + true + )) || (media.type.equals(type, true) && media.releaseDate == year) + } + return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) + } + + data class Tracker( + val malId: Int? = null, + val aniId: String? = null, + val image: String? = null, + val cover: String? = null, ) - data class JikanResponse( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), + data class Title( + @JsonProperty("romaji") val romaji: String? = null, + @JsonProperty("english") val english: String? = null, ) - private data class IdAni( - @JsonProperty("id") val id: String? = null, + data class Results( + @JsonProperty("id") val aniId: String? = null, + @JsonProperty("malId") val malId: Int? = null, + @JsonProperty("title") val title: Title? = null, + @JsonProperty("releaseDate") val releaseDate: Int? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("image") val image: String? = null, + @JsonProperty("cover") val cover: String? = null, ) - private data class MediaAni( - @JsonProperty("Media") val media: IdAni? = null, - ) - - private data class DataAni( - @JsonProperty("data") val data: MediaAni? = null, + data class AniSearch( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) } \ No newline at end of file diff --git a/KuronimeProvider/build.gradle.kts b/KuronimeProvider/build.gradle.kts index e273a423..8b1b0f7b 100644 --- a/KuronimeProvider/build.gradle.kts +++ b/KuronimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 3 +version = 4 cloudstream { diff --git a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt index 42ee0810..943a4e01 100644 --- a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt +++ b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt @@ -11,6 +11,7 @@ import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.Jsoup import org.jsoup.nodes.Element +import java.util.ArrayList class KuronimeProvider : MainAPI() { override var mainUrl = "https://45.12.2.2" @@ -27,8 +28,6 @@ class KuronimeProvider : 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", true)) TvType.OVA else if (t.contains("Movie", true)) TvType.AnimeMovie @@ -120,13 +119,7 @@ class KuronimeProvider : MainAPI() { val year = Regex("\\d, ([0-9]*)").find( document.select(".infodetail > ul > li:nth-child(5)").text() )?.groupValues?.get(1)?.toIntOrNull() - 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 (malId, anilistId, image, cover) = getTracker(title, type, year) val status = getStatus( document.selectFirst(".infodetail > ul > li:nth-child(3)")!!.ownText() .replace(Regex("\\W"), "") @@ -141,12 +134,13 @@ class KuronimeProvider : MainAPI() { return newAnimeLoadResponse(title, url, getType(type)) { engName = title - posterUrl = poster + posterUrl = image ?: poster + backgroundPosterUrl = cover ?: image ?: poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status plot = description - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) addTrailer(trailer) this.tags = tags @@ -206,24 +200,41 @@ class KuronimeProvider : MainAPI() { return true } - data class Data( - @JsonProperty("mal_id") val mal_id: String? = null, + private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { + val res = app.get("https://api.consumet.org/meta/anilist/$title") + .parsedSafe()?.results?.find { media -> + (media.title?.english.equals(title, true) || media.title?.romaji.equals( + title, + true + )) || (media.type.equals(type, true) && media.releaseDate == year) + } + return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) + } + + data class Tracker( + val malId: Int? = null, + val aniId: String? = null, + val image: String? = null, + val cover: String? = null, ) - data class JikanResponse( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), + data class Title( + @JsonProperty("romaji") val romaji: String? = null, + @JsonProperty("english") val english: String? = null, ) - private data class IdAni( - @JsonProperty("id") val id: String? = null, + data class Results( + @JsonProperty("id") val aniId: String? = null, + @JsonProperty("malId") val malId: Int? = null, + @JsonProperty("title") val title: Title? = null, + @JsonProperty("releaseDate") val releaseDate: Int? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("image") val image: String? = null, + @JsonProperty("cover") val cover: String? = null, ) - private data class MediaAni( - @JsonProperty("Media") val media: IdAni? = null, - ) - - private data class DataAni( - @JsonProperty("data") val data: MediaAni? = null, + data class AniSearch( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) } diff --git a/Loklok/build.gradle.kts b/Loklok/build.gradle.kts index 46035769..7ac9fc4f 100644 --- a/Loklok/build.gradle.kts +++ b/Loklok/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 13 +version = 14 cloudstream { diff --git a/Loklok/src/main/kotlin/com/hexated/Loklok.kt b/Loklok/src/main/kotlin/com/hexated/Loklok.kt index 73850c20..85dbf6c7 100644 --- a/Loklok/src/main/kotlin/com/hexated/Loklok.kt +++ b/Loklok/src/main/kotlin/com/hexated/Loklok.kt @@ -37,7 +37,6 @@ class Loklok : MainAPI() { private val api = base64DecodeAPI("dg==LnQ=b2s=a2w=bG8=aS4=YXA=ZS0=aWw=b2I=LW0=Z2E=Ly8=czo=dHA=aHQ=") private val apiUrl = "$api/${base64Decode("Y21zL2FwcA==")}" private val searchApi = base64Decode("aHR0cHM6Ly9sb2tsb2suY29t") - private const val jikanAPI = "https://api.jikan.moe/v4" private const val mainImageUrl = "https://images.weserv.nl" private fun base64DecodeAPI(api: String): String { @@ -175,22 +174,11 @@ class Loklok : MainAPI() { } val animeType = if(type == TvType.Anime && data.category == 0) "movie" else "tv" - - val malId = if(type == TvType.Anime) { - app.get("${jikanAPI}/anime?q=${res.name}&start_date=${res.year}&type=$animeType&limit=1") - .parsedSafe()?.data?.firstOrNull()?.mal_id - } else { - null - } - val anilistId = if(malId != null) { - app.post( - "https://graphql.anilist.co/", data = mapOf( - "query" to "{Media(idMal:$malId,type:ANIME){id}}", - ) - ).parsedSafe()?.data?.media?.id - } else { - null - } + val (malId, anilistId) = if (type == TvType.Anime) getTracker( + res.name, + animeType, + res.year + ) else Tracker() return newTvSeriesLoadResponse( res.name ?: return null, @@ -204,7 +192,7 @@ class Loklok : MainAPI() { this.plot = res.introduction this.tags = res.tagNameList this.rating = res.score.toRatingInt() - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) this.recommendations = recommendations } @@ -271,6 +259,24 @@ class Loklok : MainAPI() { } } + private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { + val res = app.get("https://api.consumet.org/meta/anilist/$title") + .parsedSafe()?.results?.find { media -> + (media.title?.english.equals(title, true) || media.title?.romaji.equals( + title, + true + )) || (media.type.equals(type, true) && media.releaseDate == year) + } + return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) + } + + data class Tracker( + val malId: Int? = null, + val aniId: String? = null, + val image: String? = null, + val cover: String? = null, + ) + data class UrlData( val id: Any? = null, val category: Int? = null, @@ -295,6 +301,25 @@ class Loklok : MainAPI() { val subtitlingList: List? = arrayListOf(), ) + data class Title( + @JsonProperty("romaji") val romaji: String? = null, + @JsonProperty("english") val english: String? = null, + ) + + data class Results( + @JsonProperty("id") val aniId: String? = null, + @JsonProperty("malId") val malId: Int? = null, + @JsonProperty("title") val title: Title? = null, + @JsonProperty("releaseDate") val releaseDate: Int? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("image") val image: String? = null, + @JsonProperty("cover") val cover: String? = null, + ) + + data class AniSearch( + @JsonProperty("results") val results: java.util.ArrayList? = arrayListOf(), + ) + data class QuickSearchData( @JsonProperty("searchResults") val searchResults: ArrayList? = arrayListOf(), ) @@ -378,25 +403,5 @@ class Loklok : MainAPI() { @JsonProperty("data") val data: Data? = null, ) - data class DataMal( - @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, - ) - } diff --git a/NeonimeProvider/build.gradle.kts b/NeonimeProvider/build.gradle.kts index af0fd013..690caf94 100644 --- a/NeonimeProvider/build.gradle.kts +++ b/NeonimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 3 +version = 4 cloudstream { diff --git a/NeonimeProvider/src/main/kotlin/com/hexated/NeonimeProvider.kt b/NeonimeProvider/src/main/kotlin/com/hexated/NeonimeProvider.kt index cac4f8b7..2eb71c49 100644 --- a/NeonimeProvider/src/main/kotlin/com/hexated/NeonimeProvider.kt +++ b/NeonimeProvider/src/main/kotlin/com/hexated/NeonimeProvider.kt @@ -25,8 +25,6 @@ class NeonimeProvider : 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", true)) TvType.OVA else if (t.contains("Movie", true)) TvType.AnimeMovie @@ -122,27 +120,28 @@ class NeonimeProvider : MainAPI() { if (url.contains("movie") || url.contains("live-action")) { val mTitle = document.selectFirst(".sbox > .data > h1[itemprop = name]")?.text().toString().replace("Subtitle Indonesia", "").trim() + val mPoster = document.selectFirst(".sbox > .imagen > .fix > img[itemprop = image]")?.attr("data-src") val mTrailer = document.selectFirst("div.youtube_id iframe")?.attr("data-wpfc-original-src")?.substringAfterLast("html#")?.let{ "https://www.youtube.com/embed/$it"} val year = document.selectFirst("a[href*=release-year]")!!.text().toIntOrNull() - val malId = getMalId(mTitle, year, "movie") - val anilistId = getAniId(malId) + val (malId, anilistId, image, cover) = getTracker(mTitle, "movie", year) return newMovieLoadResponse(name = mTitle, url = url, type = TvType.Movie, dataUrl = url) { - posterUrl = document.selectFirst(".sbox > .imagen > .fix > img[itemprop = image]")?.attr("data-src") + posterUrl = image ?: mPoster + backgroundPosterUrl = cover ?: image ?: mPoster this.year = year plot = document.select("div[itemprop = description]").text().trim() rating = document.select("span[itemprop = ratingValue]").text().toIntOrNull() tags = document.select("p.meta_dd > a").map { it.text() } addTrailer(mTrailer) - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) } } else { val title = document.select("h1[itemprop = name]").text().replace("Subtitle Indonesia", "").trim() + val poster = document.selectFirst(".imagen > img")?.attr("data-src") val trailer = document.selectFirst("div.youtube_id_tv iframe")?.attr("data-wpfc-original-src")?.substringAfterLast("html#")?.let{ "https://www.youtube.com/embed/$it"} val year = document.select("#info a[href*=\"-year/\"]").text().toIntOrNull() - val malId = getMalId(title, year, "tv") - val anilistId = getAniId(malId) + val (malId, anilistId, image, cover) = getTracker(title, "tv", year) val episodes = document.select("ul.episodios > li").mapNotNull { val header = it.selectFirst(".episodiotitle > a")?.ownText().toString() val name = Regex("(Episode\\s?[0-9]+)").find(header)?.groupValues?.getOrNull(0) ?: header @@ -152,32 +151,20 @@ class NeonimeProvider : MainAPI() { return newAnimeLoadResponse(title, url, TvType.Anime) { engName = title - posterUrl = document.selectFirst(".imagen > img")?.attr("data-src") + posterUrl = image ?: poster + backgroundPosterUrl = cover ?: image ?: poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = getStatus(document.select("div.metadatac > span").last()!!.text().trim()) plot = document.select("div[itemprop = description] > p").text().trim() tags = document.select("#info a[href*=\"-genre/\"]").map { it.text() } addTrailer(trailer) - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) } } } - private suspend fun getAniId(malId: String?) : String? { - return app.post( - "https://graphql.anilist.co/", data = mapOf( - "query" to "{Media(idMal:$malId,type:ANIME){id}}", - ) - ).parsedSafe()?.data?.media?.id - } - - private suspend fun getMalId(title: String?, year: Int?, type: String?) : String? { - return app.get("${jikanAPI}/anime?q=$title&start_date=${year}&type=$type&limit=1") - .parsedSafe()?.data?.firstOrNull()?.mal_id - } - override suspend fun loadLinks( data: String, isCasting: Boolean, @@ -201,24 +188,41 @@ class NeonimeProvider : MainAPI() { return true } - data class Data( - @JsonProperty("mal_id") val mal_id: String? = null, + private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { + val res = app.get("https://api.consumet.org/meta/anilist/$title") + .parsedSafe()?.results?.find { media -> + (media.title?.english.equals(title, true) || media.title?.romaji.equals( + title, + true + )) || (media.type.equals(type, true) && media.releaseDate == year) + } + return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) + } + + data class Tracker( + val malId: Int? = null, + val aniId: String? = null, + val image: String? = null, + val cover: String? = null, ) - data class JikanResponse( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), + data class Title( + @JsonProperty("romaji") val romaji: String? = null, + @JsonProperty("english") val english: String? = null, ) - private data class IdAni( - @JsonProperty("id") val id: String? = null, + data class Results( + @JsonProperty("id") val aniId: String? = null, + @JsonProperty("malId") val malId: Int? = null, + @JsonProperty("title") val title: Title? = null, + @JsonProperty("releaseDate") val releaseDate: Int? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("image") val image: String? = null, + @JsonProperty("cover") val cover: String? = null, ) - private data class MediaAni( - @JsonProperty("Media") val media: IdAni? = null, - ) - - private data class DataAni( - @JsonProperty("data") val data: MediaAni? = null, + data class AniSearch( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) } \ No newline at end of file diff --git a/NontonAnimeIDProvider/build.gradle.kts b/NontonAnimeIDProvider/build.gradle.kts index ac43034a..f2057d47 100644 --- a/NontonAnimeIDProvider/build.gradle.kts +++ b/NontonAnimeIDProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 8 +version = 9 cloudstream { diff --git a/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt b/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt index 5704e395..9969e8c9 100644 --- a/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt +++ b/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt @@ -25,8 +25,6 @@ class NontonAnimeIDProvider : MainAPI() { ) companion object { - private const val jikanAPI = "https://api.jikan.moe/v4" - fun getType(t: String): TvType { return when { t.contains("TV",true) -> TvType.Anime @@ -135,13 +133,7 @@ class NontonAnimeIDProvider : MainAPI() { val description = document.select(".entry-content.seriesdesc > p").text().trim() val trailer = document.selectFirst("a.trailerbutton")?.attr("href") - 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 (malId, anilistId, image, cover) = getTracker(title, type, year) val episodes = if (document.select("button.buttfilter").isNotEmpty()) { val id = document.select("input[name=series_id]").attr("value") @@ -189,13 +181,14 @@ class NontonAnimeIDProvider : MainAPI() { return newAnimeLoadResponse(title, url, getType(type)) { engName = title - posterUrl = poster + posterUrl = image ?: poster + backgroundPosterUrl = cover ?: image ?: poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status this.rating = rating plot = description - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) addTrailer(trailer) this.tags = tags @@ -241,6 +234,43 @@ class NontonAnimeIDProvider : MainAPI() { return true } + private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { + val res = app.get("https://api.consumet.org/meta/anilist/$title") + .parsedSafe()?.results?.find { media -> + (media.title?.english.equals(title, true) || media.title?.romaji.equals( + title, + true + )) || (media.type.equals(type, true) && media.releaseDate == year) + } + return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) + } + + data class Tracker( + val malId: Int? = null, + val aniId: String? = null, + val image: String? = null, + val cover: String? = null, + ) + + data class Title( + @JsonProperty("romaji") val romaji: String? = null, + @JsonProperty("english") val english: String? = null, + ) + + data class Results( + @JsonProperty("id") val aniId: String? = null, + @JsonProperty("malId") val malId: Int? = null, + @JsonProperty("title") val title: Title? = null, + @JsonProperty("releaseDate") val releaseDate: Int? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("image") val image: String? = null, + @JsonProperty("cover") val cover: String? = null, + ) + + data class AniSearch( + @JsonProperty("results") val results: java.util.ArrayList? = arrayListOf(), + ) + private data class EpResponse( @JsonProperty("posts") val posts: String?, @JsonProperty("max_page") val max_page: Int?, @@ -248,23 +278,4 @@ class NontonAnimeIDProvider : MainAPI() { @JsonProperty("content") val content: String ) - 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, - ) } diff --git a/OploverzProvider/build.gradle.kts b/OploverzProvider/build.gradle.kts index 753083b4..910eafdb 100644 --- a/OploverzProvider/build.gradle.kts +++ b/OploverzProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt index 989f4c53..006e4d86 100644 --- a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt +++ b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt @@ -25,8 +25,6 @@ class OploverzProvider : MainAPI() { ) companion object { - private const val jikanAPI = "https://api.jikan.moe/v4" - fun getType(t: String): TvType { return when { t.contains("TV") -> TvType.Anime @@ -146,13 +144,7 @@ class OploverzProvider : MainAPI() { val description = document.select(".entry-content > p").text().trim() val trailer = document.selectFirst("a.trailerbutton")?.attr("href") - val malId = app.get("${jikanAPI}/anime?q=$title&start_date=${year}&${typeCheck.lowercase()}&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 (malId, anilistId, image, cover) = getTracker(title, typeCheck, year) val episodes = document.select(".eplister > ul > li").map { val header = it.select(".epl-title").text() @@ -176,13 +168,14 @@ class OploverzProvider : MainAPI() { return newAnimeLoadResponse(title, url, type) { engName = title - posterUrl = poster + posterUrl = image ?: poster + backgroundPosterUrl = cover ?: image ?: poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status plot = description this.tags = tags - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) this.recommendations = recommendations addTrailer(trailer) @@ -190,11 +183,6 @@ class OploverzProvider : MainAPI() { } - data class Source( - @JsonProperty("play_url") val play_url: String, - @JsonProperty("format_id") val format_id: Int - ) - override suspend fun loadLinks( data: String, isCasting: Boolean, @@ -213,24 +201,41 @@ class OploverzProvider : MainAPI() { return true } - data class Data( - @JsonProperty("mal_id") val mal_id: String? = null, + private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { + val res = app.get("https://api.consumet.org/meta/anilist/$title") + .parsedSafe()?.results?.find { media -> + (media.title?.english.equals(title, true) || media.title?.romaji.equals( + title, + true + )) || (media.type.equals(type, true) && media.releaseDate == year) + } + return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) + } + + data class Tracker( + val malId: Int? = null, + val aniId: String? = null, + val image: String? = null, + val cover: String? = null, ) - data class JikanResponse( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), + data class Title( + @JsonProperty("romaji") val romaji: String? = null, + @JsonProperty("english") val english: String? = null, ) - private data class IdAni( - @JsonProperty("id") val id: String? = null, + data class Results( + @JsonProperty("id") val aniId: String? = null, + @JsonProperty("malId") val malId: Int? = null, + @JsonProperty("title") val title: Title? = null, + @JsonProperty("releaseDate") val releaseDate: Int? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("image") val image: String? = null, + @JsonProperty("cover") val cover: String? = null, ) - private data class MediaAni( - @JsonProperty("Media") val media: IdAni? = null, - ) - - private data class DataAni( - @JsonProperty("data") val data: MediaAni? = null, + data class AniSearch( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) } \ No newline at end of file diff --git a/OtakudesuProvider/build.gradle.kts b/OtakudesuProvider/build.gradle.kts index f3134bcd..cc0bf7fa 100644 --- a/OtakudesuProvider/build.gradle.kts +++ b/OtakudesuProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 6 +version = 7 cloudstream { diff --git a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt index 45fded6f..01ac8eb8 100644 --- a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt +++ b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt @@ -4,12 +4,12 @@ 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 import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.Jsoup import org.jsoup.nodes.Element +import java.util.ArrayList class OtakudesuProvider : MainAPI() { override var mainUrl = "https://otakudesu.bid" @@ -26,8 +26,6 @@ class OtakudesuProvider : MainAPI() { companion object { // private val interceptor = CloudflareKiller() - 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 @@ -117,13 +115,8 @@ 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 (malId, anilistId, image, cover) = getTracker(title, type, year) val episodes = document.select("div.episodelist")[1].select("ul > li").mapNotNull { val name = it.selectFirst("a")?.text() ?: return@mapNotNull null @@ -146,13 +139,14 @@ class OtakudesuProvider : MainAPI() { return newAnimeLoadResponse(title, url, getType(type)) { engName = title - posterUrl = poster + posterUrl = image ?: poster + backgroundPosterUrl = cover ?: image ?: poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status plot = description this.tags = tags - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) this.recommendations = recommendations // posterHeaders = interceptor.getCookieHeaders(url).toMap() @@ -230,24 +224,41 @@ class OtakudesuProvider : MainAPI() { return true } - data class Data( - @JsonProperty("mal_id") val mal_id: String? = null, + private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { + val res = app.get("https://api.consumet.org/meta/anilist/$title") + .parsedSafe()?.results?.find { media -> + (media.title?.english.equals(title, true) || media.title?.romaji.equals( + title, + true + )) || (media.type.equals(type, true) && media.releaseDate == year) + } + return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) + } + + data class Tracker( + val malId: Int? = null, + val aniId: String? = null, + val image: String? = null, + val cover: String? = null, ) - data class JikanResponse( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), + data class Title( + @JsonProperty("romaji") val romaji: String? = null, + @JsonProperty("english") val english: String? = null, ) - private data class IdAni( - @JsonProperty("id") val id: String? = null, + data class Results( + @JsonProperty("id") val aniId: String? = null, + @JsonProperty("malId") val malId: Int? = null, + @JsonProperty("title") val title: Title? = null, + @JsonProperty("releaseDate") val releaseDate: Int? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("image") val image: String? = null, + @JsonProperty("cover") val cover: String? = null, ) - private data class MediaAni( - @JsonProperty("Media") val media: IdAni? = null, - ) - - private data class DataAni( - @JsonProperty("data") val data: MediaAni? = null, + data class AniSearch( + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) } \ No newline at end of file diff --git a/Samehadaku/build.gradle.kts b/Samehadaku/build.gradle.kts index 93af29d1..fc63247e 100644 --- a/Samehadaku/build.gradle.kts +++ b/Samehadaku/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt index 3c7e2f78..ac6bc746 100644 --- a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt +++ b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt @@ -24,8 +24,6 @@ class Samehadaku : 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", true)) TvType.OVA else if (t.contains("Movie", true)) TvType.AnimeMovie @@ -115,13 +113,7 @@ class Samehadaku : MainAPI() { val description = document.select("div.desc p").text().trim() val trailer = document.selectFirst("div.trailer-anime iframe")?.attr("src") - 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 (malId, anilistId, image, cover) = getTracker(title, type, year) val episodes = document.select("div.lstepsiode.listeps ul li").mapNotNull { val header = it.selectFirst("span.lchx > a") ?: return@mapNotNull null @@ -136,13 +128,14 @@ class Samehadaku : MainAPI() { return newAnimeLoadResponse(title, url, getType(type)) { engName = title - posterUrl = poster + posterUrl = image ?: poster + backgroundPosterUrl = cover ?: image ?: poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status this.rating = rating plot = description - addMalId(malId?.toIntOrNull()) + addMalId(malId) addAniListId(anilistId?.toIntOrNull()) addTrailer(trailer) this.tags = tags @@ -187,24 +180,41 @@ class Samehadaku : MainAPI() { return true } - data class Data( - @JsonProperty("mal_id") val mal_id: String? = null, + private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { + val res = app.get("https://api.consumet.org/meta/anilist/$title") + .parsedSafe()?.results?.find { media -> + (media.title?.english.equals(title, true) || media.title?.romaji.equals( + title, + true + )) || (media.type.equals(type, true) && media.releaseDate == year) + } + return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) + } + + data class Tracker( + val malId: Int? = null, + val aniId: String? = null, + val image: String? = null, + val cover: String? = null, ) - data class JikanResponse( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), + data class Title( + @JsonProperty("romaji") val romaji: String? = null, + @JsonProperty("english") val english: String? = null, ) - private data class IdAni( - @JsonProperty("id") val id: String? = null, + data class Results( + @JsonProperty("id") val aniId: String? = null, + @JsonProperty("malId") val malId: Int? = null, + @JsonProperty("title") val title: Title? = null, + @JsonProperty("releaseDate") val releaseDate: Int? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("image") val image: String? = null, + @JsonProperty("cover") val cover: String? = null, ) - private data class MediaAni( - @JsonProperty("Media") val media: IdAni? = null, - ) - - private data class DataAni( - @JsonProperty("data") val data: MediaAni? = null, + data class AniSearch( + @JsonProperty("results") val results: java.util.ArrayList? = arrayListOf(), ) } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 86029d2e..289891f1 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1352,13 +1352,12 @@ object SoraExtractor : SoraStream() { sources.addAll(iframeList.filter { it.first.contains("1080p", true) }) } - val base = "https://drivebit.in" sources.apmap { (quality, link) -> delay(2000) val driveLink = bypassHrefli(link ?: return@apmap null) - val res = app.get(driveLink ?: return@apmap null).document - val resDoc = res.selectFirst("script")?.data()?.substringAfter("replace(\"") - ?.substringBefore("\")")?.let { + val base = getBaseUrl(driveLink ?: return@apmap null) + val resDoc = app.get(driveLink).text.substringAfter("replace(\"") + .substringBefore("\")").let { app.get(fixUrl(it, base)).document } val bitLink = resDoc?.selectFirst("a.btn.btn-outline-success")?.attr("href") diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index f9d52f60..ad49ba0b 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -66,14 +66,27 @@ fun String.filterMedia(title: String?, yearNum: Int?, seasonNum: Int?): Boolean } } +fun Document.getMirrorLink(): String? { + return this.select("div.mb-4 a").randomOrNull() + ?.attr("href") +} + +fun Document.getMirrorServer(server: Int): String { + return this.select("div.text-center a:contains(Server $server)").attr("href") +} + suspend fun extractMirrorUHD(url: String, ref: String): String? { - val baseDoc = app.get(fixUrl(url, ref)).document - val downLink = baseDoc.select("div.mb-4 a").randomOrNull() - ?.attr("href") ?: run { - val server = baseDoc.select("div.text-center a:contains(Server 2)").attr("href") - app.get(fixUrl(server, ref)).document.selectFirst("div.mb-4 a") - ?.attr("href") + var baseDoc = app.get(fixUrl(url, ref)).document + var downLink = baseDoc.getMirrorLink() + run lit@{ + (1..2).forEach { + if(downLink != null) return@lit + val server = baseDoc.getMirrorServer(it.plus(1)) + baseDoc = app.get(fixUrl(server, ref)).document + downLink = baseDoc.getMirrorLink() + } } + if(downLink?.contains(".mkv") == true || downLink?.contains(".mp4") == true) return downLink val downPage = app.get(downLink ?: return null).document return downPage.selectFirst("form[method=post] a.btn.btn-success") ?.attr("onclick")?.substringAfter("Openblank('")?.substringBefore("')") ?: run { @@ -93,7 +106,8 @@ suspend fun extractBackupUHD(url: String): String? { val ssid = resumeDoc.cookies["PHPSESSID"] val baseIframe = getBaseUrl(url) - val fetchLink = script?.substringAfter("fetch('")?.substringBefore("',")?.let { fixUrl(it, baseIframe) } + val fetchLink = + script?.substringAfter("fetch('")?.substringBefore("',")?.let { fixUrl(it, baseIframe) } val token = script?.substringAfter("'token', '")?.substringBefore("');") val body = FormBody.Builder() @@ -146,16 +160,18 @@ suspend fun extractGdbot(url: String): String? { } suspend fun extractDirectDl(url: String): String? { - val iframe = app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(Direct DL)")?.attr("href") + val iframe = app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(Direct DL)") + ?.attr("href") val request = app.get(iframe ?: return null) val driveDoc = request.document val token = driveDoc.select("section#generate_url").attr("data-token") val uid = driveDoc.select("section#generate_url").attr("data-uid") val ssid = request.cookies["PHPSESSID"] - val body = """{"type":"DOWNLOAD_GENERATE","payload":{"uid":"$uid","access_token":"$token"}}""".toRequestBody( - RequestBodyTypes.JSON.toMediaTypeOrNull() - ) + val body = + """{"type":"DOWNLOAD_GENERATE","payload":{"uid":"$uid","access_token":"$token"}}""".toRequestBody( + RequestBodyTypes.JSON.toMediaTypeOrNull() + ) val json = app.post( "https://rajbetmovies.com/action", requestBody = body, headers = mapOf( @@ -168,17 +184,20 @@ suspend fun extractDirectDl(url: String): String? { } suspend fun extractDrivebot(url: String): String? { - val iframeDrivebot = app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(Drivebot)") + val iframeDrivebot = + app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(Drivebot)") ?.attr("href") ?: return null return getDrivebotLink(iframeDrivebot) } suspend fun extractGdflix(url: String): String? { - val iframeGdflix = app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(GDFlix Direct)") - ?.attr("href") ?: return null + val iframeGdflix = + app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(GDFlix Direct)") + ?.attr("href") ?: return null val base = getBaseUrl(iframeGdflix) - val gdfDoc = app.get(iframeGdflix).document.selectFirst("script:containsData(replace)")?.data()?.substringAfter("replace(\"") + val gdfDoc = app.get(iframeGdflix).document.selectFirst("script:containsData(replace)")?.data() + ?.substringAfter("replace(\"") ?.substringBefore("\")")?.let { app.get(fixUrl(it, base)).document } @@ -268,7 +287,7 @@ fun getDirectGdrive(url: String): String { } } -suspend fun bypassOuo(url: String?) : String? { +suspend fun bypassOuo(url: String?): String? { var res = session.get(url ?: return null) run lit@{ (1..2).forEach { _ -> @@ -322,54 +341,47 @@ fun String.splitData(): List { } suspend fun bypassFdAds(url: String?): String? { - val directUrl = app.get(url ?: return null, verify = false).document.select("a#link").attr("href") - .substringAfter("/go/") - .let { base64Decode(it) } + val directUrl = + app.get(url ?: return null, verify = false).document.select("a#link").attr("href") + .substringAfter("/go/") + .let { base64Decode(it) } val doc = app.get(directUrl, verify = false).document val lastDoc = app.post( doc.select("form#landing").attr("action"), data = mapOf("go" to doc.select("form#landing input").attr("value")), verify = false ).document - val json = lastDoc.select("form#landing input[name=newwpsafelink]").attr("value").let { base64Decode(it) } - val finalJson = tryParseJson(json)?.linkr?.substringAfter("redirect=")?.let { base64Decode(it) } + val json = lastDoc.select("form#landing input[name=newwpsafelink]").attr("value") + .let { base64Decode(it) } + val finalJson = + tryParseJson(json)?.linkr?.substringAfter("redirect=")?.let { base64Decode(it) } return tryParseJson(finalJson)?.safelink } suspend fun bypassHrefli(url: String): String? { - val direct = url.removePrefix("https://href.li/?") - - val res = app.get(direct).document - val formLink = res.select("form#landing").attr("action") - val wpHttp = res.select("input[name=_wp_http]").attr("value") - - val res2 = app.post(formLink, data = mapOf("_wp_http" to wpHttp)).document - val formLink2 = res2.select("form#landing").attr("action") - val wpHttp2 = res2.select("input[name=_wp_http2]").attr("value") - val token = res2.select("input[name=token]").attr("value") - - val res3 = app.post( - formLink2, data = mapOf( - "_wp_http2" to wpHttp2, "token" to token + var res = app.get(url.removePrefix("https://href.li/?")) + (1..2).forEach { _ -> + val document = res.document + val nextUrl = document.select("form").attr("action") + val data = document.select("form input").mapNotNull { + it.attr("name") to it.attr("value") + }.toMap() + res = app.post( + nextUrl, + data = data, ) - ).document - - val script = res3.selectFirst("script:containsData(verify_button)")?.data() - val directLink = script?.substringAfter("\"href\",\"")?.substringBefore("\")") - val matchCookies = + } + val script = res.document.selectFirst("script:containsData(verify_button)")?.data() + val goUrl = script?.substringAfter("\"href\",\"")?.substringBefore("\")") + val cookies = Regex("sumitbot_\\('(\\S+?)',\n|.?'(\\S+?)',").findAll(script ?: return null).map { it.groupValues[2] - }.toList() - - val cookeName = matchCookies.firstOrNull() ?: return null - val cookeValue = matchCookies.lastOrNull() ?: return null - - val cookies = mapOf( - cookeName to cookeValue - ) + }.toList().let { + mapOf(it.first() to it.last()) + }.ifEmpty { return null } return app.get( - directLink ?: return null, + goUrl ?: return null, cookies = cookies ).document.selectFirst("meta[http-equiv=refresh]")?.attr("content")?.substringAfter("url=") } @@ -377,7 +389,7 @@ suspend fun bypassHrefli(url: String): String? { suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair? { val req = app.get(url) - if(!req.isSuccessful) return null + if (!req.isSuccessful) return null val doc = req.document return if (season == null) {