several fix

This commit is contained in:
hexated 2023-01-14 16:40:35 +07:00
parent 730556f5de
commit 7f83b0e73e
24 changed files with 479 additions and 372 deletions

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 5 version = 6
cloudstream { cloudstream {

View file

@ -27,8 +27,6 @@ class AnimeIndoProvider : MainAPI() {
) )
companion object { companion object {
private const val jikanAPI = "https://api.jikan.moe/v4"
fun getType(t: String): TvType { fun getType(t: String): TvType {
return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA
else if (t.contains("Movie", true)) TvType.AnimeMovie 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 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 description = document.select("div[itemprop=description] > p").text()
val malId = app.get("${jikanAPI}/anime?q=$title&start_date=${year}&type=$type&limit=1") val (malId, anilistId, image, cover) = getTracker(title, type, year)
.parsedSafe<JikanResponse>()?.data?.firstOrNull()?.mal_id
val anilistId = app.post(
"https://graphql.anilist.co/", data = mapOf(
"query" to "{Media(idMal:$malId,type:ANIME){id}}",
)
).parsedSafe<DataAni>()?.data?.media?.id
val trailer = document.selectFirst("div.player-embed iframe")?.attr("src") val trailer = document.selectFirst("div.player-embed iframe")?.attr("src")
val episodes = document.select("div.lstepsiode.listeps ul li").mapNotNull { val episodes = document.select("div.lstepsiode.listeps ul li").mapNotNull {
val header = it.selectFirst("span.lchx > a") ?: return@mapNotNull null val header = it.selectFirst("span.lchx > a") ?: return@mapNotNull null
@ -164,13 +156,14 @@ class AnimeIndoProvider : MainAPI() {
return newAnimeLoadResponse(title, url, getType(type)) { return newAnimeLoadResponse(title, url, getType(type)) {
engName = title engName = title
posterUrl = poster posterUrl = image ?: poster
backgroundPosterUrl = cover ?: image ?: poster
this.year = year this.year = year
addEpisodes(DubStatus.Subbed, episodes) addEpisodes(DubStatus.Subbed, episodes)
showStatus = status showStatus = status
plot = description plot = description
this.tags = tags this.tags = tags
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) addAniListId(anilistId?.toIntOrNull())
addTrailer(trailer) addTrailer(trailer)
} }
@ -199,24 +192,41 @@ class AnimeIndoProvider : MainAPI() {
return true return true
} }
data class Data( private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker {
@JsonProperty("mal_id") val mal_id: String? = null, val res = app.get("https://api.consumet.org/meta/anilist/$title")
.parsedSafe<AniSearch>()?.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( data class Title(
@JsonProperty("data") val data: ArrayList<Data>? = arrayListOf(), @JsonProperty("romaji") val romaji: String? = null,
@JsonProperty("english") val english: String? = null,
) )
private data class IdAni( data class Results(
@JsonProperty("id") val id: String? = null, @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( data class AniSearch(
@JsonProperty("Media") val media: IdAni? = null, @JsonProperty("results") val results: ArrayList<Results>? = arrayListOf(),
)
private data class DataAni(
@JsonProperty("data") val data: MediaAni? = null,
) )

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 4 version = 5
cloudstream { cloudstream {

View file

@ -26,8 +26,6 @@ class AnimeSailProvider : MainAPI() {
) )
companion object { companion object {
private const val jikanAPI = "https://api.jikan.moe/v4"
fun getType(t: String): TvType { fun getType(t: String): TvType {
return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA
else if (t.contains("Movie", true)) TvType.AnimeMovie else if (t.contains("Movie", true)) TvType.AnimeMovie
@ -111,16 +109,11 @@ class AnimeSailProvider : MainAPI() {
val title = document.selectFirst("h1.entry-title")?.text().toString() val title = document.selectFirst("h1.entry-title")?.text().toString()
.replace("Subtitle Indonesia", "").trim() .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 type = document.select("tbody th:contains(Tipe)").next().text().lowercase()
val year = document.select("tbody th:contains(Dirilis)").next().text().trim().toIntOrNull() 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") val (malId, anilistId, image, cover) = getTracker(title, type, year)
.parsedSafe<JikanResponse>()?.data?.firstOrNull()?.mal_id
val anilistId = app.post(
"https://graphql.anilist.co/", data = mapOf(
"query" to "{Media(idMal:$malId,type:ANIME){id}}",
)
).parsedSafe<DataAni>()?.data?.media?.id
val episodes = document.select("ul.daftar > li").map { val episodes = document.select("ul.daftar > li").map {
val episode = Regex("Episode\\s?([0-9]+)").find( val episode = Regex("Episode\\s?([0-9]+)").find(
@ -131,7 +124,8 @@ class AnimeSailProvider : MainAPI() {
}.reversed() }.reversed()
return newAnimeLoadResponse(title, url, getType(type)) { 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 this.year = year
addEpisodes(DubStatus.Subbed, episodes) addEpisodes(DubStatus.Subbed, episodes)
showStatus = showStatus =
@ -139,7 +133,7 @@ class AnimeSailProvider : MainAPI() {
plot = document.selectFirst("div.entry-content > p")?.text() plot = document.selectFirst("div.entry-content > p")?.text()
this.tags = this.tags =
document.select("tbody th:contains(Genre)").next().select("a").map { it.text() } document.select("tbody th:contains(Genre)").next().select("a").map { it.text() }
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) addAniListId(anilistId?.toIntOrNull())
} }
} }
@ -208,24 +202,41 @@ class AnimeSailProvider : MainAPI() {
return true return true
} }
data class Data( private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker {
@JsonProperty("mal_id") val mal_id: String? = null, val res = app.get("https://api.consumet.org/meta/anilist/$title")
.parsedSafe<AniSearch>()?.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( data class Title(
@JsonProperty("data") val data: ArrayList<Data>? = arrayListOf(), @JsonProperty("romaji") val romaji: String? = null,
@JsonProperty("english") val english: String? = null,
) )
private data class IdAni( data class Results(
@JsonProperty("id") val id: String? = null, @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( data class AniSearch(
@JsonProperty("Media") val media: IdAni? = null, @JsonProperty("results") val results: ArrayList<Results>? = arrayListOf(),
)
private data class DataAni(
@JsonProperty("data") val data: MediaAni? = null,
) )
} }

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 2 version = 3
cloudstream { cloudstream {

View file

@ -23,7 +23,6 @@ class Gomunimeis : MainAPI() {
) )
companion object { companion object {
private const val jikanAPI = "https://api.jikan.moe/v4"
private const val mainImageUrl = "https://upload.anoboy.live" private const val mainImageUrl = "https://upload.anoboy.live"
fun getType(t: String): TvType { fun getType(t: String): TvType {
@ -101,15 +100,7 @@ class Gomunimeis : MainAPI() {
)?.groupValues?.get(1)?.toIntOrNull() )?.groupValues?.get(1)?.toIntOrNull()
val status = getStatus(document.selectFirst(".spe > span")!!.ownText()) val status = getStatus(document.selectFirst(".spe > span")!!.ownText())
val description = document.select("div[itemprop = description] > p").text() val description = document.select("div[itemprop = description] > p").text()
val (malId, anilistId, image, cover) = getTracker(title, type, year)
val malId = app.get("${jikanAPI}/anime?q=$title&start_date=${year}&type=$type&limit=1")
.parsedSafe<JikanResponse>()?.data?.firstOrNull()?.mal_id
val anilistId = app.post(
"https://graphql.anilist.co/", data = mapOf(
"query" to "{Media(idMal:$malId,type:ANIME){id}}",
)
).parsedSafe<DataAni>()?.data?.media?.id
val episodes = document.select(".eplister > ul > li").map { val episodes = document.select(".eplister > ul > li").map {
val episode = Regex("Episode\\s?([0-9]+)").find( val episode = Regex("Episode\\s?([0-9]+)").find(
it.select(".epl-title").text() it.select(".epl-title").text()
@ -120,11 +111,12 @@ class Gomunimeis : MainAPI() {
return newAnimeLoadResponse(title, url, getType(type)) { return newAnimeLoadResponse(title, url, getType(type)) {
engName = title engName = title
posterUrl = poster posterUrl = image ?: poster
backgroundPosterUrl = cover ?: image ?: poster
this.year = year this.year = year
addEpisodes(DubStatus.Subbed, episodes) addEpisodes(DubStatus.Subbed, episodes)
showStatus = status showStatus = status
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) addAniListId(anilistId?.toIntOrNull())
plot = description plot = description
this.tags = tags this.tags = tags
@ -151,6 +143,43 @@ class Gomunimeis : MainAPI() {
return true 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<AniSearch>()?.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<Results>? = arrayListOf(),
)
data class Streamsb( data class Streamsb(
@JsonProperty("link") val link: String?, @JsonProperty("link") val link: String?,
) )
@ -175,24 +204,4 @@ class Gomunimeis : MainAPI() {
@JsonProperty("salt") val salt: String?, @JsonProperty("salt") val salt: String?,
) )
data class Data(
@JsonProperty("mal_id") val mal_id: String? = null,
)
data class JikanResponse(
@JsonProperty("data") val data: ArrayList<Data>? = 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,
)
} }

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 6 version = 7
cloudstream { cloudstream {

View file

@ -5,12 +5,12 @@ import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.ArrayList
class KuramanimeProvider : MainAPI() { class KuramanimeProvider : MainAPI() {
override var mainUrl = "https://kuramanime.net" override var mainUrl = "https://kuramanime.net"
@ -27,8 +27,6 @@ class KuramanimeProvider : MainAPI() {
) )
companion object { companion object {
private const val jikanAPI = "https://api.jikan.moe/v4"
fun getType(t: String): TvType { fun getType(t: String): TvType {
return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA
else if (t.contains("Movie", true)) TvType.AnimeMovie 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 href = getProperAnimeLink(fixUrl(this.selectFirst("a")!!.attr("href")))
val title = this.selectFirst("h5 a")?.text() ?: return null val title = this.selectFirst("h5 a")?.text() ?: return null
val posterUrl = fixUrl(this.select("div.product__item__pic.set-bg").attr("data-setbg")) val posterUrl = fixUrl(this.select("div.product__item__pic.set-bg").attr("data-setbg"))
val episode = Regex("([0-9*])\\s?/").find( val episode = this.select("div.ep span").text().let {
this.select("div.ep span").text() Regex("Ep\\s([0-9]+)\\s/").find(it)?.groupValues?.getOrNull(1)?.toIntOrNull()
)?.groupValues?.getOrNull(1)?.toIntOrNull() }
return newAnimeSearchResponse(title, href, TvType.Anime) { return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl 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 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 description = document.select(".anime__details__text > p").text().trim()
val (malId, anilistId, image, cover) = getTracker(title, type, year)
val malId = app.get("${jikanAPI}/anime?q=$title&start_date=${year}&type=$type&limit=1")
.parsedSafe<JikanResponse>()?.data?.firstOrNull()?.mal_id
val anilistId = app.post(
"https://graphql.anilist.co/", data = mapOf(
"query" to "{Media(idMal:$malId,type:ANIME){id}}",
)
).parsedSafe<DataAni>()?.data?.media?.id
val episodes = mutableListOf<Episode>() val episodes = mutableListOf<Episode>()
@ -148,12 +139,13 @@ class KuramanimeProvider : MainAPI() {
return newAnimeLoadResponse(title, url, getType(type)) { return newAnimeLoadResponse(title, url, getType(type)) {
engName = title engName = title
posterUrl = poster posterUrl = image ?: poster
backgroundPosterUrl = cover ?: image ?: poster
this.year = year this.year = year
addEpisodes(DubStatus.Subbed, episodes) addEpisodes(DubStatus.Subbed, episodes)
showStatus = status showStatus = status
plot = description plot = description
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) addAniListId(anilistId?.toIntOrNull())
this.tags = tags this.tags = tags
this.recommendations = recommendations this.recommendations = recommendations
@ -217,24 +209,41 @@ class KuramanimeProvider : MainAPI() {
return true return true
} }
data class Data( private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker {
@JsonProperty("mal_id") val mal_id: String? = null, val res = app.get("https://api.consumet.org/meta/anilist/$title")
.parsedSafe<AniSearch>()?.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( data class Title(
@JsonProperty("data") val data: ArrayList<Data>? = arrayListOf(), @JsonProperty("romaji") val romaji: String? = null,
@JsonProperty("english") val english: String? = null,
) )
private data class IdAni( data class Results(
@JsonProperty("id") val id: String? = null, @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( data class AniSearch(
@JsonProperty("Media") val media: IdAni? = null, @JsonProperty("results") val results: ArrayList<Results>? = arrayListOf(),
)
private data class DataAni(
@JsonProperty("data") val data: MediaAni? = null,
) )
} }

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 3 version = 4
cloudstream { cloudstream {

View file

@ -11,6 +11,7 @@ import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.ArrayList
class KuronimeProvider : MainAPI() { class KuronimeProvider : MainAPI() {
override var mainUrl = "https://45.12.2.2" override var mainUrl = "https://45.12.2.2"
@ -27,8 +28,6 @@ class KuronimeProvider : MainAPI() {
) )
companion object { companion object {
private const val jikanAPI = "https://api.jikan.moe/v4"
fun getType(t: String): TvType { fun getType(t: String): TvType {
return if (t.contains("OVA", true) || t.contains("Special", true)) TvType.OVA return if (t.contains("OVA", true) || t.contains("Special", true)) TvType.OVA
else if (t.contains("Movie", true)) TvType.AnimeMovie else if (t.contains("Movie", true)) TvType.AnimeMovie
@ -120,13 +119,7 @@ class KuronimeProvider : MainAPI() {
val year = Regex("\\d, ([0-9]*)").find( val year = Regex("\\d, ([0-9]*)").find(
document.select(".infodetail > ul > li:nth-child(5)").text() document.select(".infodetail > ul > li:nth-child(5)").text()
)?.groupValues?.get(1)?.toIntOrNull() )?.groupValues?.get(1)?.toIntOrNull()
val malId = app.get("$jikanAPI/anime?q=$title&start_date=${year}&type=$type&limit=1") val (malId, anilistId, image, cover) = getTracker(title, type, year)
.parsedSafe<JikanResponse>()?.data?.firstOrNull()?.mal_id
val anilistId = app.post(
"https://graphql.anilist.co/", data = mapOf(
"query" to "{Media(idMal:$malId,type:ANIME){id}}",
)
).parsedSafe<DataAni>()?.data?.media?.id
val status = getStatus( val status = getStatus(
document.selectFirst(".infodetail > ul > li:nth-child(3)")!!.ownText() document.selectFirst(".infodetail > ul > li:nth-child(3)")!!.ownText()
.replace(Regex("\\W"), "") .replace(Regex("\\W"), "")
@ -141,12 +134,13 @@ class KuronimeProvider : MainAPI() {
return newAnimeLoadResponse(title, url, getType(type)) { return newAnimeLoadResponse(title, url, getType(type)) {
engName = title engName = title
posterUrl = poster posterUrl = image ?: poster
backgroundPosterUrl = cover ?: image ?: poster
this.year = year this.year = year
addEpisodes(DubStatus.Subbed, episodes) addEpisodes(DubStatus.Subbed, episodes)
showStatus = status showStatus = status
plot = description plot = description
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) addAniListId(anilistId?.toIntOrNull())
addTrailer(trailer) addTrailer(trailer)
this.tags = tags this.tags = tags
@ -206,24 +200,41 @@ class KuronimeProvider : MainAPI() {
return true return true
} }
data class Data( private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker {
@JsonProperty("mal_id") val mal_id: String? = null, val res = app.get("https://api.consumet.org/meta/anilist/$title")
.parsedSafe<AniSearch>()?.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( data class Title(
@JsonProperty("data") val data: ArrayList<Data>? = arrayListOf(), @JsonProperty("romaji") val romaji: String? = null,
@JsonProperty("english") val english: String? = null,
) )
private data class IdAni( data class Results(
@JsonProperty("id") val id: String? = null, @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( data class AniSearch(
@JsonProperty("Media") val media: IdAni? = null, @JsonProperty("results") val results: ArrayList<Results>? = arrayListOf(),
)
private data class DataAni(
@JsonProperty("data") val data: MediaAni? = null,
) )
} }

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 13 version = 14
cloudstream { cloudstream {

View file

@ -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 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 apiUrl = "$api/${base64Decode("Y21zL2FwcA==")}"
private val searchApi = base64Decode("aHR0cHM6Ly9sb2tsb2suY29t") private val searchApi = base64Decode("aHR0cHM6Ly9sb2tsb2suY29t")
private const val jikanAPI = "https://api.jikan.moe/v4"
private const val mainImageUrl = "https://images.weserv.nl" private const val mainImageUrl = "https://images.weserv.nl"
private fun base64DecodeAPI(api: String): String { 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 animeType = if(type == TvType.Anime && data.category == 0) "movie" else "tv"
val (malId, anilistId) = if (type == TvType.Anime) getTracker(
val malId = if(type == TvType.Anime) { res.name,
app.get("${jikanAPI}/anime?q=${res.name}&start_date=${res.year}&type=$animeType&limit=1") animeType,
.parsedSafe<JikanResponse>()?.data?.firstOrNull()?.mal_id res.year
} else { ) else Tracker()
null
}
val anilistId = if(malId != null) {
app.post(
"https://graphql.anilist.co/", data = mapOf(
"query" to "{Media(idMal:$malId,type:ANIME){id}}",
)
).parsedSafe<DataAni>()?.data?.media?.id
} else {
null
}
return newTvSeriesLoadResponse( return newTvSeriesLoadResponse(
res.name ?: return null, res.name ?: return null,
@ -204,7 +192,7 @@ class Loklok : MainAPI() {
this.plot = res.introduction this.plot = res.introduction
this.tags = res.tagNameList this.tags = res.tagNameList
this.rating = res.score.toRatingInt() this.rating = res.score.toRatingInt()
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) addAniListId(anilistId?.toIntOrNull())
this.recommendations = recommendations 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<AniSearch>()?.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( data class UrlData(
val id: Any? = null, val id: Any? = null,
val category: Int? = null, val category: Int? = null,
@ -295,6 +301,25 @@ class Loklok : MainAPI() {
val subtitlingList: List<Subtitling>? = arrayListOf(), val subtitlingList: List<Subtitling>? = 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<Results>? = arrayListOf(),
)
data class QuickSearchData( data class QuickSearchData(
@JsonProperty("searchResults") val searchResults: ArrayList<Media>? = arrayListOf(), @JsonProperty("searchResults") val searchResults: ArrayList<Media>? = arrayListOf(),
) )
@ -378,25 +403,5 @@ class Loklok : MainAPI() {
@JsonProperty("data") val data: Data? = null, @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<DataMal>? = 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,
)
} }

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 3 version = 4
cloudstream { cloudstream {

View file

@ -25,8 +25,6 @@ class NeonimeProvider : MainAPI() {
) )
companion object { companion object {
private const val jikanAPI = "https://api.jikan.moe/v4"
fun getType(t: String): TvType { fun getType(t: String): TvType {
return if (t.contains("OVA", true) || t.contains("Special", true)) TvType.OVA return if (t.contains("OVA", true) || t.contains("Special", true)) TvType.OVA
else if (t.contains("Movie", true)) TvType.AnimeMovie else if (t.contains("Movie", true)) TvType.AnimeMovie
@ -122,27 +120,28 @@ class NeonimeProvider : MainAPI() {
if (url.contains("movie") || url.contains("live-action")) { if (url.contains("movie") || url.contains("live-action")) {
val mTitle = document.selectFirst(".sbox > .data > h1[itemprop = name]")?.text().toString().replace("Subtitle Indonesia", "").trim() 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 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 year = document.selectFirst("a[href*=release-year]")!!.text().toIntOrNull()
val malId = getMalId(mTitle, year, "movie") val (malId, anilistId, image, cover) = getTracker(mTitle, "movie", year)
val anilistId = getAniId(malId)
return newMovieLoadResponse(name = mTitle, url = url, type = TvType.Movie, dataUrl = url) { 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 this.year = year
plot = document.select("div[itemprop = description]").text().trim() plot = document.select("div[itemprop = description]").text().trim()
rating = document.select("span[itemprop = ratingValue]").text().toIntOrNull() rating = document.select("span[itemprop = ratingValue]").text().toIntOrNull()
tags = document.select("p.meta_dd > a").map { it.text() } tags = document.select("p.meta_dd > a").map { it.text() }
addTrailer(mTrailer) addTrailer(mTrailer)
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) addAniListId(anilistId?.toIntOrNull())
} }
} }
else { else {
val title = document.select("h1[itemprop = name]").text().replace("Subtitle Indonesia", "").trim() 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 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 year = document.select("#info a[href*=\"-year/\"]").text().toIntOrNull()
val malId = getMalId(title, year, "tv") val (malId, anilistId, image, cover) = getTracker(title, "tv", year)
val anilistId = getAniId(malId)
val episodes = document.select("ul.episodios > li").mapNotNull { val episodes = document.select("ul.episodios > li").mapNotNull {
val header = it.selectFirst(".episodiotitle > a")?.ownText().toString() val header = it.selectFirst(".episodiotitle > a")?.ownText().toString()
val name = Regex("(Episode\\s?[0-9]+)").find(header)?.groupValues?.getOrNull(0) ?: header 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) { return newAnimeLoadResponse(title, url, TvType.Anime) {
engName = title engName = title
posterUrl = document.selectFirst(".imagen > img")?.attr("data-src") posterUrl = image ?: poster
backgroundPosterUrl = cover ?: image ?: poster
this.year = year this.year = year
addEpisodes(DubStatus.Subbed, episodes) addEpisodes(DubStatus.Subbed, episodes)
showStatus = getStatus(document.select("div.metadatac > span").last()!!.text().trim()) showStatus = getStatus(document.select("div.metadatac > span").last()!!.text().trim())
plot = document.select("div[itemprop = description] > p").text().trim() plot = document.select("div[itemprop = description] > p").text().trim()
tags = document.select("#info a[href*=\"-genre/\"]").map { it.text() } tags = document.select("#info a[href*=\"-genre/\"]").map { it.text() }
addTrailer(trailer) addTrailer(trailer)
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) 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<DataAni>()?.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<JikanResponse>()?.data?.firstOrNull()?.mal_id
}
override suspend fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
@ -201,24 +188,41 @@ class NeonimeProvider : MainAPI() {
return true return true
} }
data class Data( private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker {
@JsonProperty("mal_id") val mal_id: String? = null, val res = app.get("https://api.consumet.org/meta/anilist/$title")
.parsedSafe<AniSearch>()?.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( data class Title(
@JsonProperty("data") val data: ArrayList<Data>? = arrayListOf(), @JsonProperty("romaji") val romaji: String? = null,
@JsonProperty("english") val english: String? = null,
) )
private data class IdAni( data class Results(
@JsonProperty("id") val id: String? = null, @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( data class AniSearch(
@JsonProperty("Media") val media: IdAni? = null, @JsonProperty("results") val results: ArrayList<Results>? = arrayListOf(),
)
private data class DataAni(
@JsonProperty("data") val data: MediaAni? = null,
) )
} }

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 8 version = 9
cloudstream { cloudstream {

View file

@ -25,8 +25,6 @@ class NontonAnimeIDProvider : MainAPI() {
) )
companion object { companion object {
private const val jikanAPI = "https://api.jikan.moe/v4"
fun getType(t: String): TvType { fun getType(t: String): TvType {
return when { return when {
t.contains("TV",true) -> TvType.Anime t.contains("TV",true) -> TvType.Anime
@ -135,13 +133,7 @@ class NontonAnimeIDProvider : MainAPI() {
val description = document.select(".entry-content.seriesdesc > p").text().trim() val description = document.select(".entry-content.seriesdesc > p").text().trim()
val trailer = document.selectFirst("a.trailerbutton")?.attr("href") val trailer = document.selectFirst("a.trailerbutton")?.attr("href")
val malId = app.get("${jikanAPI}/anime?q=$title&start_date=${year}&type=$type&limit=1") val (malId, anilistId, image, cover) = getTracker(title, type, year)
.parsedSafe<JikanResponse>()?.data?.firstOrNull()?.mal_id
val anilistId = app.post(
"https://graphql.anilist.co/", data = mapOf(
"query" to "{Media(idMal:$malId,type:ANIME){id}}",
)
).parsedSafe<DataAni>()?.data?.media?.id
val episodes = if (document.select("button.buttfilter").isNotEmpty()) { val episodes = if (document.select("button.buttfilter").isNotEmpty()) {
val id = document.select("input[name=series_id]").attr("value") val id = document.select("input[name=series_id]").attr("value")
@ -189,13 +181,14 @@ class NontonAnimeIDProvider : MainAPI() {
return newAnimeLoadResponse(title, url, getType(type)) { return newAnimeLoadResponse(title, url, getType(type)) {
engName = title engName = title
posterUrl = poster posterUrl = image ?: poster
backgroundPosterUrl = cover ?: image ?: poster
this.year = year this.year = year
addEpisodes(DubStatus.Subbed, episodes) addEpisodes(DubStatus.Subbed, episodes)
showStatus = status showStatus = status
this.rating = rating this.rating = rating
plot = description plot = description
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) addAniListId(anilistId?.toIntOrNull())
addTrailer(trailer) addTrailer(trailer)
this.tags = tags this.tags = tags
@ -241,6 +234,43 @@ class NontonAnimeIDProvider : MainAPI() {
return true 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<AniSearch>()?.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<Results>? = arrayListOf(),
)
private data class EpResponse( private data class EpResponse(
@JsonProperty("posts") val posts: String?, @JsonProperty("posts") val posts: String?,
@JsonProperty("max_page") val max_page: Int?, @JsonProperty("max_page") val max_page: Int?,
@ -248,23 +278,4 @@ class NontonAnimeIDProvider : MainAPI() {
@JsonProperty("content") val content: String @JsonProperty("content") val content: String
) )
data class Data(
@JsonProperty("mal_id") val mal_id: String? = null,
)
data class JikanResponse(
@JsonProperty("data") val data: ArrayList<Data>? = 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,
)
} }

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 4 version = 5
cloudstream { cloudstream {

View file

@ -25,8 +25,6 @@ class OploverzProvider : MainAPI() {
) )
companion object { companion object {
private const val jikanAPI = "https://api.jikan.moe/v4"
fun getType(t: String): TvType { fun getType(t: String): TvType {
return when { return when {
t.contains("TV") -> TvType.Anime t.contains("TV") -> TvType.Anime
@ -146,13 +144,7 @@ class OploverzProvider : MainAPI() {
val description = document.select(".entry-content > p").text().trim() val description = document.select(".entry-content > p").text().trim()
val trailer = document.selectFirst("a.trailerbutton")?.attr("href") val trailer = document.selectFirst("a.trailerbutton")?.attr("href")
val malId = app.get("${jikanAPI}/anime?q=$title&start_date=${year}&${typeCheck.lowercase()}&limit=1") val (malId, anilistId, image, cover) = getTracker(title, typeCheck, year)
.parsedSafe<JikanResponse>()?.data?.firstOrNull()?.mal_id
val anilistId = app.post(
"https://graphql.anilist.co/", data = mapOf(
"query" to "{Media(idMal:$malId,type:ANIME){id}}",
)
).parsedSafe<DataAni>()?.data?.media?.id
val episodes = document.select(".eplister > ul > li").map { val episodes = document.select(".eplister > ul > li").map {
val header = it.select(".epl-title").text() val header = it.select(".epl-title").text()
@ -176,13 +168,14 @@ class OploverzProvider : MainAPI() {
return newAnimeLoadResponse(title, url, type) { return newAnimeLoadResponse(title, url, type) {
engName = title engName = title
posterUrl = poster posterUrl = image ?: poster
backgroundPosterUrl = cover ?: image ?: poster
this.year = year this.year = year
addEpisodes(DubStatus.Subbed, episodes) addEpisodes(DubStatus.Subbed, episodes)
showStatus = status showStatus = status
plot = description plot = description
this.tags = tags this.tags = tags
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) addAniListId(anilistId?.toIntOrNull())
this.recommendations = recommendations this.recommendations = recommendations
addTrailer(trailer) 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( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
@ -213,24 +201,41 @@ class OploverzProvider : MainAPI() {
return true return true
} }
data class Data( private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker {
@JsonProperty("mal_id") val mal_id: String? = null, val res = app.get("https://api.consumet.org/meta/anilist/$title")
.parsedSafe<AniSearch>()?.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( data class Title(
@JsonProperty("data") val data: ArrayList<Data>? = arrayListOf(), @JsonProperty("romaji") val romaji: String? = null,
@JsonProperty("english") val english: String? = null,
) )
private data class IdAni( data class Results(
@JsonProperty("id") val id: String? = null, @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( data class AniSearch(
@JsonProperty("Media") val media: IdAni? = null, @JsonProperty("results") val results: ArrayList<Results>? = arrayListOf(),
)
private data class DataAni(
@JsonProperty("data") val data: MediaAni? = null,
) )
} }

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 6 version = 7
cloudstream { cloudstream {

View file

@ -4,12 +4,12 @@ import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId 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.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.ArrayList
class OtakudesuProvider : MainAPI() { class OtakudesuProvider : MainAPI() {
override var mainUrl = "https://otakudesu.bid" override var mainUrl = "https://otakudesu.bid"
@ -26,8 +26,6 @@ class OtakudesuProvider : MainAPI() {
companion object { companion object {
// private val interceptor = CloudflareKiller() // private val interceptor = CloudflareKiller()
private const val jikanAPI = "https://api.jikan.moe/v4"
fun getType(t: String): TvType { fun getType(t: String): TvType {
return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA
else if (t.contains("Movie", true)) TvType.AnimeMovie else if (t.contains("Movie", true)) TvType.AnimeMovie
@ -117,13 +115,8 @@ class OtakudesuProvider : MainAPI() {
.trim() .trim()
) )
val description = document.select("div.sinopc > p").text() val description = document.select("div.sinopc > p").text()
val malId = app.get("${jikanAPI}/anime?q=$title&start_date=${year}&type=$type&limit=1")
.parsedSafe<JikanResponse>()?.data?.firstOrNull()?.mal_id val (malId, anilistId, image, cover) = getTracker(title, type, year)
val anilistId = app.post(
"https://graphql.anilist.co/", data = mapOf(
"query" to "{Media(idMal:$malId,type:ANIME){id}}",
)
).parsedSafe<DataAni>()?.data?.media?.id
val episodes = document.select("div.episodelist")[1].select("ul > li").mapNotNull { val episodes = document.select("div.episodelist")[1].select("ul > li").mapNotNull {
val name = it.selectFirst("a")?.text() ?: return@mapNotNull null val name = it.selectFirst("a")?.text() ?: return@mapNotNull null
@ -146,13 +139,14 @@ class OtakudesuProvider : MainAPI() {
return newAnimeLoadResponse(title, url, getType(type)) { return newAnimeLoadResponse(title, url, getType(type)) {
engName = title engName = title
posterUrl = poster posterUrl = image ?: poster
backgroundPosterUrl = cover ?: image ?: poster
this.year = year this.year = year
addEpisodes(DubStatus.Subbed, episodes) addEpisodes(DubStatus.Subbed, episodes)
showStatus = status showStatus = status
plot = description plot = description
this.tags = tags this.tags = tags
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) addAniListId(anilistId?.toIntOrNull())
this.recommendations = recommendations this.recommendations = recommendations
// posterHeaders = interceptor.getCookieHeaders(url).toMap() // posterHeaders = interceptor.getCookieHeaders(url).toMap()
@ -230,24 +224,41 @@ class OtakudesuProvider : MainAPI() {
return true return true
} }
data class Data( private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker {
@JsonProperty("mal_id") val mal_id: String? = null, val res = app.get("https://api.consumet.org/meta/anilist/$title")
.parsedSafe<AniSearch>()?.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( data class Title(
@JsonProperty("data") val data: ArrayList<Data>? = arrayListOf(), @JsonProperty("romaji") val romaji: String? = null,
@JsonProperty("english") val english: String? = null,
) )
private data class IdAni( data class Results(
@JsonProperty("id") val id: String? = null, @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( data class AniSearch(
@JsonProperty("Media") val media: IdAni? = null, @JsonProperty("results") val results: ArrayList<Results>? = arrayListOf(),
)
private data class DataAni(
@JsonProperty("data") val data: MediaAni? = null,
) )
} }

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 4 version = 5
cloudstream { cloudstream {

View file

@ -24,8 +24,6 @@ class Samehadaku : MainAPI() {
) )
companion object { companion object {
private const val jikanAPI = "https://api.jikan.moe/v4"
fun getType(t: String): TvType { fun getType(t: String): TvType {
return if (t.contains("OVA", true) || t.contains("Special", true)) TvType.OVA return if (t.contains("OVA", true) || t.contains("Special", true)) TvType.OVA
else if (t.contains("Movie", true)) TvType.AnimeMovie 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 description = document.select("div.desc p").text().trim()
val trailer = document.selectFirst("div.trailer-anime iframe")?.attr("src") 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") val (malId, anilistId, image, cover) = getTracker(title, type, year)
.parsedSafe<JikanResponse>()?.data?.firstOrNull()?.mal_id
val anilistId = app.post(
"https://graphql.anilist.co/", data = mapOf(
"query" to "{Media(idMal:$malId,type:ANIME){id}}",
)
).parsedSafe<DataAni>()?.data?.media?.id
val episodes = document.select("div.lstepsiode.listeps ul li").mapNotNull { val episodes = document.select("div.lstepsiode.listeps ul li").mapNotNull {
val header = it.selectFirst("span.lchx > a") ?: return@mapNotNull null val header = it.selectFirst("span.lchx > a") ?: return@mapNotNull null
@ -136,13 +128,14 @@ class Samehadaku : MainAPI() {
return newAnimeLoadResponse(title, url, getType(type)) { return newAnimeLoadResponse(title, url, getType(type)) {
engName = title engName = title
posterUrl = poster posterUrl = image ?: poster
backgroundPosterUrl = cover ?: image ?: poster
this.year = year this.year = year
addEpisodes(DubStatus.Subbed, episodes) addEpisodes(DubStatus.Subbed, episodes)
showStatus = status showStatus = status
this.rating = rating this.rating = rating
plot = description plot = description
addMalId(malId?.toIntOrNull()) addMalId(malId)
addAniListId(anilistId?.toIntOrNull()) addAniListId(anilistId?.toIntOrNull())
addTrailer(trailer) addTrailer(trailer)
this.tags = tags this.tags = tags
@ -187,24 +180,41 @@ class Samehadaku : MainAPI() {
return true return true
} }
data class Data( private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker {
@JsonProperty("mal_id") val mal_id: String? = null, val res = app.get("https://api.consumet.org/meta/anilist/$title")
.parsedSafe<AniSearch>()?.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( data class Title(
@JsonProperty("data") val data: ArrayList<Data>? = arrayListOf(), @JsonProperty("romaji") val romaji: String? = null,
@JsonProperty("english") val english: String? = null,
) )
private data class IdAni( data class Results(
@JsonProperty("id") val id: String? = null, @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( data class AniSearch(
@JsonProperty("Media") val media: IdAni? = null, @JsonProperty("results") val results: java.util.ArrayList<Results>? = arrayListOf(),
)
private data class DataAni(
@JsonProperty("data") val data: MediaAni? = null,
) )
} }

View file

@ -1352,13 +1352,12 @@ object SoraExtractor : SoraStream() {
sources.addAll(iframeList.filter { it.first.contains("1080p", true) }) sources.addAll(iframeList.filter { it.first.contains("1080p", true) })
} }
val base = "https://drivebit.in"
sources.apmap { (quality, link) -> sources.apmap { (quality, link) ->
delay(2000) delay(2000)
val driveLink = bypassHrefli(link ?: return@apmap null) val driveLink = bypassHrefli(link ?: return@apmap null)
val res = app.get(driveLink ?: return@apmap null).document val base = getBaseUrl(driveLink ?: return@apmap null)
val resDoc = res.selectFirst("script")?.data()?.substringAfter("replace(\"") val resDoc = app.get(driveLink).text.substringAfter("replace(\"")
?.substringBefore("\")")?.let { .substringBefore("\")").let {
app.get(fixUrl(it, base)).document app.get(fixUrl(it, base)).document
} }
val bitLink = resDoc?.selectFirst("a.btn.btn-outline-success")?.attr("href") val bitLink = resDoc?.selectFirst("a.btn.btn-outline-success")?.attr("href")

View file

@ -66,14 +66,27 @@ fun String.filterMedia(title: String?, yearNum: Int?, seasonNum: Int?): Boolean
} }
} }
suspend fun extractMirrorUHD(url: String, ref: String): String? { fun Document.getMirrorLink(): String? {
val baseDoc = app.get(fixUrl(url, ref)).document return this.select("div.mb-4 a").randomOrNull()
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") ?.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? {
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 val downPage = app.get(downLink ?: return null).document
return downPage.selectFirst("form[method=post] a.btn.btn-success") return downPage.selectFirst("form[method=post] a.btn.btn-success")
?.attr("onclick")?.substringAfter("Openblank('")?.substringBefore("')") ?: run { ?.attr("onclick")?.substringAfter("Openblank('")?.substringBefore("')") ?: run {
@ -93,7 +106,8 @@ suspend fun extractBackupUHD(url: String): String? {
val ssid = resumeDoc.cookies["PHPSESSID"] val ssid = resumeDoc.cookies["PHPSESSID"]
val baseIframe = getBaseUrl(url) 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 token = script?.substringAfter("'token', '")?.substringBefore("');")
val body = FormBody.Builder() val body = FormBody.Builder()
@ -146,14 +160,16 @@ suspend fun extractGdbot(url: String): String? {
} }
suspend fun extractDirectDl(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 request = app.get(iframe ?: return null)
val driveDoc = request.document val driveDoc = request.document
val token = driveDoc.select("section#generate_url").attr("data-token") val token = driveDoc.select("section#generate_url").attr("data-token")
val uid = driveDoc.select("section#generate_url").attr("data-uid") val uid = driveDoc.select("section#generate_url").attr("data-uid")
val ssid = request.cookies["PHPSESSID"] val ssid = request.cookies["PHPSESSID"]
val body = """{"type":"DOWNLOAD_GENERATE","payload":{"uid":"$uid","access_token":"$token"}}""".toRequestBody( val body =
"""{"type":"DOWNLOAD_GENERATE","payload":{"uid":"$uid","access_token":"$token"}}""".toRequestBody(
RequestBodyTypes.JSON.toMediaTypeOrNull() RequestBodyTypes.JSON.toMediaTypeOrNull()
) )
@ -168,17 +184,20 @@ suspend fun extractDirectDl(url: String): String? {
} }
suspend fun extractDrivebot(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 ?.attr("href") ?: return null
return getDrivebotLink(iframeDrivebot) return getDrivebotLink(iframeDrivebot)
} }
suspend fun extractGdflix(url: String): String? { suspend fun extractGdflix(url: String): String? {
val iframeGdflix = app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(GDFlix Direct)") val iframeGdflix =
app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(GDFlix Direct)")
?.attr("href") ?: return null ?.attr("href") ?: return null
val base = getBaseUrl(iframeGdflix) 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 { ?.substringBefore("\")")?.let {
app.get(fixUrl(it, base)).document 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) var res = session.get(url ?: return null)
run lit@{ run lit@{
(1..2).forEach { _ -> (1..2).forEach { _ ->
@ -322,7 +341,8 @@ fun String.splitData(): List<String> {
} }
suspend fun bypassFdAds(url: String?): String? { suspend fun bypassFdAds(url: String?): String? {
val directUrl = app.get(url ?: return null, verify = false).document.select("a#link").attr("href") val directUrl =
app.get(url ?: return null, verify = false).document.select("a#link").attr("href")
.substringAfter("/go/") .substringAfter("/go/")
.let { base64Decode(it) } .let { base64Decode(it) }
val doc = app.get(directUrl, verify = false).document val doc = app.get(directUrl, verify = false).document
@ -331,45 +351,37 @@ suspend fun bypassFdAds(url: String?): String? {
data = mapOf("go" to doc.select("form#landing input").attr("value")), data = mapOf("go" to doc.select("form#landing input").attr("value")),
verify = false verify = false
).document ).document
val json = lastDoc.select("form#landing input[name=newwpsafelink]").attr("value").let { base64Decode(it) } val json = lastDoc.select("form#landing input[name=newwpsafelink]").attr("value")
val finalJson = tryParseJson<FDAds>(json)?.linkr?.substringAfter("redirect=")?.let { base64Decode(it) } .let { base64Decode(it) }
val finalJson =
tryParseJson<FDAds>(json)?.linkr?.substringAfter("redirect=")?.let { base64Decode(it) }
return tryParseJson<Safelink>(finalJson)?.safelink return tryParseJson<Safelink>(finalJson)?.safelink
} }
suspend fun bypassHrefli(url: String): String? { suspend fun bypassHrefli(url: String): String? {
val direct = url.removePrefix("https://href.li/?") var res = app.get(url.removePrefix("https://href.li/?"))
(1..2).forEach { _ ->
val res = app.get(direct).document val document = res.document
val formLink = res.select("form#landing").attr("action") val nextUrl = document.select("form").attr("action")
val wpHttp = res.select("input[name=_wp_http]").attr("value") val data = document.select("form input").mapNotNull {
it.attr("name") to it.attr("value")
val res2 = app.post(formLink, data = mapOf("_wp_http" to wpHttp)).document }.toMap()
val formLink2 = res2.select("form#landing").attr("action") res = app.post(
val wpHttp2 = res2.select("input[name=_wp_http2]").attr("value") nextUrl,
val token = res2.select("input[name=token]").attr("value") data = data,
val res3 = app.post(
formLink2, data = mapOf(
"_wp_http2" to wpHttp2, "token" to token
) )
).document }
val script = res.document.selectFirst("script:containsData(verify_button)")?.data()
val script = res3.selectFirst("script:containsData(verify_button)")?.data() val goUrl = script?.substringAfter("\"href\",\"")?.substringBefore("\")")
val directLink = script?.substringAfter("\"href\",\"")?.substringBefore("\")") val cookies =
val matchCookies =
Regex("sumitbot_\\('(\\S+?)',\n|.?'(\\S+?)',").findAll(script ?: return null).map { Regex("sumitbot_\\('(\\S+?)',\n|.?'(\\S+?)',").findAll(script ?: return null).map {
it.groupValues[2] it.groupValues[2]
}.toList() }.toList().let {
mapOf(it.first() to it.last())
val cookeName = matchCookies.firstOrNull() ?: return null }.ifEmpty { return null }
val cookeValue = matchCookies.lastOrNull() ?: return null
val cookies = mapOf(
cookeName to cookeValue
)
return app.get( return app.get(
directLink ?: return null, goUrl ?: return null,
cookies = cookies cookies = cookies
).document.selectFirst("meta[http-equiv=refresh]")?.attr("content")?.substringAfter("url=") ).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<String, String?>? { suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair<String, String?>? {
val req = app.get(url) val req = app.get(url)
if(!req.isSuccessful) return null if (!req.isSuccessful) return null
val doc = req.document val doc = req.document
return if (season == null) { return if (season == null) {