sora: fix some sources & solved #299

This commit is contained in:
helo 2023-09-28 21:05:17 +07:00
parent 39de0eb2b6
commit ab50fee8a5
18 changed files with 110 additions and 152 deletions

View file

@ -93,11 +93,9 @@ open class DramaidProvider : MainAPI() {
val episodes = document.select(".eplister > ul > li").mapNotNull {
val name = it.selectFirst("a > .epl-title")?.text()
val link = fixUrl(it.selectFirst("a")?.attr("href") ?: return@mapNotNull null)
val epNum = it.selectFirst(".epl-num")?.text()?.toIntOrNull()
Episode(
link,
name,
episode = epNum
)
}.reversed()

View file

@ -3,7 +3,7 @@ package com.hexated
import com.lagradost.cloudstream3.extractors.Filesim
class Oppadrama : DramaidProvider() {
override var mainUrl = "http://185.217.95.34"
override var mainUrl = "http://185.217.95.30"
override var name = "Oppadrama"
}

View file

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

View file

@ -25,6 +25,11 @@ class FilelionsTo : Filesim() {
override var mainUrl = "https://filelions.to"
}
class FilelionsOn : Filesim() {
override val name = "Filelions"
override var mainUrl = "https://filelions.online"
}
class Lylxan : Filesim() {
override val name = "Lylxan"
override var mainUrl = "https://lylxan.com"

View file

@ -21,5 +21,6 @@ class GomovPlugin: Plugin() {
registerExtractorAPI(Embedwish())
registerExtractorAPI(Doods())
registerExtractorAPI(Lylxan())
registerExtractorAPI(FilelionsOn())
}
}

View file

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

View file

@ -44,46 +44,24 @@ class NontonAnimeIDProvider : MainAPI() {
}
}
override val mainPage = mainPageOf(
"" to "Latest Update",
"ongoing-list/" to " Ongoing List",
"popular-series/" to "Popular Series",
)
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
val document = app.get(mainUrl).document
val homePageList = ArrayList<HomePageList>()
document.select("section#postbaru").forEach { block ->
val header = block.selectFirst("h2")!!.text().trim()
val animes = block.select("article.animeseries").mapNotNull {
val document = app.get("$mainUrl/${request.data}").document
val home = document.select(".animeseries").mapNotNull {
it.toSearchResult()
}
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes))
return newHomePageResponse(request.name, home, hasNext = false)
}
document.select("aside#sidebar_right > div.side").forEach { block ->
val header = block.selectFirst("h3")!!.ownText().trim()
val animes = block.select("div.bor").mapNotNull {
it.toSearchResultPopular()
}
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes))
}
return HomePageResponse(homePageList)
}
private fun Element.toSearchResult(): AnimeSearchResponse? {
private fun Element.toSearchResult(): AnimeSearchResponse {
val href = fixUrl(this.selectFirst("a")!!.attr("href"))
val title = this.selectFirst("h3.title")?.text() ?: return null
val posterUrl = fixUrl(this.select("img").attr("src"))
return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl
addDubStatus(dubExist = false, subExist = true)
}
}
private fun Element.toSearchResultPopular(): AnimeSearchResponse? {
val href = fixUrl(this.selectFirst("a")!!.attr("href"))
val title = this.selectFirst("h4")?.text()?.trim() ?: return null
val posterUrl = fixUrl(this.select("img").attr("src"))
val title = this.selectFirst(".title")?.text() ?: ""
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("data-src"))
return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl
@ -207,7 +185,6 @@ class NontonAnimeIDProvider : MainAPI() {
): Boolean {
val document = app.get(data).document
val sources = ArrayList<String>()
document.select(".container1 > ul > li:not(.boxtab)").apmap {
val dataPost = it.attr("data-post")
@ -220,17 +197,14 @@ class NontonAnimeIDProvider : MainAPI() {
"action" to "player_ajax",
"post" to dataPost,
"nume" to dataNume,
"type" to dataType
"type" to dataType,
"nonce" to "e4dd8e45c2"
),
referer = data,
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
).document.select("iframe").attr("src")
).document.selectFirst("iframe")?.attr("src")
sources.add(fixUrl(iframe))
}
sources.apmap {
loadExtractor(it, "$mainUrl/", subtitleCallback, callback)
loadExtractor(iframe ?: return@apmap , "$mainUrl/", subtitleCallback, callback)
}
return true
@ -255,3 +229,15 @@ class KotakAnimeid2 : Hxfile() {
override val mainUrl = "https://embed2.kotakanimeid.com"
override val requiresReferer = true
}
class KotakAnimeidCom : Hxfile() {
override val name = "KotakAnimeid"
override val mainUrl = "https://nontonanimeid.com"
override val requiresReferer = true
}
class EmbedKotakAnimeid : Hxfile() {
override val name = "EmbedKotakAnimeid"
override val mainUrl = "https://embed2.kotakanimeid.com"
override val requiresReferer = true
}

