mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
sora: added Animetosho
This commit is contained in:
parent
3d60b9c792
commit
83e2c399f6
5 changed files with 100 additions and 70 deletions
|
@ -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 = 158
|
version = 159
|
||||||
|
|
||||||
android {
|
android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
|
import org.jsoup.select.Elements
|
||||||
|
|
||||||
val session = Session(Requests().baseClient)
|
val session = Session(Requests().baseClient)
|
||||||
|
|
||||||
|
@ -968,10 +969,10 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
argamap(
|
argamap(
|
||||||
{
|
{
|
||||||
invokeAniwatch(malId, episode, subtitleCallback, callback)
|
invokeAnimetosho(malId, season, episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeBiliBili(aniId, episode, subtitleCallback, callback)
|
invokeAniwatch(malId, episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
if (season != null) invokeCrunchyroll(
|
if (season != null) invokeCrunchyroll(
|
||||||
|
@ -987,54 +988,55 @@ object SoraExtractor : SoraStream() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun invokeBiliBili(
|
private suspend fun invokeAnimetosho(
|
||||||
aniId: Int? = null,
|
malId: Int? = null,
|
||||||
|
season: Int? = null,
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val res = app.get(
|
fun Elements.getLinks(): List<Triple<String, String, Int>> {
|
||||||
"$biliBiliAPI/anime/episodes?id=${aniId ?: return}&source_id=bilibili",
|
return this.flatMap { ele ->
|
||||||
referer = otakuzBaseUrl
|
ele.select("div.links a:matches(KrakenFiles|GoFile)").map {
|
||||||
)
|
Triple(
|
||||||
.parsedSafe<BiliBiliDetails>()?.episodes?.find {
|
it.attr("href"),
|
||||||
it.episodeNumber == episode
|
ele.select("div.size").text(),
|
||||||
} ?: return
|
getIndexQuality(ele.select("div.link a").text())
|
||||||
|
)
|
||||||
val sources =
|
}
|
||||||
app.get(
|
}
|
||||||
"$biliBiliAPI/source?episode_id=${res.sourceEpisodeId}&source_media_id=${res.sourceMediaId}&source_id=${res.sourceId}",
|
|
||||||
referer = otakuzBaseUrl
|
|
||||||
)
|
|
||||||
.parsedSafe<BiliBiliSourcesResponse>()
|
|
||||||
|
|
||||||
sources?.sources?.apmap { source ->
|
|
||||||
val quality =
|
|
||||||
app.get(
|
|
||||||
source.file ?: return@apmap null,
|
|
||||||
referer = otakuzBaseUrl
|
|
||||||
).document.selectFirst("Representation")
|
|
||||||
?.attr("height")
|
|
||||||
callback.invoke(
|
|
||||||
ExtractorLink(
|
|
||||||
"BiliBili",
|
|
||||||
"BiliBili",
|
|
||||||
source.file,
|
|
||||||
"",
|
|
||||||
quality?.toIntOrNull() ?: Qualities.Unknown.value,
|
|
||||||
isDash = true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sources?.subtitles?.map { sub ->
|
val (seasonSLug, episodeSlug) = getEpisodeSlug(season, episode)
|
||||||
subtitleCallback.invoke(
|
val jikan = app.get("$jikanAPI/anime/$malId/full").parsedSafe<JikanResponse>()?.data
|
||||||
SubtitleFile(
|
val aniId = jikan?.external?.find { it.name == "AniDB" }?.url?.substringAfterLast("=")
|
||||||
SubtitleHelper.fromTwoLettersToLanguage(sub.lang ?: "") ?: sub.language
|
val res = app.get("$animetoshoAPI/series/${jikan?.title?.createSlug()}.$aniId?filter[0][t]=nyaa_class&filter[0][v]=trusted").document
|
||||||
?: return@map null,
|
|
||||||
sub.file ?: return@map null
|
val servers = if (season == null) {
|
||||||
|
res.select("div.home_list_entry:has(div.links)").getLinks()
|
||||||
|
} else {
|
||||||
|
res.select("div.home_list_entry:has(div.link a:matches([\\.\\s]$episodeSlug[\\.\\s]|S${seasonSLug}E$episodeSlug))")
|
||||||
|
.getLinks()
|
||||||
|
}
|
||||||
|
|
||||||
|
servers.filter { it.third in arrayOf(Qualities.P1080.value,Qualities.P720.value) }.apmap {
|
||||||
|
loadExtractor(it.first, "$animetoshoAPI/", subtitleCallback) { link ->
|
||||||
|
callback.invoke(
|
||||||
|
ExtractorLink(
|
||||||
|
link.source,
|
||||||
|
"${link.name} [${it.second}]",
|
||||||
|
link.url,
|
||||||
|
link.referer,
|
||||||
|
when {
|
||||||
|
link.isM3u8 -> link.quality
|
||||||
|
else -> it.third
|
||||||
|
},
|
||||||
|
link.isM3u8,
|
||||||
|
link.headers,
|
||||||
|
link.extractorData
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2209,7 +2211,7 @@ object SoraExtractor : SoraStream() {
|
||||||
"$dahmerMoviesAPI/tvs/${title?.replace(":", " -")}/Season $season/"
|
"$dahmerMoviesAPI/tvs/${title?.replace(":", " -")}/Season $season/"
|
||||||
}
|
}
|
||||||
|
|
||||||
val request = app.get(url)
|
val request = app.get(url, timeout = 120L)
|
||||||
if (!request.isSuccessful) return
|
if (!request.isSuccessful) return
|
||||||
val paths = request.document.select("a").map {
|
val paths = request.document.select("a").map {
|
||||||
it.text() to it.attr("href")
|
it.text() to it.attr("href")
|
||||||
|
@ -2239,6 +2241,33 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun invoke2embed(
|
||||||
|
imdbId: String?,
|
||||||
|
season: Int?,
|
||||||
|
episode: Int?,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
) {
|
||||||
|
val server = "https://stream.2embed.cc"
|
||||||
|
val url = if(season == null) {
|
||||||
|
"$twoEmbedAPI/embed/$imdbId"
|
||||||
|
} else {
|
||||||
|
"$twoEmbedAPI/embedtv/$imdbId&s=$season&e=$episode"
|
||||||
|
}
|
||||||
|
|
||||||
|
val iframesrc = app.get(url).document.selectFirst("iframe#iframesrc")?.attr("src")
|
||||||
|
val framesrc = app.get(fixUrl(iframesrc ?: return, twoEmbedAPI)).document.selectFirst("iframe#framesrc")?.attr("src")
|
||||||
|
val video = app.get(fixUrl(framesrc ?: return, "$server/e/")).text.let {
|
||||||
|
Regex("file:\\s*\"(.*?m3u8.*?)\"").find(it)?.groupValues?.getOrNull(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
M3u8Helper.generateM3u8(
|
||||||
|
"2embed",
|
||||||
|
video ?: return,
|
||||||
|
"$server/",
|
||||||
|
).forEach(callback)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun invokePrimewire(
|
suspend fun invokePrimewire(
|
||||||
title: String? = null,
|
title: String? = null,
|
||||||
year: Int? = null,
|
year: Int? = null,
|
||||||
|
|
|
@ -177,32 +177,18 @@ data class IndexSearch(
|
||||||
@JsonProperty("data") val data: IndexData? = null,
|
@JsonProperty("data") val data: IndexData? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class BiliBiliEpisodes(
|
data class JikanExternal(
|
||||||
@JsonProperty("id") val id: Int? = null,
|
@JsonProperty("name") val name: String? = null,
|
||||||
@JsonProperty("sourceId") val sourceId: String? = null,
|
@JsonProperty("url") val url: String? = null,
|
||||||
@JsonProperty("sourceEpisodeId") val sourceEpisodeId: String? = null,
|
|
||||||
@JsonProperty("sourceMediaId") val sourceMediaId: String? = null,
|
|
||||||
@JsonProperty("episodeNumber") val episodeNumber: Int? = null,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
data class BiliBiliDetails(
|
data class JikanData(
|
||||||
@JsonProperty("episodes") val episodes: ArrayList<BiliBiliEpisodes>? = arrayListOf(),
|
@JsonProperty("title") val title: String? = null,
|
||||||
|
@JsonProperty("external") val external: ArrayList<JikanExternal>? = arrayListOf(),
|
||||||
)
|
)
|
||||||
|
|
||||||
data class BiliBiliSubtitles(
|
data class JikanResponse(
|
||||||
@JsonProperty("file") val file: String? = null,
|
@JsonProperty("data") val data: JikanData? = null,
|
||||||
@JsonProperty("lang") val lang: String? = null,
|
|
||||||
@JsonProperty("language") val language: String? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class BiliBiliSources(
|
|
||||||
@JsonProperty("file") val file: String? = null,
|
|
||||||
@JsonProperty("type") val type: String? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class BiliBiliSourcesResponse(
|
|
||||||
@JsonProperty("sources") val sources: ArrayList<BiliBiliSources>? = arrayListOf(),
|
|
||||||
@JsonProperty("subtitles") val subtitles: ArrayList<BiliBiliSubtitles>? = arrayListOf(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
data class WatchOnlineItems(
|
data class WatchOnlineItems(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.hexated
|
package com.hexated
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
import com.hexated.SoraExtractor.invoke2embed
|
||||||
import com.hexated.SoraExtractor.invokeAnimes
|
import com.hexated.SoraExtractor.invokeAnimes
|
||||||
import com.hexated.SoraExtractor.invokeAsk4Movies
|
import com.hexated.SoraExtractor.invokeAsk4Movies
|
||||||
import com.hexated.SoraExtractor.invokeBollyMaza
|
import com.hexated.SoraExtractor.invokeBollyMaza
|
||||||
|
@ -80,11 +81,13 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val anilistAPI = "https://graphql.anilist.co"
|
const val anilistAPI = "https://graphql.anilist.co"
|
||||||
const val malsyncAPI = "https://api.malsync.moe"
|
const val malsyncAPI = "https://api.malsync.moe"
|
||||||
const val consumetHelper = "https://api.consumet.org/anime/9anime/helper"
|
const val consumetHelper = "https://api.consumet.org/anime/9anime/helper"
|
||||||
|
const val jikanAPI = "https://api.jikan.moe/v4"
|
||||||
|
|
||||||
private val apiKey =
|
private val apiKey =
|
||||||
base64DecodeAPI("ZTM=NTg=MjM=MjM=ODc=MzI=OGQ=MmE=Nzk=Nzk=ZjI=NTA=NDY=NDA=MzA=YjA=") // PLEASE DON'T STEAL
|
base64DecodeAPI("ZTM=NTg=MjM=MjM=ODc=MzI=OGQ=MmE=Nzk=Nzk=ZjI=NTA=NDY=NDA=MzA=YjA=") // PLEASE DON'T STEAL
|
||||||
|
|
||||||
/** ALL SOURCES */
|
/** ALL SOURCES */
|
||||||
|
const val twoEmbedAPI = "https://www.2embed.cc"
|
||||||
const val vidSrcAPI = "https://v2.vidsrc.me"
|
const val vidSrcAPI = "https://v2.vidsrc.me"
|
||||||
const val dbgoAPI = "https://dbgo.fun"
|
const val dbgoAPI = "https://dbgo.fun"
|
||||||
const val movieHabAPI = "https://moviehab.com"
|
const val movieHabAPI = "https://moviehab.com"
|
||||||
|
@ -113,7 +116,6 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val smashyStreamAPI = "https://embed.smashystream.com"
|
const val smashyStreamAPI = "https://embed.smashystream.com"
|
||||||
const val watchSomuchAPI = "https://watchsomuch.tv" // sub only
|
const val watchSomuchAPI = "https://watchsomuch.tv" // sub only
|
||||||
const val ask4MoviesAPI = "https://ask4movie.nl"
|
const val ask4MoviesAPI = "https://ask4movie.nl"
|
||||||
const val biliBiliAPI = "https://api-vn.otakuz.live/server"
|
|
||||||
const val watchOnlineAPI = "https://watchonline.ag"
|
const val watchOnlineAPI = "https://watchonline.ag"
|
||||||
const val nineTvAPI = "https://moviesapi.club"
|
const val nineTvAPI = "https://moviesapi.club"
|
||||||
const val putlockerAPI = "https://ww7.putlocker.vip"
|
const val putlockerAPI = "https://ww7.putlocker.vip"
|
||||||
|
@ -132,6 +134,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val primewireAPI = "https://real-primewire.club"
|
const val primewireAPI = "https://real-primewire.club"
|
||||||
const val vidsrctoAPI = "https://vidsrc.to"
|
const val vidsrctoAPI = "https://vidsrc.to"
|
||||||
const val dramadayAPI = "https://dramaday.me"
|
const val dramadayAPI = "https://dramaday.me"
|
||||||
|
const val animetoshoAPI = "https://animetosho.org"
|
||||||
|
|
||||||
// INDEX SITE
|
// INDEX SITE
|
||||||
const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev"
|
const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev"
|
||||||
|
@ -739,7 +742,10 @@ open class SoraStream : TmdbProvider() {
|
||||||
subtitleCallback,
|
subtitleCallback,
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
if(!res.isAnime) invoke2embed(res.imdbId,res.season,res.episode,callback)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.hexated
|
package com.hexated
|
||||||
|
|
||||||
|
import com.hexated.SoraExtractor.invoke2embed
|
||||||
import com.hexated.SoraExtractor.invokeAnimes
|
import com.hexated.SoraExtractor.invokeAnimes
|
||||||
import com.hexated.SoraExtractor.invokeAsk4Movies
|
import com.hexated.SoraExtractor.invokeAsk4Movies
|
||||||
import com.hexated.SoraExtractor.invokeDbgo
|
import com.hexated.SoraExtractor.invokeDbgo
|
||||||
|
@ -355,7 +356,15 @@ class SoraStreamLite : SoraStream() {
|
||||||
subtitleCallback,
|
subtitleCallback,
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
if(!res.isAnime) invoke2embed(
|
||||||
|
res.imdbId,
|
||||||
|
res.season,
|
||||||
|
res.episode,
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
Loading…
Reference in a new issue