This commit is contained in:
hexated 2023-09-21 14:43:38 +07:00
parent 7ebdfeb3e0
commit cdf15ff08a
11 changed files with 98 additions and 29 deletions

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

@ -9,7 +9,7 @@ import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
class Animasu : MainAPI() { class Animasu : MainAPI() {
override var mainUrl = "https://animasu.uno" override var mainUrl = "https://animasu.info"
override var name = "Animasu" override var name = "Animasu"
override val hasMainPage = true override val hasMainPage = true
override var lang = "id" override var lang = "id"

View file

@ -1,7 +1,7 @@
import org.jetbrains.kotlin.konan.properties.Properties import org.jetbrains.kotlin.konan.properties.Properties
// use an integer for version numbers // use an integer for version numbers
version = 172 version = 173
android { android {
defaultConfig { defaultConfig {

View file

@ -208,8 +208,7 @@ open class VCloud : ExtractorApi() {
) )
).document.select("p.text-success ~ a").apmap { ).document.select("p.text-success ~ a").apmap {
val link = it.attr("href") val link = it.attr("href")
val uri = URI(link) if (link.contains("workers.dev")) {
if (uri.path.contains("workers.dev")) {
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
this.name, this.name,

View file

@ -1,6 +1,7 @@
package com.hexated package com.hexated
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.unixTime
import com.lagradost.cloudstream3.APIHolder.unixTimeMS import com.lagradost.cloudstream3.APIHolder.unixTimeMS
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
@ -1022,7 +1023,16 @@ object SoraExtractor : SoraStream() {
} }
suspend fun invokeDotmovies(
title: String? = null,
year: Int? = null,
season: Int? = null,
episode: Int? = null,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
invokeWpredis(title, year, season, episode, subtitleCallback, callback, dotmoviesAPI)
}
suspend fun invokeVegamovies( suspend fun invokeVegamovies(
title: String? = null, title: String? = null,
year: Int? = null, year: Int? = null,
@ -1031,7 +1041,18 @@ object SoraExtractor : SoraStream() {
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
) { ) {
var res = app.get("$vegaMoviesAPI/search/$title").document invokeWpredis(title, year, season, episode, subtitleCallback, callback, vegaMoviesAPI)
}
private suspend fun invokeWpredis(
title: String? = null,
year: Int? = null,
season: Int? = null,
episode: Int? = null,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit,
api: String
) {
var res = app.get("$api/search/$title").document
val match = if (season == null) "$year" else "Season $season" val match = if (season == null) "$year" else "Season $season"
val media = val media =
res.selectFirst("div.blog-items article:has(h3.entry-title:matches((?i)$title.*$match)) a") res.selectFirst("div.blog-items article:has(h3.entry-title:matches((?i)$title.*$match)) a")
@ -1048,7 +1069,7 @@ object SoraExtractor : SoraStream() {
app.post( app.post(
"${getBaseUrl(url)}/red.php", "${getBaseUrl(url)}/red.php",
data = mapOf("link" to url), data = mapOf("link" to url),
referer = "$vegaMoviesAPI/" referer = "$api/"
).text.substringAfter("location.href = \"").substringBefore("\"") ).text.substringAfter("location.href = \"").substringBefore("\"")
} }
val selector = val selector =
@ -1059,7 +1080,7 @@ object SoraExtractor : SoraStream() {
loadCustomTagExtractor( loadCustomTagExtractor(
tags, tags,
server ?: return@apmap, server ?: return@apmap,
"$vegaMoviesAPI/", "$api/",
subtitleCallback, subtitleCallback,
callback, callback,
getIndexQuality(it.text()) getIndexQuality(it.text())
@ -2401,7 +2422,7 @@ object SoraExtractor : SoraStream() {
})?.substringAfter("id=")?.substringBefore("&") })?.substringAfter("id=")?.substringBefore("&")
val server = app.get( val server = app.get(
"$emoviesAPI/ajax/v4_get_sources?s=oserver&id=${id ?: return}&_=${APIHolder.unixTimeMS}", "$emoviesAPI/ajax/v4_get_sources?s=oserver&id=${id ?: return}&_=${unixTimeMS}",
headers = mapOf( headers = mapOf(
"X-Requested-With" to "XMLHttpRequest" "X-Requested-With" to "XMLHttpRequest"
) )
@ -2513,7 +2534,7 @@ object SoraExtractor : SoraStream() {
ExtractorLink( ExtractorLink(
"Jump1", "Jump1",
"Jump1", "Jump1",
"$jump1API/hls/${source ?: return}/master.m3u8?ts=${APIHolder.unixTimeMS}", "$jump1API/hls/${source ?: return}/master.m3u8?ts=${unixTimeMS}",
referer, referer,
Qualities.P1080.value, Qualities.P1080.value,
true true
@ -2523,30 +2544,36 @@ object SoraExtractor : SoraStream() {
suspend fun invokeNetflix( suspend fun invokeNetflix(
imdbId: String? = null, imdbId: String? = null,
title: String? = null,
season: Int? = null, season: Int? = null,
episode: Int? = null, episode: Int? = null,
callback: (ExtractorLink) -> Unit, callback: (ExtractorLink) -> Unit,
) { ) {
val headers = mapOf("X-Requested-With" to "XMLHttpRequest", "Cookie" to "hd=on") val headers = mapOf("X-Requested-With" to "XMLHttpRequest", "Cookie" to "hd=on")
val netflixId = imdbToNetflixId(imdbId, season) val netflixId = imdbToNetflixId(imdbId, season) ?: run {
val (title, id) = app.get( app.get("$netflixAPI/search.php?s=$title&t=${unixTime}", headers = headers)
"$netflixAPI/post.php?id=${netflixId ?: return}&t=${APIHolder.unixTime}", .parsedSafe<NetflixSearch>()?.searchResult?.find { it.t.equals(title) }?.id
}
val (t, id) = app.get(
"$netflixAPI/post.php?id=${netflixId ?: return}&t=${unixTime}",
headers = headers headers = headers
).parsedSafe<NetflixResponse>().let { media -> ).parsedSafe<NetflixResponse>().let { media ->
if (season == null) { if (season == null) {
media?.title to netflixId media?.title to netflixId
} else { } else {
val seasonId = media?.season?.find { it.s == "$season" }?.id val seasonId = media?.season?.find { it.s == "$season" }?.id
val episodeId = app.get( val episodeId =
"$netflixAPI/episodes.php?s=${seasonId}&series=$netflixId&t=${APIHolder.unixTime}", app.get(
"$netflixAPI/episodes.php?s=${seasonId}&series=$netflixId&t=${unixTime}",
headers = headers headers = headers
).parsedSafe<NetflixResponse>()?.episodes?.find { it.ep == "E$episode" }?.id )
.parsedSafe<NetflixResponse>()?.episodes?.find { it.ep == "E$episode" }?.id
media?.title to episodeId media?.title to episodeId
} }
} }
app.get( app.get(
"$netflixAPI/playlist.php?id=${id ?: return}&t=${title ?: return}&tm=${APIHolder.unixTime}", "$netflixAPI/playlist.php?id=${id ?: return}&t=${t ?: return}&tm=${unixTime}",
headers = headers headers = headers
).text.let { ).text.let {
tryParseJson<ArrayList<NetflixResponse>>(it) tryParseJson<ArrayList<NetflixResponse>>(it)

View file

@ -419,3 +419,12 @@ data class NetflixResponse(
@JsonProperty("episodes") val episodes: ArrayList<NetflixEpisodes>? = arrayListOf(), @JsonProperty("episodes") val episodes: ArrayList<NetflixEpisodes>? = arrayListOf(),
@JsonProperty("sources") val sources: ArrayList<NetflixSources>? = arrayListOf(), @JsonProperty("sources") val sources: ArrayList<NetflixSources>? = arrayListOf(),
) )
data class NetflixSearchResult(
@JsonProperty("t") val t: String? = null,
@JsonProperty("id") val id: String? = null,
)
data class NetflixSearch(
@JsonProperty("searchResult") val searchResult: ArrayList<NetflixSearchResult>? = arrayListOf(),
)

View file

@ -14,6 +14,7 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.metaproviders.TmdbProvider import com.lagradost.cloudstream3.metaproviders.TmdbProvider
import com.hexated.SoraExtractor.invokeDahmerMovies import com.hexated.SoraExtractor.invokeDahmerMovies
import com.hexated.SoraExtractor.invokeDoomovies import com.hexated.SoraExtractor.invokeDoomovies
import com.hexated.SoraExtractor.invokeDotmovies
import com.hexated.SoraExtractor.invokeDramaday import com.hexated.SoraExtractor.invokeDramaday
import com.hexated.SoraExtractor.invokeDreamfilm import com.hexated.SoraExtractor.invokeDreamfilm
import com.hexated.SoraExtractor.invokeFDMovies import com.hexated.SoraExtractor.invokeFDMovies
@ -129,6 +130,7 @@ open class SoraStream : TmdbProvider() {
const val netflixAPI = "https://m.netflixmirror.com" const val netflixAPI = "https://m.netflixmirror.com"
const val hdmovies4uAPI = "https://hdmovies4u.name" const val hdmovies4uAPI = "https://hdmovies4u.name"
const val watchflxAPI = "https://watchflx.tv" const val watchflxAPI = "https://watchflx.tv"
const val dotmoviesAPI = "https://dotmovies.today"
// INDEX SITE // INDEX SITE
const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev" const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev"
@ -247,6 +249,7 @@ open class SoraStream : TmdbProvider() {
val isAnime = val isAnime =
genres?.contains("Animation") == true && (res.original_language == "zh" || res.original_language == "ja") genres?.contains("Animation") == true && (res.original_language == "zh" || res.original_language == "ja")
val isAsian = !isAnime && (res.original_language == "zh" || res.original_language == "ko") val isAsian = !isAnime && (res.original_language == "zh" || res.original_language == "ko")
val isBollywood = res.production_countries?.any { it.name == "India" } ?: false
val keywords = res.keywords?.results?.mapNotNull { it.name }.orEmpty() val keywords = res.keywords?.results?.mapNotNull { it.name }.orEmpty()
.ifEmpty { res.keywords?.keywords?.mapNotNull { it.name } } .ifEmpty { res.keywords?.keywords?.mapNotNull { it.name } }
@ -289,6 +292,7 @@ open class SoraStream : TmdbProvider() {
date = season.airDate, date = season.airDate,
airedDate = res.releaseDate ?: res.firstAirDate, airedDate = res.releaseDate ?: res.firstAirDate,
isAsian = isAsian, isAsian = isAsian,
isBollywood = isBollywood
).toJson(), ).toJson(),
name = eps.name + if (isUpcoming(eps.airDate)) " - [UPCOMING]" else "", name = eps.name + if (isUpcoming(eps.airDate)) " - [UPCOMING]" else "",
season = eps.seasonNumber, season = eps.seasonNumber,
@ -337,6 +341,7 @@ open class SoraStream : TmdbProvider() {
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, airedDate = res.releaseDate ?: res.firstAirDate,
isAsian = isAsian, isAsian = isAsian,
isBollywood = isBollywood
).toJson(), ).toJson(),
) { ) {
this.posterUrl = poster this.posterUrl = poster
@ -525,7 +530,7 @@ open class SoraStream : TmdbProvider() {
) )
}, },
{ {
if (!res.isAnime) invokeBollyMaza( if (!res.isAnime && res.isBollywood) invokeBollyMaza(
bollyMazaAPI, bollyMazaAPI,
"BollyMaza", "BollyMaza",
res.title, res.title,
@ -653,6 +658,16 @@ open class SoraStream : TmdbProvider() {
callback callback
) )
}, },
{
if (!res.isAnime && res.isBollywood) invokeDotmovies(
res.title,
res.year,
res.season,
res.episode,
subtitleCallback,
callback
)
},
{ {
if (!res.isAnime && res.season == null) invokePobmovies( if (!res.isAnime && res.season == null) invokePobmovies(
res.title, res.title,
@ -710,6 +725,7 @@ open class SoraStream : TmdbProvider() {
{ {
if (!res.isAnime) invokeNetflix( if (!res.isAnime) invokeNetflix(
res.imdbId, res.imdbId,
res.title,
res.season, res.season,
res.episode, res.episode,
callback callback
@ -763,6 +779,7 @@ open class SoraStream : TmdbProvider() {
val date: String? = null, val date: String? = null,
val airedDate: String? = null, val airedDate: String? = null,
val isAsian: Boolean = false, val isAsian: Boolean = false,
val isBollywood: Boolean = false,
) )
data class Data( data class Data(
@ -867,6 +884,10 @@ open class SoraStream : TmdbProvider() {
@JsonProperty("season_number") val season_number: Int? = null, @JsonProperty("season_number") val season_number: Int? = null,
) )
data class ProductionCountries(
@JsonProperty("name") val name: String? = null,
)
data class MediaDetail( data class MediaDetail(
@JsonProperty("id") val id: Int? = null, @JsonProperty("id") val id: Int? = null,
@JsonProperty("imdb_id") val imdbId: String? = null, @JsonProperty("imdb_id") val imdbId: String? = null,
@ -892,6 +913,7 @@ open class SoraStream : TmdbProvider() {
@JsonProperty("credits") val credits: Credits? = null, @JsonProperty("credits") val credits: Credits? = null,
@JsonProperty("recommendations") val recommendations: ResultsRecommendations? = null, @JsonProperty("recommendations") val recommendations: ResultsRecommendations? = null,
@JsonProperty("alternative_titles") val alternative_titles: ResultsAltTitles? = null, @JsonProperty("alternative_titles") val alternative_titles: ResultsAltTitles? = null,
@JsonProperty("production_countries") val production_countries: ArrayList<ProductionCountries>? = arrayListOf(),
) )
} }

View file

@ -316,6 +316,7 @@ class SoraStreamLite : SoraStream() {
{ {
if (!res.isAnime) invokeNetflix( if (!res.isAnime) invokeNetflix(
res.imdbId, res.imdbId,
res.title,
res.season, res.season,
res.episode, res.episode,
callback callback

View file

@ -17,6 +17,7 @@ import com.hexated.SoraStream.Companion.watchhubApi
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
import com.lagradost.cloudstream3.APIHolder.unixTimeMS import com.lagradost.cloudstream3.APIHolder.unixTimeMS
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
@ -1334,10 +1335,14 @@ fun getBaseUrl(url: String): String {
} }
fun isUpcoming(dateString: String?): Boolean { fun isUpcoming(dateString: String?): Boolean {
if (dateString == null) return false return try {
val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val dateTime = format.parse(dateString)?.time ?: return false val dateTime = dateString?.let { format.parse(it)?.time } ?: return false
return unixTimeMS < dateTime return unixTimeMS < dateTime
} catch (t: Throwable) {
logError(t)
false
}
} }
fun decode(input: String): String = URLDecoder.decode(input, "utf-8") fun decode(input: String): String = URLDecoder.decode(input, "utf-8")

View file

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

View file

@ -1,6 +1,7 @@
package com.hexated package com.hexated
import com.lagradost.cloudstream3.APIHolder import com.lagradost.cloudstream3.APIHolder
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.nicehttp.Requests.Companion.await import com.lagradost.nicehttp.Requests.Companion.await
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@ -58,10 +59,15 @@ fun getEpisodeSlug(
} }
fun isUpcoming(dateString: String?): Boolean { fun isUpcoming(dateString: String?): Boolean {
if (dateString == null) return false return try {
val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val dateTime = format.parse(dateString)?.time ?: return false val dateTime = dateString?.let { format.parse(it)?.time } ?: return false
return APIHolder.unixTimeMS < dateTime return APIHolder.unixTimeMS < dateTime
} catch (t: Throwable) {
logError(t)
false
}
} }
fun fixUrl(url: String, domain: String): String { fun fixUrl(url: String, domain: String): String {