View file

@ -11,5 +11,7 @@ class NontonAnimeIDProviderPlugin: Plugin() {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(NontonAnimeIDProvider())
registerExtractorAPI(KotakAnimeid2())
registerExtractorAPI(KotakAnimeidCom())
registerExtractorAPI(EmbedKotakAnimeid())
}
}

View file

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

View file

@ -282,3 +282,8 @@ class DesuBeta : JWPlayer() {
override val name = "DesuBeta"
override val mainUrl = "https://desustream.me/beta/"
}
class Desudesuhd : JWPlayer() {
override val name = "Desudesuhd"
override val mainUrl = "https://desustream.me/desudesuhd/"
}

View file

@ -12,5 +12,6 @@ class OtakudesuProviderPlugin: Plugin() {
registerMainAPI(OtakudesuProvider())
registerExtractorAPI(Moedesu())
registerExtractorAPI(DesuBeta())
registerExtractorAPI(Desudesuhd())
}
}

View file

@ -14,7 +14,7 @@ import org.jsoup.Jsoup
import org.jsoup.nodes.Element
class Samehadaku : MainAPI() {
override var mainUrl = "https://samehadaku.bond"
override var mainUrl = "https://samehadaku.help"
override var name = "Samehadaku"
override val hasMainPage = true
override var lang = "id"

View file

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

View file

@ -1653,15 +1653,12 @@ object SoraExtractor : SoraStream() {
"$rStreamAPI/e/?tmdb=$id&s=$season&e=$episode"
}
val res = app.get(url).text
val res = app.get(url, referer = "https://watcha.movie/").text
val link = Regex("\"file\":\"(http.*?)\"").find(res)?.groupValues?.getOrNull(1) ?: return
delay(1000)
if (!app.get(link, referer = rStreamAPI).isSuccessful) return
callback.invoke(
ExtractorLink(
"RStream", "RStream", link, rStreamAPI, Qualities.P720.value, link.contains(".m3u8")
"RStream", "RStream", link, rStreamAPI, Qualities.P720.value, INFER_TYPE
)
)
}
@ -2057,7 +2054,7 @@ object SoraExtractor : SoraStream() {
)
}
suspend fun invokePrimewire(
suspend fun invokeGomovies(
title: String? = null,
year: Int? = null,
season: Int? = null,
@ -2070,10 +2067,10 @@ object SoraExtractor : SoraStream() {
season,
episode,
callback,
primewireAPI,
"Primewire",
"RvnMfoxhgm",
"vvqUtffkId"
gomoviesAPI,
"Gomovies",
"_smQamBQsETb",
"_sBWcqbTBMaT"
)
}
@ -2175,7 +2172,6 @@ object SoraExtractor : SoraStream() {
suspend fun invokeWatchOnline(
imdbId: String? = null,
tmdbId: Int? = null,
title: String? = null,
year: Int? = null,
season: Int? = null,
@ -2186,34 +2182,37 @@ object SoraExtractor : SoraStream() {
val id = imdbId?.removePrefix("tt")
val slug = title.createSlug()
val url = if (season == null) {
"$watchOnlineAPI/movies/view/$id-$slug-$year"
"$watchOnlineAPI/movies/play/$id-$slug-$year"
} else {
"$watchOnlineAPI/shows/view/$id-$slug-$year"
"$watchOnlineAPI/shows/play/$id-$slug-$year"
}
var res = app.get(url)
if (res.code == 403) return
if (!res.isSuccessful) res = searchWatchOnline(title, season, imdbId, tmdbId) ?: return
if (!res.isSuccessful) res = searchWatchOnline(title, season, year) ?: return
val doc = res.document
val episodeId = if (season == null) {
doc.selectFirst("div.movie__buttons-items a")?.attr("data-watch-list-media-id")
val script = doc.selectFirst("script:containsData(hash:)")?.data()
val hash = Regex("hash:\\s*['\"](\\S+)['\"]").find(script ?: return)?.groupValues?.get(1)
val expires = Regex("expires:\\s*(\\d+)").find(script)?.groupValues?.get(1)
val episodeId = (if(season == null) {
"""id_movie:\s*(\d+)"""
} else {
doc.select("ul[data-season-episodes=$season] li").find {
it.select("div.episodes__number").text().equals("Episode $episode", true)
}?.attr("data-id-episode")
} ?: return
argamap({
invokeMonster(res.url.substringAfterLast("/"), episodeId, season, callback)
}, {
"""episode:\s*['"]$episode['"],[\n\s]+id_episode:\s*(\d+),[\n\s]+season:\s*['"]$season['"]"""
}).let { it.toRegex().find(script)?.groupValues?.get(1) }
val videoUrl = if (season == null) {
"$watchOnlineAPI/api/v1/security/movie-access?id_movie=$episodeId"
"$watchOnlineAPI/api/v1/security/movie-access?id_movie=$episodeId&hash=$hash&expires=$expires"
} else {
"$watchOnlineAPI/api/v1/security/episode-access?id=$episodeId"
"$watchOnlineAPI/api/v1/security/episode-access?id_episode=$episodeId&hash=$hash&expires=$expires"
}
val json = app.get(videoUrl, referer = url).parsedSafe<WatchOnlineResponse>()
val sources = app.get(
videoUrl,
referer = url,
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
).parsedSafe<WatchOnlineResponse>()
json?.streams?.mapKeys { source ->
sources?.streams?.mapKeys { source ->
callback.invoke(
ExtractorLink(
"WatchOnline",
@ -2225,61 +2224,19 @@ object SoraExtractor : SoraStream() {
)
)
}
val subtitles = json?.subtitles as ArrayList<HashMap<String, String>>
subtitles.map { sub ->
sources?.subtitles?.map { sub ->
val file = sub.file.toString()
subtitleCallback.invoke(
SubtitleFile(
sub["language"] ?: return@map,
fixUrl(sub["url"] ?: return@map, watchOnlineAPI)
sub.language ?: return@map,
if(file.startsWith("[")) return@map else fixUrl(file, watchOnlineAPI),
)
)
}
})
}
private suspend fun invokeMonster(
urlSlug: String? = null,
episodeId: String? = null,
season: Int? = null,
callback: (ExtractorLink) -> Unit,
) {
val monsterMainUrl = "https://lookmovie.foundation"
val viewSlug = if (season == null) {
"movies/view/$urlSlug"
} else {
"shows/view/$urlSlug"
}
val streamUrl =
app.get("$monsterMainUrl/$viewSlug").document.select("a.round-button:first-child")
.attr("href")
val res = app.get(fixUrl(streamUrl, monsterMainUrl)).document
val script = res.selectFirst("script:containsData(hash:)")?.data()
val hash = Regex("hash:\\s*['\"](\\S+)['\"]").find(script ?: return)?.groupValues?.get(1)
val expires = Regex("expires:\\s*(\\d+)").find(script)?.groupValues?.get(1)
val videoUrl = if (season == null) {
"$monsterMainUrl/api/v1/security/movie-access?id_movie=$episodeId&hash=$hash&expires=$expires"
} else {
"$monsterMainUrl/api/v1/security/episode-access?id_episode=$episodeId&hash=$hash&expires=$expires"
}
app.get(
videoUrl, referer = streamUrl, headers = mapOf("X-Requested-With" to "XMLHttpRequest")
).parsedSafe<WatchOnlineResponse>()?.streams?.mapKeys { source ->
callback.invoke(
ExtractorLink(
"WatchOnline",
"WatchOnline",
source.value,
"$monsterMainUrl/",
getQualityFromName(source.key),
true
)
)
}
}
suspend fun invokeNinetv(
tmdbId: Int? = null,
season: Int? = null,

View file

@ -195,19 +195,25 @@ data class JikanResponse(
@JsonProperty("data") val data: JikanData? = null,
)
data class WatchOnlineItems(
data class WatchOnlineResults(
@JsonProperty("slug") val slug: String? = null,
@JsonProperty("tmdb_id") val tmdb_id: Int? = null,
@JsonProperty("imdb_id") val imdb_id: String? = null,
@JsonProperty("title") val title: String? = null,
@JsonProperty("year") val year: String? = null,
)
data class WatchOnlineSearch(
@JsonProperty("items") val items: ArrayList<WatchOnlineItems>? = arrayListOf(),
@JsonProperty("result") val result: ArrayList<WatchOnlineResults>? = arrayListOf(),
)
data class WatchOnlineSubtitles(
@JsonProperty("language") val language: String? = null,
@JsonProperty("file") val file: Any? = null,
)
data class WatchOnlineResponse(
@JsonProperty("streams") val streams: HashMap<String, String>? = null,
@JsonProperty("subtitles") val subtitles: Any? = null,
@JsonProperty("subtitles") val subtitles: ArrayList<WatchOnlineSubtitles>? = arrayListOf(),
)
data class CryMoviesProxyHeaders(

View file

@ -42,7 +42,7 @@ import com.hexated.SoraExtractor.invokeMultimovies
import com.hexated.SoraExtractor.invokeNetflix
import com.hexated.SoraExtractor.invokeNetmovies
import com.hexated.SoraExtractor.invokePobmovies
import com.hexated.SoraExtractor.invokePrimewire
import com.hexated.SoraExtractor.invokeGomovies
import com.hexated.SoraExtractor.invokePutactor
import com.hexated.SoraExtractor.invokeTvMovies
import com.hexated.SoraExtractor.invokeUhdmovies
@ -109,7 +109,7 @@ open class SoraStream : TmdbProvider() {
const val flixonAPI = "https://flixon.lol"
const val smashyStreamAPI = "https://embed.smashystream.com"
const val watchSomuchAPI = "https://watchsomuch.tv" // sub only
const val watchOnlineAPI = "https://watchonline.ag"
const val watchOnlineAPI = "https://lookmovie.foundation"
const val nineTvAPI = "https://moviesapi.club"
const val nowTvAPI = "https://myfilestorage.xyz"
const val gokuAPI = "https://goku.sx"
@ -121,7 +121,6 @@ open class SoraStream : TmdbProvider() {
const val netmoviesAPI = "https://netmovies.to"
const val momentAPI = "https://moment-explanation-i-244.site"
const val doomoviesAPI = "https://doomovies.net"
const val primewireAPI = "https://real-primewire.club"
const val vidsrctoAPI = "https://vidsrc.to"
const val dramadayAPI = "https://dramaday.me"
const val animetoshoAPI = "https://animetosho.org"
@ -132,6 +131,7 @@ open class SoraStream : TmdbProvider() {
const val netflixAPI = "https://m.netflixmirror.com"
const val hdmovies4uAPI = "https://hdmovies4u.name"
const val watchflxAPI = "https://watchflx.tv"
const val gomoviesAPI = "https://gomovies-online.cam"
const val dotmoviesAPI = "https://dotmovies.today"
// INDEX SITE
@ -585,7 +585,7 @@ open class SoraStream : TmdbProvider() {
)
},
{
if (!res.isAnime) invokePrimewire(res.title, res.year, res.season, res.episode, callback)
if (!res.isAnime) invokeGomovies(res.title, res.year, res.season, res.episode, callback)
},
{
if (!res.isAnime) invokePutactor(res.title, res.year, res.season, res.episode, callback)
@ -604,7 +604,6 @@ open class SoraStream : TmdbProvider() {
{
invokeWatchOnline(
res.imdbId,
res.id,
res.title,
res.airedYear ?: res.year,
res.season,

View file

@ -27,7 +27,7 @@ import com.hexated.SoraExtractor.invokeMoment
import com.hexated.SoraExtractor.invokeMultimovies
import com.hexated.SoraExtractor.invokeNetflix
import com.hexated.SoraExtractor.invokeNetmovies
import com.hexated.SoraExtractor.invokePrimewire
import com.hexated.SoraExtractor.invokeGomovies
import com.hexated.SoraExtractor.invokePutactor
import com.hexated.SoraExtractor.invokeVidSrc
import com.hexated.SoraExtractor.invokeVidsrcto
@ -207,7 +207,7 @@ class SoraStreamLite : SoraStream() {
if (!res.isAnime) invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback)
},
{
if (!res.isAnime) invokePrimewire(res.title, res.year, res.season, res.episode, callback)
if (!res.isAnime) invokeGomovies(res.title, res.year, res.season, res.episode, callback)
},
{
if (!res.isAnime) invokePutactor(res.title, res.year, res.season, res.episode, callback)
@ -215,7 +215,6 @@ class SoraStreamLite : SoraStream() {
{
invokeWatchOnline(
res.imdbId,
res.id,
res.title,
res.airedYear ?: res.year,
res.season,

View file

@ -841,26 +841,25 @@ fun Document.findTvMoviesIframe(): String? {
suspend fun searchWatchOnline(
title: String? = null,
season: Int? = null,
imdbId: String? = null,
tmdbId: Int? = null,
year: Int? = null,
): NiceResponse? {
val wTitle = title?.dropLast(1) // weird but this will make search working
val mediaId = app.get(
if (season == null) {
"${watchOnlineAPI}/api/v1/movies?filters[q]=$wTitle"
"${watchOnlineAPI}/api/v1/do-search/?q=$wTitle"
} else {
"${watchOnlineAPI}/api/v1/shows?filters[q]=$wTitle"
"${watchOnlineAPI}/api/v1/do-search/?q=$wTitle"
}
).parsedSafe<WatchOnlineSearch>()?.items?.find {
it.imdb_id == imdbId || it.tmdb_id == tmdbId || it.imdb_id == imdbId?.removePrefix("tt")
).parsedSafe<WatchOnlineSearch>()?.result?.find {
it.title.equals(title, true) && it.year.equals("$year")
}?.slug
return app.get(
fixUrl(
mediaId ?: return null, if (season == null) {
"${watchOnlineAPI}/movies/view"
"${watchOnlineAPI}/movies/play"
} else {
"${watchOnlineAPI}/shows/view"
"${watchOnlineAPI}/shows/play"
}
)
)