sora: added Animetosho

This commit is contained in:
hexated 2023-08-21 07:55:21 +07:00
parent 3d60b9c792
commit 83e2c399f6
5 changed files with 100 additions and 70 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 = 158 version = 159
android { android {
defaultConfig { defaultConfig {

View file

@ -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(
it.attr("href"),
ele.select("div.size").text(),
getIndexQuality(ele.select("div.link a").text())
) )
.parsedSafe<BiliBiliDetails>()?.episodes?.find { }
it.episodeNumber == episode }
} ?: return }
val sources = val (seasonSLug, episodeSlug) = getEpisodeSlug(season, episode)
app.get( val jikan = app.get("$jikanAPI/anime/$malId/full").parsedSafe<JikanResponse>()?.data
"$biliBiliAPI/source?episode_id=${res.sourceEpisodeId}&source_media_id=${res.sourceMediaId}&source_id=${res.sourceId}", val aniId = jikan?.external?.find { it.name == "AniDB" }?.url?.substringAfterLast("=")
referer = otakuzBaseUrl val res = app.get("$animetoshoAPI/series/${jikan?.title?.createSlug()}.$aniId?filter[0][t]=nyaa_class&filter[0][v]=trusted").document
)
.parsedSafe<BiliBiliSourcesResponse>()
sources?.sources?.apmap { source -> val servers = if (season == null) {
val quality = res.select("div.home_list_entry:has(div.links)").getLinks()
app.get( } else {
source.file ?: return@apmap null, res.select("div.home_list_entry:has(div.link a:matches([\\.\\s]$episodeSlug[\\.\\s]|S${seasonSLug}E$episodeSlug))")
referer = otakuzBaseUrl .getLinks()
).document.selectFirst("Representation") }
?.attr("height")
servers.filter { it.third in arrayOf(Qualities.P1080.value,Qualities.P720.value) }.apmap {
loadExtractor(it.first, "$animetoshoAPI/", subtitleCallback) { link ->
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
"BiliBili", link.source,
"BiliBili", "${link.name} [${it.second}]",
source.file, link.url,
"", link.referer,
quality?.toIntOrNull() ?: Qualities.Unknown.value, when {
isDash = true link.isM3u8 -> link.quality
else -> it.third
},
link.isM3u8,
link.headers,
link.extractorData
) )
) )
} }
sources?.subtitles?.map { sub ->
subtitleCallback.invoke(
SubtitleFile(
SubtitleHelper.fromTwoLettersToLanguage(sub.lang ?: "") ?: sub.language
?: return@map null,
sub.file ?: return@map null
)
)
} }
} }
@ -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,

View file

@ -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(

View file

@ -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

View file

@ -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