Merge pull request #2 from hexated/master

createpull
This commit is contained in:
irfannajmudinsidik 2023-12-24 17:23:30 +07:00 committed by GitHub
commit 85c93e5f2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 129 additions and 75 deletions

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 = 208 version = 209
android { android {
defaultConfig { defaultConfig {

View File

@ -10,6 +10,7 @@ import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.base64Decode import com.lagradost.cloudstream3.base64Decode
import com.lagradost.cloudstream3.extractors.Jeniusplay
import com.lagradost.cloudstream3.extractors.Pixeldrain import com.lagradost.cloudstream3.extractors.Pixeldrain
import com.lagradost.cloudstream3.extractors.Vidplay import com.lagradost.cloudstream3.extractors.Vidplay
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
@ -409,4 +410,9 @@ class Vidplay2 : Vidplay() {
class Flaswish : Filesim() { class Flaswish : Filesim() {
override val name = "Flaswish" override val name = "Flaswish"
override var mainUrl = "https://flaswish.com" override var mainUrl = "https://flaswish.com"
}
class Comedyshow : Jeniusplay() {
override val mainUrl = "https://comedyshow.to"
override val name = "Comedyshow"
} }

View File

@ -14,7 +14,6 @@ import com.lagradost.nicehttp.RequestBodyTypes
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.internal.closeQuietly
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.select.Elements import org.jsoup.select.Elements
@ -252,9 +251,9 @@ object SoraExtractor : SoraStream() {
val req = app.get(url) val req = app.get(url)
val directUrl = getBaseUrl(req.url) val directUrl = getBaseUrl(req.url)
val iframe = req.document.selectFirst("div.pframe iframe")?.attr("src") ?: return val iframe = req.document.selectFirst("div.pframe iframe")?.attr("src") ?: return
if(!iframe.contains("youtube")) { if (!iframe.contains("youtube")) {
loadExtractor(iframe, "$directUrl/", subtitleCallback) { link -> loadExtractor(iframe, "$directUrl/", subtitleCallback) { link ->
if(link.quality == Qualities.Unknown.value) { if (link.quality == Qualities.Unknown.value) {
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
link.source, link.source,
@ -323,6 +322,52 @@ object SoraExtractor : SoraStream() {
} }
suspend fun invokeWatchCartoon(
title: String? = null,
year: Int? = null,
season: Int? = null,
episode: Int? = null,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val fixTitle = title.createSlug()
val url = if (season == null) {
"$watchCartoonAPI/movies/$fixTitle-$year"
} else {
"$watchCartoonAPI/episode/$fixTitle-season-$season-episode-$episode"
}
val req = app.get(url)
val host = getBaseUrl(req.url)
val doc = req.document
val id = doc.select("link[rel=shortlink]").attr("href").substringAfterLast("=")
doc.select("div.form-group.list-server option").apmap {
val server = app.get(
"$host/ajax-get-link-stream/?server=${it.attr("value")}&filmId=$id",
headers = mapOf(
"X-Requested-With" to "XMLHttpRequest"
)
).text
loadExtractor(server, "$host/", subtitleCallback) { link ->
if (link.quality == Qualities.Unknown.value) {
callback.invoke(
ExtractorLink(
"WatchCartoon",
"WatchCartoon",
link.url,
link.referer,
Qualities.P720.value,
link.type,
link.headers,
link.extractorData
)
)
}
}
}
}
suspend fun invokeNetmovies( suspend fun invokeNetmovies(
title: String? = null, title: String? = null,
year: Int? = null, year: Int? = null,
@ -1319,7 +1364,7 @@ object SoraExtractor : SoraStream() {
} }
type.contains("oiya") || type.contains("rarbgx") -> { type.contains("oiya") || type.contains("rarbgx") -> {
val oiyaLink = extractOiya(fdLink ?: return@apmap null, qualities) val oiyaLink = extractOiya(fdLink ?: return@apmap null)
if (oiyaLink?.contains("gdtot") == true) { if (oiyaLink?.contains("gdtot") == true) {
val gdBotLink = extractGdbot(oiyaLink) val gdBotLink = extractGdbot(oiyaLink)
extractGdflix(gdBotLink ?: return@apmap null) extractGdflix(gdBotLink ?: return@apmap null)
@ -1702,6 +1747,7 @@ object SoraExtractor : SoraStream() {
imdbId: String? = null, imdbId: String? = null,
season: Int? = null, season: Int? = null,
episode: Int? = null, episode: Int? = null,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit, callback: (ExtractorLink) -> Unit,
) { ) {
val url = if (season == null) { val url = if (season == null) {
@ -1717,7 +1763,7 @@ object SoraExtractor : SoraStream() {
}.apmap { }.apmap {
when (it.second) { when (it.second) {
"Player F" -> { "Player F" -> {
invokeSmashyFfix(it.second, it.first, url, callback) invokeSmashyFfix(it.second, it.first, url, subtitleCallback, callback)
} }
"Player D (Hindi)" -> { "Player D (Hindi)" -> {
@ -2211,7 +2257,8 @@ object SoraExtractor : SoraStream() {
"$cinemaTvAPI/shows/play/$id-$slug-$year" "$cinemaTvAPI/shows/play/$id-$slug-$year"
} }
val session = "PHPSESSID=ngr4cudjrimdnhkth30ssohs0n; _csrf=a6ffd7bb7654083fce6df528225a238d0e85aa1fb885dc7638c1259ec1ba0d5ca%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22mTTLiDLjxohs-CpKk0bjRH3HdYMB9uBV%22%3B%7D; _ga=GA1.1.1195498587.1701871187; _ga_VZD7HJ3WK6=GS1.1.$unixTime.4.0.1.$unixTime.0.0.0" val session =
"PHPSESSID=ngr4cudjrimdnhkth30ssohs0n; _csrf=a6ffd7bb7654083fce6df528225a238d0e85aa1fb885dc7638c1259ec1ba0d5ca%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22mTTLiDLjxohs-CpKk0bjRH3HdYMB9uBV%22%3B%7D; _ga=GA1.1.1195498587.1701871187; _ga_VZD7HJ3WK6=GS1.1.$unixTime.4.0.1.$unixTime.0.0.0"
val headers = mapOf( val headers = mapOf(
"Cookie" to session, "Cookie" to session,
@ -2288,16 +2335,16 @@ object SoraExtractor : SoraStream() {
) )
} }
val media = mediaRes.find { val filter = mediaRes.filter {
it.title.equals( it.title.equals(title, true) && it.type == if (season == null) "Movie" else "TV"
title, }
true
) && it.infor.equals(if (season == null) "$year" else "SS $lastSeason") && it.type == if (season == null) "Movie" else "TV" val media = if (season == null) {
} ?: mediaRes.find { filter.find { it.infor == "$year" }
it.title.equals( } else {
title, filter.find { it.infor == "SS $lastSeason" }
true ?: filter.find { it.infor == "SS ${lastSeason?.minus(1)}" }
) && it.infor.contains(if (season == null) "$year" else "SS") && it.type == if (season == null) "Movie" else "TV" ?: filter.find { it.infor == "SS 1" }
} }
val shareId = media?.url?.substringAfterLast("/") ?: return val shareId = media?.url?.substringAfterLast("/") ?: return
@ -2307,14 +2354,21 @@ object SoraExtractor : SoraStream() {
.parsedSafe<FebboxResponse>()?.data?.link?.substringAfterLast("/") .parsedSafe<FebboxResponse>()?.data?.link?.substringAfterLast("/")
val headers = mapOf("Accept-Language" to "en") val headers = mapOf("Accept-Language" to "en")
val shareRes = app.get("$febboxAPI/file/file_share_list?share_key=${shareKey ?: return}", headers = headers) val shareRes = app.get(
"$febboxAPI/file/file_share_list?share_key=${shareKey ?: return}",
headers = headers
)
.parsedSafe<FebboxResponse>()?.data .parsedSafe<FebboxResponse>()?.data
val fids = if (season == null) { val fids = if (season == null) {
shareRes?.file_list shareRes?.file_list
} else { } else {
val parentId = shareRes?.file_list?.find { it.file_name.equals("season $season", true) }?.fid val parentId =
app.get("$febboxAPI/file/file_share_list?share_key=${shareKey}&parent_id=$parentId&page=1", headers = headers) shareRes?.file_list?.find { it.file_name.equals("season $season", true) }?.fid
app.get(
"$febboxAPI/file/file_share_list?share_key=${shareKey}&parent_id=$parentId&page=1",
headers = headers
)
.parsedSafe<FebboxResponse>()?.data?.file_list?.filter { .parsedSafe<FebboxResponse>()?.data?.file_list?.filter {
it.file_name?.contains( it.file_name?.contains(
"s${seasonSlug}e${episodeSlug}", "s${seasonSlug}e${episodeSlug}",

View File

@ -46,6 +46,7 @@ import com.hexated.SoraExtractor.invokeVidsrcto
import com.hexated.SoraExtractor.invokeCinemaTv import com.hexated.SoraExtractor.invokeCinemaTv
import com.hexated.SoraExtractor.invokeFebbox import com.hexated.SoraExtractor.invokeFebbox
import com.hexated.SoraExtractor.invokeOmovies import com.hexated.SoraExtractor.invokeOmovies
import com.hexated.SoraExtractor.invokeWatchCartoon
import com.hexated.SoraExtractor.invokeWatchsomuch import com.hexated.SoraExtractor.invokeWatchsomuch
import com.hexated.SoraExtractor.invokeZshow import com.hexated.SoraExtractor.invokeZshow
import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId
@ -115,8 +116,9 @@ open class SoraStream : TmdbProvider() {
const val showflixAPI = "https://showflix.space" const val showflixAPI = "https://showflix.space"
const val aoneroomAPI = "https://api3.aoneroom.com" const val aoneroomAPI = "https://api3.aoneroom.com"
const val febboxAPI = "https://www.febbox.com" const val febboxAPI = "https://www.febbox.com"
const val watchCartoonAPI = "https://www1.watchcartoononline.bz"
const val fdMoviesAPI = "https://freedrivemovie.lol" const val fdMoviesAPI = "https://freedrivemovie.com"
const val uhdmoviesAPI = "https://uhdmovies.zip" const val uhdmoviesAPI = "https://uhdmovies.zip"
const val gMoviesAPI = "https://gdrivemovies.xyz" const val gMoviesAPI = "https://gdrivemovies.xyz"
const val hdmovies4uAPI = "https://hdmovies4u.band" const val hdmovies4uAPI = "https://hdmovies4u.band"
@ -450,6 +452,16 @@ open class SoraStream : TmdbProvider() {
callback callback
) )
}, },
{
if (!res.isAnime && res.isCartoon) invokeWatchCartoon(
res.title,
res.year,
res.season,
res.episode,
subtitleCallback,
callback
)
},
{ {
if (!res.isAnime) invokeVidsrcto( if (!res.isAnime) invokeVidsrcto(
res.imdbId, res.imdbId,
@ -568,6 +580,7 @@ open class SoraStream : TmdbProvider() {
res.imdbId, res.imdbId,
res.season, res.season,
res.episode, res.episode,
subtitleCallback,
callback callback
) )
}, },

View File

@ -32,6 +32,7 @@ import com.hexated.SoraExtractor.invokeVidsrcto
import com.hexated.SoraExtractor.invokeCinemaTv import com.hexated.SoraExtractor.invokeCinemaTv
import com.hexated.SoraExtractor.invokeFebbox import com.hexated.SoraExtractor.invokeFebbox
import com.hexated.SoraExtractor.invokeOmovies import com.hexated.SoraExtractor.invokeOmovies
import com.hexated.SoraExtractor.invokeWatchCartoon
import com.hexated.SoraExtractor.invokeWatchsomuch import com.hexated.SoraExtractor.invokeWatchsomuch
import com.hexated.SoraExtractor.invokeZshow import com.hexated.SoraExtractor.invokeZshow
import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.SubtitleFile
@ -106,6 +107,16 @@ class SoraStreamLite : SoraStream() {
{ {
invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback)
}, },
{
if (!res.isAnime && res.isCartoon) invokeWatchCartoon(
res.title,
res.year,
res.season,
res.episode,
subtitleCallback,
callback
)
},
{ {
if (res.isAnime) invokeAnimes( if (res.isAnime) invokeAnimes(
res.title, res.title,
@ -159,6 +170,7 @@ class SoraStreamLite : SoraStream() {
res.imdbId, res.imdbId,
res.season, res.season,
res.episode, res.episode,
subtitleCallback,
callback callback
) )
}, },

View File

@ -30,5 +30,6 @@ class SoraStreamPlugin: Plugin() {
registerExtractorAPI(Netembed()) registerExtractorAPI(Netembed())
registerExtractorAPI(Vidplay2()) registerExtractorAPI(Vidplay2())
registerExtractorAPI(Flaswish()) registerExtractorAPI(Flaswish())
registerExtractorAPI(Comedyshow())
} }
} }

View File

@ -49,7 +49,6 @@ import kotlin.math.min
var watchflxCookies: Map<String, String>? = null var watchflxCookies: Map<String, String>? = null
var filmxyCookies: Map<String, String>? = null var filmxyCookies: Map<String, String>? = null
var sfServer: String? = null var sfServer: String? = null
var cinemaCookiesChecker: Boolean? = null
val encodedIndex = arrayOf( val encodedIndex = arrayOf(
"GamMovies", "GamMovies",
@ -331,10 +330,8 @@ suspend fun getDrivebotLink(url: String?): String? {
?.data()?.substringAfter("window.open('")?.substringBefore("')") ?.data()?.substringAfter("window.open('")?.substringBefore("')")
} }
suspend fun extractOiya(url: String, quality: String): String? { suspend fun extractOiya(url: String): String? {
val doc = app.get(url).document return app.get(url).document.selectFirst("div.wp-block-button a")?.attr("href")
return doc.selectFirst("div.wp-block-button a:matches((?i)$quality)")?.attr("href")
?: doc.selectFirst("div.wp-block-button a")?.attr("href")
} }
fun deobfstr(hash: String, index: String): String { fun deobfstr(hash: String, index: String): String {
@ -405,6 +402,7 @@ suspend fun invokeSmashyFfix(
name: String, name: String,
url: String, url: String,
ref: String, ref: String,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit, callback: (ExtractorLink) -> Unit,
) { ) {
val json = app.get(url, referer = ref, headers = mapOf("X-Requested-With" to "XMLHttpRequest")) val json = app.get(url, referer = ref, headers = mapOf("X-Requested-With" to "XMLHttpRequest"))
@ -417,6 +415,17 @@ suspend fun invokeSmashyFfix(
).forEach(callback) ).forEach(callback)
} }
json?.subtitleUrls?.split(",")?.map { sub ->
val lang = "\\[(.*)]".toRegex().find(sub)?.groupValues?.get(1)
val subUrl = sub.replace("[$lang]", "").trim()
subtitleCallback.invoke(
SubtitleFile(
lang ?: return@map,
subUrl
)
)
}
} }
suspend fun invokeSmashyD( suspend fun invokeSmashyD(
@ -589,10 +598,11 @@ suspend fun bypassFdAds(url: String?): String? {
} }
suspend fun bypassHrefli(url: String): String? { suspend fun bypassHrefli(url: String): String? {
fun Document.getFormUrl() : String { fun Document.getFormUrl(): String {
return this.select("form#landing").attr("action") return this.select("form#landing").attr("action")
} }
fun Document.getFormData() : Map<String,String> {
fun Document.getFormData(): Map<String, String> {
return this.select("form#landing input").associate { it.attr("name") to it.attr("value") } return this.select("form#landing input").associate { it.attr("name") to it.attr("value") }
} }
@ -606,7 +616,8 @@ suspend fun bypassHrefli(url: String): String? {
formData = res.getFormData() formData = res.getFormData()
res = app.post(formUrl, data = formData).document res = app.post(formUrl, data = formData).document
val skToken = res.selectFirst("script:containsData(?go=)")?.data()?.substringAfter("?go=")?.substringBefore("\"") ?: return null val skToken = res.selectFirst("script:containsData(?go=)")?.data()?.substringAfter("?go=")
?.substringBefore("\"") ?: return null
val driveUrl = app.get( val driveUrl = app.get(
"$host?go=$skToken", cookies = mapOf( "$host?go=$skToken", cookies = mapOf(
skToken to "${formData["_wp_http2"]}" skToken to "${formData["_wp_http2"]}"
@ -648,49 +659,6 @@ suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair<St
} }
} }
suspend fun refreshCinemaCookies(session: String) = cinemaCookiesChecker ?: fetchCinemaCookiesChecker(session).also { cinemaCookiesChecker = it }
suspend fun fetchCinemaCookiesChecker(session: String): Boolean {
val wiwiApi = base64Decode("aHR0cHM6Ly9jaW5lbWEud2l3aWNlbnRlci5jb20=")
suspend fun createConfig(headers: Map<String, String>) {
app.get(
"$wiwiApi/api/v1/app-config",
headers = headers
).text
}
suspend fun checkCookies(session: String, headers: Map<String, String>) {
app.post(
"$wiwiApi/api/v1/cookie",
data = mapOf("cookie" to session),
headers = headers
).text
}
val configHeaders = mapOf(
"App-version" to "3.4",
"Authorization" to "Basic d2l3aTpXaXdpQDIwMjA=",
"Country" to "Indonesia",
"Device-id" to getDeviceId(),
"User-id" to "user-6694327",
)
listOf(1..2).apmap { createConfig(configHeaders) }
val unityData = """
{
"platform": "android",
"idfi": "d1ec7051-f58f-4ddb-9da8-8debb82cfbea",
"sdkVersionName": "4.3.0",
"gdpr.consent": true,
"user.nonbehavioral": false,
"unity.privacy.permissions.all": false,
"unity.privacy.permissions.gameExp": false,
"unity.privacy.permissions.ads": false,
"unity.privacy.permissions.external": false
}
""".trimIndent().toJson().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull())
app.post("https://configv2.unityads.unity3d.com/privacy/4519473/state", requestBody = unityData).text
listOf(1..4).map {checkCookies(session, configHeaders)}
return true
}
suspend fun getSfServer() = sfServer ?: fetchSfServer().also { sfServer = it } suspend fun getSfServer() = sfServer ?: fetchSfServer().also { sfServer = it }
suspend fun fetchSfServer(): String { suspend fun fetchSfServer(): String {

View File

@ -13,7 +13,7 @@ import org.jsoup.nodes.Element
import java.net.URI import java.net.URI
class YugenAnime : MainAPI() { class YugenAnime : MainAPI() {
override var mainUrl = "https://yugenanime.tv" override var mainUrl = "https://yugenanime.sx"
override var name = "YugenAnime" override var name = "YugenAnime"
override val hasMainPage = true override val hasMainPage = true
override var lang = "en" override var lang = "en"
@ -84,7 +84,7 @@ class YugenAnime : MainAPI() {
} }
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val document = app.get("$mainUrl/search/?q=$query").document val document = app.get("$mainUrl/discover/?q=$query").document
return document.select("div.cards-grid a.anime-meta").mapNotNull { return document.select("div.cards-grid a.anime-meta").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
@ -231,4 +231,4 @@ class YugenAnime : MainAPI() {
@JsonProperty("season") val season: String? = null, @JsonProperty("season") val season: String? = null,
) )
} }