mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
sora: make my own mapping for anime
This commit is contained in:
parent
aa25976a1b
commit
03d3731979
4 changed files with 184 additions and 72 deletions
|
@ -15,6 +15,7 @@ import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import okio.ByteString.Companion.encode
|
import okio.ByteString.Companion.encode
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
val session = Session(Requests().baseClient)
|
val session = Session(Requests().baseClient)
|
||||||
|
|
||||||
|
@ -729,6 +730,16 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
val servers = tryParseJson<HashMap<String, String>>(serversKname)
|
val servers = tryParseJson<HashMap<String, String>>(serversKname)
|
||||||
|
|
||||||
|
val sub = app.get("$fmoviesAPI/ajax/episode/subtitles/${servers?.get("28")}").text
|
||||||
|
tryParseJson<List<FmoviesSubtitles>>(sub)?.map {
|
||||||
|
subtitleCallback.invoke(
|
||||||
|
SubtitleFile(
|
||||||
|
it.label ?: "",
|
||||||
|
it.file ?: return@map
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
servers?.apmap { server ->
|
servers?.apmap { server ->
|
||||||
val decryptServer = app.get("$fmoviesAPI/ajax/episode/info?id=${server.value}")
|
val decryptServer = app.get("$fmoviesAPI/ajax/episode/info?id=${server.value}")
|
||||||
.parsedSafe<FmoviesResponses>()?.url?.let { decodeVrf(it) } ?: return@apmap
|
.parsedSafe<FmoviesResponses>()?.url?.let { decodeVrf(it) } ?: return@apmap
|
||||||
|
@ -738,16 +749,6 @@ object SoraExtractor : SoraStream() {
|
||||||
loadExtractor(decryptServer, fmoviesAPI, subtitleCallback, callback)
|
loadExtractor(decryptServer, fmoviesAPI, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val sub = app.get("$fmoviesAPI/ajax/episode/subtitles/${servers?.get("28") ?: return}").text
|
|
||||||
tryParseJson<List<FmoviesSubtitles>>(sub)?.map {
|
|
||||||
subtitleCallback.invoke(
|
|
||||||
SubtitleFile(
|
|
||||||
it.label ?: "",
|
|
||||||
it.file ?: return@map
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun invokeKisskh(
|
suspend fun invokeKisskh(
|
||||||
|
@ -829,19 +830,17 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun invokeAnimes(
|
suspend fun invokeAnimes(
|
||||||
id: Int? = null,
|
|
||||||
title: String? = null,
|
title: String? = null,
|
||||||
jpTitle: String? = null,
|
|
||||||
epsTitle: String? = null,
|
epsTitle: String? = null,
|
||||||
year: Int? = null,
|
date: String?,
|
||||||
|
airedDate: String?,
|
||||||
season: Int? = null,
|
season: Int? = null,
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val (aniId, malId) = app.get(
|
|
||||||
if (season == null) "$tmdb2anilist/movie/?id=$id" else "$tmdb2anilist/tv/?id=$id&s=$season"
|
val (aniId, malId) = convertTmdbToAnimeId(title, date, airedDate, if(season == null) TvType.AnimeMovie else TvType.Anime)
|
||||||
).parsedSafe<Tmdb2Anilist>().let { it?.anilist_id to it?.mal_id }
|
|
||||||
|
|
||||||
argamap(
|
argamap(
|
||||||
{
|
{
|
||||||
|
@ -860,7 +859,7 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun invokeBiliBili(
|
private suspend fun invokeBiliBili(
|
||||||
aniId: String? = null,
|
aniId: Int? = null,
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
|
@ -904,22 +903,23 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun invokeZoro(
|
private suspend fun invokeZoro(
|
||||||
aniId: String? = null,
|
aniId: Int? = null,
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val animeId =
|
val animeId =
|
||||||
app.get("https://raw.githubusercontent.com/MALSync/MAL-Sync-Backup/master/data/anilist/anime/$aniId.json")
|
app.get("https://raw.githubusercontent.com/MALSync/MAL-Sync-Backup/master/data/anilist/anime/${aniId ?: return}.json")
|
||||||
.parsedSafe<MALSyncResponses>()?.pages?.zoro?.keys?.firstOrNull()
|
.parsedSafe<MALSyncResponses>()?.pages?.zoro?.keys?.map { it }
|
||||||
|
|
||||||
val episodeId = app.get("$zoroAPI/ajax/v2/episode/list/${animeId ?: return}")
|
animeId?.apmap { id ->
|
||||||
|
val episodeId = app.get("$zoroAPI/ajax/v2/episode/list/${id ?: return@apmap}")
|
||||||
.parsedSafe<ZoroResponses>()?.html?.let {
|
.parsedSafe<ZoroResponses>()?.html?.let {
|
||||||
Jsoup.parse(it)
|
Jsoup.parse(it)
|
||||||
}?.select("div.ss-list a")?.find { it.attr("data-number") == "$episode" }
|
}?.select("div.ss-list a")?.find { it.attr("data-number") == "$episode" }
|
||||||
?.attr("data-id")
|
?.attr("data-id")
|
||||||
|
|
||||||
val servers = app.get("$zoroAPI/ajax/v2/episode/servers?episodeId=${episodeId ?: return}")
|
val servers = app.get("$zoroAPI/ajax/v2/episode/servers?episodeId=${episodeId ?: return@apmap}")
|
||||||
.parsedSafe<ZoroResponses>()?.html?.let { Jsoup.parse(it) }
|
.parsedSafe<ZoroResponses>()?.html?.let { Jsoup.parse(it) }
|
||||||
?.select("div.item.server-item")?.map {
|
?.select("div.item.server-item")?.map {
|
||||||
Triple(
|
Triple(
|
||||||
|
@ -929,9 +929,9 @@ object SoraExtractor : SoraStream() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
servers?.apmap { server ->
|
servers?.apmap servers@{ server ->
|
||||||
val iframe = app.get("$zoroAPI/ajax/v2/episode/sources?id=${server.second ?: return@apmap}")
|
val iframe = app.get("$zoroAPI/ajax/v2/episode/sources?id=${server.second ?: return@servers}")
|
||||||
.parsedSafe<ZoroResponses>()?.link ?: return@apmap
|
.parsedSafe<ZoroResponses>()?.link ?: return@servers
|
||||||
val audio = if(server.third == "sub") "Raw" else "English Dub"
|
val audio = if(server.third == "sub") "Raw" else "English Dub"
|
||||||
if(server.first == "Vidstreaming" || server.first == "Vidcloud") {
|
if(server.first == "Vidstreaming" || server.first == "Vidcloud") {
|
||||||
extractRabbitStream(
|
extractRabbitStream(
|
||||||
|
@ -948,22 +948,23 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun invokeAnimeKaizoku(
|
private suspend fun invokeAnimeKaizoku(
|
||||||
malId: String? = null,
|
malId: Int? = null,
|
||||||
epsTitle: String? = null,
|
epsTitle: String? = null,
|
||||||
season: Int? = null,
|
season: Int? = null,
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val search = app.get("$animeKaizokuAPI/?s=$malId").document
|
val search = app.get("$animeKaizokuAPI/?s=${malId ?: return}").document
|
||||||
val detailHref =
|
val detailHref =
|
||||||
search.select("ul#posts-container li").map { it.selectFirst("a")?.attr("href") }
|
search.select("ul#posts-container li").map { it.selectFirst("a")?.attr("href") }
|
||||||
.find {
|
.find {
|
||||||
it?.contains(malId ?: return) == true
|
it?.contains("$malId") == true
|
||||||
}?.let { fixUrl(it, animeKaizokuAPI) }
|
}?.let { fixUrl(it, animeKaizokuAPI) }
|
||||||
|
|
||||||
val detail = app.get(detailHref ?: return).document
|
val detail = app.get(detailHref ?: return).document
|
||||||
|
@ -1467,14 +1468,14 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun invokeCrunchyroll(
|
suspend fun invokeCrunchyroll(
|
||||||
aniId: String? = null,
|
aniId: Int? = null,
|
||||||
epsTitle: String? = null,
|
epsTitle: String? = null,
|
||||||
season: Int? = null,
|
season: Int? = null,
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val id = getCrunchyrollId(aniId)
|
val id = getCrunchyrollId("${aniId ?: return}")
|
||||||
val audioLocal = listOf(
|
val audioLocal = listOf(
|
||||||
"ja-JP",
|
"ja-JP",
|
||||||
"en-US",
|
"en-US",
|
||||||
|
@ -2875,6 +2876,28 @@ data class BaymoviesConfig(
|
||||||
val workers: List<String>
|
val workers: List<String>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class AniIds(
|
||||||
|
var id: Int? = null,
|
||||||
|
var idMal: Int? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class AniMedia(
|
||||||
|
@JsonProperty("id") var id: Int? = null,
|
||||||
|
@JsonProperty("idMal") var idMal: Int? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class AniPage(
|
||||||
|
@JsonProperty("media") var media: java.util.ArrayList<AniMedia> = arrayListOf()
|
||||||
|
)
|
||||||
|
|
||||||
|
data class AniData(
|
||||||
|
@JsonProperty("Page") var Page: AniPage? = AniPage()
|
||||||
|
)
|
||||||
|
|
||||||
|
data class AniSearch(
|
||||||
|
@JsonProperty("data") var data: AniData? = AniData()
|
||||||
|
)
|
||||||
|
|
||||||
data class Tmdb2Anilist(
|
data class Tmdb2Anilist(
|
||||||
@JsonProperty("tmdb_id") val tmdb_id: String? = null,
|
@JsonProperty("tmdb_id") val tmdb_id: String? = null,
|
||||||
@JsonProperty("anilist_id") val anilist_id: String? = null,
|
@JsonProperty("anilist_id") val anilist_id: String? = null,
|
||||||
|
@ -3264,7 +3287,7 @@ data class CrunchyrollSourcesResponses(
|
||||||
)
|
)
|
||||||
|
|
||||||
data class MALSyncPages(
|
data class MALSyncPages(
|
||||||
@JsonProperty("Zoro") val zoro: HashMap<String, HashMap<String, String>>? = hashMapOf(),
|
@JsonProperty("Zoro") val zoro: HashMap<String?, HashMap<String, String?>>? = hashMapOf(),
|
||||||
)
|
)
|
||||||
|
|
||||||
data class MALSyncResponses(
|
data class MALSyncResponses(
|
||||||
|
|
|
@ -74,8 +74,8 @@ open class SoraStream : TmdbProvider() {
|
||||||
companion object {
|
companion object {
|
||||||
/** TOOLS */
|
/** TOOLS */
|
||||||
private const val tmdbAPI = "https://api.themoviedb.org/3"
|
private const val tmdbAPI = "https://api.themoviedb.org/3"
|
||||||
const val tmdb2anilist = "https://tmdb2anilist.slidemovies.org"
|
|
||||||
const val gdbot = "https://gdtot.pro"
|
const val gdbot = "https://gdtot.pro"
|
||||||
|
const val anilistAPI = "https://graphql.anilist.co"
|
||||||
|
|
||||||
private val apiKey = base64DecodeAPI("ZTM=NTg=MjM=MjM=ODc=MzI=OGQ=MmE=Nzk=Nzk=ZjI=NTA=NDY=NDA=MzA=YjA=") // PLEASE DON'T STEAL
|
private val apiKey = base64DecodeAPI("ZTM=NTg=MjM=MjM=ODc=MzI=OGQ=MmE=Nzk=Nzk=ZjI=NTA=NDY=NDA=MzA=YjA=") // PLEASE DON'T STEAL
|
||||||
|
|
||||||
|
@ -291,7 +291,9 @@ open class SoraStream : TmdbProvider() {
|
||||||
airedYear = year,
|
airedYear = year,
|
||||||
lastSeason = lastSeason,
|
lastSeason = lastSeason,
|
||||||
epsTitle = eps.name,
|
epsTitle = eps.name,
|
||||||
jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title
|
jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title,
|
||||||
|
date = season.airDate,
|
||||||
|
airedDate = res.releaseDate ?: res.firstAirDate
|
||||||
).toJson(),
|
).toJson(),
|
||||||
name = eps.name,
|
name = eps.name,
|
||||||
season = eps.seasonNumber,
|
season = eps.seasonNumber,
|
||||||
|
@ -334,7 +336,8 @@ open class SoraStream : TmdbProvider() {
|
||||||
year = year,
|
year = year,
|
||||||
orgTitle = orgTitle,
|
orgTitle = orgTitle,
|
||||||
isAnime = isAnime,
|
isAnime = isAnime,
|
||||||
jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title
|
jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title,
|
||||||
|
airedDate = res.releaseDate ?: res.firstAirDate
|
||||||
).toJson(),
|
).toJson(),
|
||||||
) {
|
) {
|
||||||
this.posterUrl = poster
|
this.posterUrl = poster
|
||||||
|
@ -399,11 +402,10 @@ open class SoraStream : TmdbProvider() {
|
||||||
// },
|
// },
|
||||||
{
|
{
|
||||||
if (res.isAnime) invokeAnimes(
|
if (res.isAnime) invokeAnimes(
|
||||||
res.id,
|
|
||||||
res.title,
|
res.title,
|
||||||
res.jpTitle,
|
|
||||||
res.epsTitle,
|
res.epsTitle,
|
||||||
res.airedYear ?: res.year,
|
res.date,
|
||||||
|
res.airedDate,
|
||||||
res.season,
|
res.season,
|
||||||
res.episode,
|
res.episode,
|
||||||
subtitleCallback,
|
subtitleCallback,
|
||||||
|
@ -790,6 +792,8 @@ open class SoraStream : TmdbProvider() {
|
||||||
val lastSeason: Int? = null,
|
val lastSeason: Int? = null,
|
||||||
val epsTitle: String? = null,
|
val epsTitle: String? = null,
|
||||||
val jpTitle: String? = null,
|
val jpTitle: String? = null,
|
||||||
|
val date: String? = null,
|
||||||
|
val airedDate: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class Data(
|
data class Data(
|
||||||
|
|
|
@ -107,11 +107,10 @@ class SoraStreamLite : SoraStream() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
if (res.isAnime) invokeAnimes(
|
if (res.isAnime) invokeAnimes(
|
||||||
res.id,
|
|
||||||
res.title,
|
res.title,
|
||||||
res.jpTitle,
|
|
||||||
res.epsTitle,
|
res.epsTitle,
|
||||||
res.airedYear ?: res.year,
|
res.date,
|
||||||
|
res.airedDate,
|
||||||
res.season,
|
res.season,
|
||||||
res.episode,
|
res.episode,
|
||||||
subtitleCallback,
|
subtitleCallback,
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.hexated
|
||||||
|
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
import com.hexated.SoraStream.Companion.anilistAPI
|
||||||
import com.hexated.SoraStream.Companion.base64DecodeAPI
|
import com.hexated.SoraStream.Companion.base64DecodeAPI
|
||||||
import com.hexated.SoraStream.Companion.baymoviesAPI
|
import com.hexated.SoraStream.Companion.baymoviesAPI
|
||||||
import com.hexated.SoraStream.Companion.crunchyrollAPI
|
import com.hexated.SoraStream.Companion.crunchyrollAPI
|
||||||
|
@ -10,7 +11,6 @@ import com.hexated.SoraStream.Companion.gdbot
|
||||||
import com.hexated.SoraStream.Companion.putlockerAPI
|
import com.hexated.SoraStream.Companion.putlockerAPI
|
||||||
import com.hexated.SoraStream.Companion.smashyStreamAPI
|
import com.hexated.SoraStream.Companion.smashyStreamAPI
|
||||||
import com.hexated.SoraStream.Companion.tvMoviesAPI
|
import com.hexated.SoraStream.Companion.tvMoviesAPI
|
||||||
import com.hexated.SoraStream.Companion.twoEmbedAPI
|
|
||||||
import com.hexated.SoraStream.Companion.watchOnlineAPI
|
import com.hexated.SoraStream.Companion.watchOnlineAPI
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
|
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
|
||||||
|
@ -40,7 +40,8 @@ import javax.crypto.spec.SecretKeySpec
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
val soraAPI = base64DecodeAPI("cA==YXA=cy8=Y20=di8=LnQ=b2s=a2w=bG8=aS4=YXA=ZS0=aWw=b2I=LW0=Z2E=Ly8=czo=dHA=aHQ=")
|
val soraAPI =
|
||||||
|
base64DecodeAPI("cA==YXA=cy8=Y20=di8=LnQ=b2s=a2w=bG8=aS4=YXA=ZS0=aWw=b2I=LW0=Z2E=Ly8=czo=dHA=aHQ=")
|
||||||
val bflixChipperKey = base64DecodeAPI("Yjc=ejM=TzA=YTk=WHE=WnU=bXU=RFo=")
|
val bflixChipperKey = base64DecodeAPI("Yjc=ejM=TzA=YTk=WHE=WnU=bXU=RFo=")
|
||||||
val bflixKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
val bflixKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||||
const val kaguyaBaseUrl = "https://kaguya.app/"
|
const val kaguyaBaseUrl = "https://kaguya.app/"
|
||||||
|
@ -535,7 +536,8 @@ suspend fun invokeSmashyRip(
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit,
|
callback: (ExtractorLink) -> Unit,
|
||||||
) {
|
) {
|
||||||
val script = app.get(url).document.selectFirst("script:containsData(player =)")?.data() ?: return
|
val script =
|
||||||
|
app.get(url).document.selectFirst("script:containsData(player =)")?.data() ?: return
|
||||||
|
|
||||||
val source = Regex("file:\\s*\"([^\"]+)").find(script)?.groupValues?.get(1)
|
val source = Regex("file:\\s*\"([^\"]+)").find(script)?.groupValues?.get(1)
|
||||||
val subtitle = Regex("subtitle:\\s*\"([^\"]+)").find(script)?.groupValues?.get(1)
|
val subtitle = Regex("subtitle:\\s*\"([^\"]+)").find(script)?.groupValues?.get(1)
|
||||||
|
@ -957,10 +959,11 @@ suspend fun getCrunchyrollId(aniId: String?): String? {
|
||||||
"variables" to variables
|
"variables" to variables
|
||||||
).toJson().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull())
|
).toJson().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull())
|
||||||
|
|
||||||
val externalLinks = app.post("https://graphql.anilist.co", requestBody = data)
|
val externalLinks = app.post(anilistAPI, requestBody = data)
|
||||||
.parsedSafe<AnilistResponses>()?.data?.Media?.externalLinks
|
.parsedSafe<AnilistResponses>()?.data?.Media?.externalLinks
|
||||||
|
|
||||||
return (externalLinks?.find { it.site == "VRV" } ?: externalLinks?.find { it.site == "Crunchyroll" })?.url?.let {
|
return (externalLinks?.find { it.site == "VRV" }
|
||||||
|
?: externalLinks?.find { it.site == "Crunchyroll" })?.url?.let {
|
||||||
Regex("series/(\\w+)/?").find(it)?.groupValues?.get(1)
|
Regex("series/(\\w+)/?").find(it)?.groupValues?.get(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1011,6 +1014,89 @@ suspend fun PutlockerResponses?.callback(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun convertTmdbToAnimeId(
|
||||||
|
title: String?,
|
||||||
|
date: String?,
|
||||||
|
airedDate: String?,
|
||||||
|
type: TvType
|
||||||
|
): AniIds {
|
||||||
|
val sDate = date?.split("-")
|
||||||
|
val sAiredDate = airedDate?.split("-")
|
||||||
|
|
||||||
|
val year = sDate?.firstOrNull()?.toIntOrNull()
|
||||||
|
val airedYear = sAiredDate?.firstOrNull()?.toIntOrNull()
|
||||||
|
val season = getSeason(sDate?.get(1)?.toIntOrNull())
|
||||||
|
val airedSeason = getSeason(sAiredDate?.get(1)?.toIntOrNull())
|
||||||
|
|
||||||
|
return if (type == TvType.AnimeMovie) {
|
||||||
|
tmdbToAnimeId(title, airedYear, "", type)
|
||||||
|
} else {
|
||||||
|
val ids = tmdbToAnimeId(title, year, season, type)
|
||||||
|
if (ids.id == null && ids.idMal == null) tmdbToAnimeId(
|
||||||
|
title,
|
||||||
|
airedYear,
|
||||||
|
airedSeason,
|
||||||
|
type
|
||||||
|
) else ids
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun tmdbToAnimeId(title: String?, year: Int?, season: String?, type: TvType): AniIds {
|
||||||
|
val query = """
|
||||||
|
query (
|
||||||
|
${'$'}page: Int = 1
|
||||||
|
${'$'}search: String
|
||||||
|
${'$'}sort: [MediaSort] = [POPULARITY_DESC, SCORE_DESC]
|
||||||
|
${'$'}type: MediaType
|
||||||
|
${'$'}season: MediaSeason
|
||||||
|
${'$'}seasonYear: Int
|
||||||
|
${'$'}format: [MediaFormat]
|
||||||
|
) {
|
||||||
|
Page(page: ${'$'}page, perPage: 20) {
|
||||||
|
media(
|
||||||
|
search: ${'$'}search
|
||||||
|
sort: ${'$'}sort
|
||||||
|
type: ${'$'}type
|
||||||
|
season: ${'$'}season
|
||||||
|
seasonYear: ${'$'}seasonYear
|
||||||
|
format_in: ${'$'}format
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
idMal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent().trim()
|
||||||
|
|
||||||
|
val variables = mapOf(
|
||||||
|
"search" to title,
|
||||||
|
"sort" to "SEARCH_MATCH",
|
||||||
|
"type" to "ANIME",
|
||||||
|
"season" to season?.uppercase(),
|
||||||
|
"seasonYear" to year,
|
||||||
|
"format" to listOf(if (type == TvType.AnimeMovie) "MOVIE" else "TV")
|
||||||
|
).filterValues { value -> value != null && value.toString().isNotEmpty() }
|
||||||
|
|
||||||
|
val data = mapOf(
|
||||||
|
"query" to query,
|
||||||
|
"variables" to variables
|
||||||
|
).toJson().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull())
|
||||||
|
|
||||||
|
val res = app.post(anilistAPI, requestBody = data)
|
||||||
|
.parsedSafe<AniSearch>()?.data?.Page?.media?.firstOrNull()
|
||||||
|
return AniIds(res?.id, res?.idMal)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSeason(month: Int?): String? {
|
||||||
|
val seasons = arrayOf(
|
||||||
|
"Winter", "Winter", "Spring", "Spring", "Spring", "Summer",
|
||||||
|
"Summer", "Summer", "Fall", "Fall", "Fall", "Winter"
|
||||||
|
)
|
||||||
|
if(month == null) return null
|
||||||
|
return seasons[month - 1]
|
||||||
|
}
|
||||||
|
|
||||||
fun getPutlockerQuality(quality: String): Int {
|
fun getPutlockerQuality(quality: String): Int {
|
||||||
return when {
|
return when {
|
||||||
quality.contains("NAME=\"1080p\"") || quality.contains("RESOLUTION=1920x1080") -> Qualities.P1080.value
|
quality.contains("NAME=\"1080p\"") || quality.contains("RESOLUTION=1920x1080") -> Qualities.P1080.value
|
||||||
|
|
Loading…
Reference in a new issue