refactor: Make extensions use the FilemoonExtractor shared lib (#1927)

This commit is contained in:
Claudemirovsky 2023-07-19 09:30:51 +00:00 committed by GitHub
parent 2b3f65062c
commit 70b2b1406e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 48 additions and 542 deletions

View File

@ -24,7 +24,9 @@ android {
applicationIdSuffix pkgNameSuffix
versionCode extVersionCode
versionName project.ext.properties.getOrDefault("libVersion", "13") + ".$extVersionCode"
setProperty("archivesBaseName", "aniyomi-$pkgNameSuffix-v$versionName")
base {
archivesBaseName = "aniyomi-$pkgNameSuffix-v$versionName"
}
def readmes = project.projectDir.listFiles({ File file ->
file.name.equals("README.md") ||
file.name.equals("CHANGELOG.md")

View File

@ -1,4 +1,5 @@
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation(project(':lib-streamsb-extractor'))
implementation "dev.datlag.jsunpacker:jsunpacker:1.0.1"
}

View File

@ -2,12 +2,12 @@ package eu.kanade.tachiyomi.animeextension.en.animenosub
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.en.animenosub.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animeextension.en.animenosub.extractors.StreamWishExtractor
import eu.kanade.tachiyomi.animeextension.en.animenosub.extractors.VidMolyExtractor
import eu.kanade.tachiyomi.animeextension.en.animenosub.extractors.VtubeExtractor
import eu.kanade.tachiyomi.animeextension.en.animenosub.extractors.WolfstreamExtractor
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor
import eu.kanade.tachiyomi.multisrc.animestream.AnimeStream
import org.jsoup.nodes.Element
@ -55,7 +55,7 @@ class Animenosub : AnimeStream(
WolfstreamExtractor(client).videosFromUrl(url, prefix)
}
url.contains("filemoon") -> {
FilemoonExtractor(client, headers).videosFromUrl(url, prefix)
FilemoonExtractor(client).videosFromUrl(url, prefix, headers)
}
else -> emptyList()
}

View File

@ -1,34 +0,0 @@
package eu.kanade.tachiyomi.animeextension.en.animenosub.extractors
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
class FilemoonExtractor(private val client: OkHttpClient, private val headers: Headers) {
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val jsE = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(eval)")!!.data()
val masterUrl = JsUnpacker.unpackAndCombine(jsE)?.substringAfter("{file:\"")
?.substringBefore("\"}") ?: return emptyList()
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:")
.forEach {
val quality = it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
val videoHeaders = headers.newBuilder()
.add("Accept", "*/*")
.add("Host", videoUrl.toHttpUrl().host)
.add("Origin", "https://${url.toHttpUrl().host}")
.add("Referer", "https://${url.toHttpUrl().host}/")
.build()
videoList.add(Video(videoUrl, prefix + quality, videoUrl, headers = videoHeaders))
}
return videoList
}
}

View File

@ -1,4 +1,5 @@
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation(project(':lib-dood-extractor'))
implementation(project(':lib-streamlare-extractor'))
implementation(project(':lib-streamsb-extractor'))

View File

@ -3,10 +3,10 @@ package eu.kanade.tachiyomi.animeextension.de.cinemathek
import androidx.preference.ListPreference
import androidx.preference.MultiSelectListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.de.cinemathek.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animeextension.de.cinemathek.extractors.StreamHideExtractor
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.streamlareextractor.StreamlareExtractor
import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor
import eu.kanade.tachiyomi.multisrc.dooplay.DooPlay

View File

@ -1,28 +0,0 @@
package eu.kanade.tachiyomi.animeextension.de.cinemathek.extractors
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
class FilemoonExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
return runCatching {
val doc = client.newCall(GET(url)).execute().asJsoup()
val jsEval = doc.selectFirst("script:containsData(eval)")!!.data()
val masterUrl = JsUnpacker.unpackAndCombine(jsEval)
?.substringAfter("{file:\"")
?.substringBefore("\"}")
?: return emptyList()
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val separator = "#EXT-X-STREAM-INF:"
masterPlaylist.substringAfter(separator).split(separator).map {
val quality = "Filemoon:" + it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
Video(videoUrl, quality, videoUrl)
}
}.getOrElse { emptyList() }
}
}

View File

@ -11,6 +11,7 @@ ext {
}
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation(project(':lib-voe-extractor'))
}

View File

@ -6,7 +6,6 @@ import androidx.preference.ListPreference
import androidx.preference.MultiSelectListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.de.filmpalast.extractors.EvoloadExtractor
import eu.kanade.tachiyomi.animeextension.de.filmpalast.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animeextension.de.filmpalast.extractors.StreamHideVidExtractor
import eu.kanade.tachiyomi.animeextension.de.filmpalast.extractors.UpstreamExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
@ -15,6 +14,7 @@ import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
@ -136,7 +136,7 @@ class FilmPalast : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
url.contains("filemoon.sx") && hosterSelection.contains("moon") ->
FilemoonExtractor(client).videoFromUrl(url)
FilemoonExtractor(client).videosFromUrl(url)
url.contains("hide.com") && hosterSelection.contains("hide") ->
StreamHideVidExtractor(client).videosFromUrl(url, "StreamHide")
url.contains("streamvid.net") && hosterSelection.contains("vid") ->

View File

@ -1,28 +0,0 @@
package eu.kanade.tachiyomi.animeextension.de.filmpalast.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
class FilemoonExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String): MutableList<Video>? {
try {
val jsE = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(eval)")!!.data()
val masterUrl = JsUnpacker(jsE).unpack().toString()
.substringAfter("{file:\"").substringBefore("\"}")
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:")
.forEach {
val quality = "Filemoon:" + it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} catch (e: Exception) {
return null
}
}
}

View File

@ -11,6 +11,7 @@ ext {
}
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation(project(':lib-streamtape-extractor'))
implementation(project(':lib-voe-extractor'))
}

View File

@ -6,7 +6,6 @@ import android.util.Log
import androidx.preference.ListPreference
import androidx.preference.MultiSelectListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.de.kool.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animeextension.de.movie4k.extractors.VidozaExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
@ -16,6 +15,7 @@ import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.network.POST
@ -418,10 +418,7 @@ class Kool : ConfigurableAnimeSource, AnimeHttpSource() {
}
item.jsonObject["url"]!!.jsonPrimitive.content.contains("https://filemoon.sx") && hosterSelection?.contains("fmoon") == true -> {
val videoUrl = item.jsonObject["url"]!!.jsonPrimitive.content
val videos = FilemoonExtractor(client).videoFromUrl(videoUrl)
if (videos != null) {
videoList.addAll(videos)
}
videoList.addAll(FilemoonExtractor(client).videosFromUrl(videoUrl))
}
response.request.url.toString().contains("kool-cluster/mediahubmx-resolve.json") -> {
val videoUrl = item.jsonObject["url"]!!.jsonPrimitive.content

View File

@ -1,28 +0,0 @@
package eu.kanade.tachiyomi.animeextension.de.kool.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
class FilemoonExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String): MutableList<Video>? {
try {
val jsE = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(eval)")!!.data()
val masterUrl = JsUnpacker(jsE).unpack().toString()
.substringAfter("{file:\"").substringBefore("\"}")
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:")
.forEach {
val quality = "Filemoon:" + it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} catch (e: Exception) {
return null
}
}
}

View File

@ -11,6 +11,7 @@ ext {
}
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation "dev.datlag.jsunpacker:jsunpacker:1.0.1"
}

View File

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.animeextension.en.ask4movie
import android.app.Application
import android.content.SharedPreferences
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.en.ask4movie.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@ -12,6 +11,7 @@ import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
@ -172,7 +172,7 @@ class Ask4Movie : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
// ============================ Video Links =============================
override fun fetchVideoList(episode: SEpisode): Observable<List<Video>> {
val videoList = FilemoonExtractor(client, headers).videosFromUrl(episode.url)
val videoList = FilemoonExtractor(client).videosFromUrl(episode.url, headers = headers)
require(videoList.isNotEmpty()) { "Failed to fetch videos" }
return Observable.just(videoList)
}

View File

@ -1,77 +0,0 @@
package eu.kanade.tachiyomi.animeextension.en.ask4movie.extractors
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
class FilemoonExtractor(private val client: OkHttpClient, private val headers: Headers) {
private val json: Json by injectLazy()
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val subtitleList = mutableListOf<Track>()
val subInfoUrl = url.toHttpUrl().queryParameter("sub.info")
runCatching {
if (subInfoUrl != null) {
val subData = client.newCall(GET(subInfoUrl, headers)).execute().parseAs<List<FMoviesSubs>>()
subtitleList.addAll(
subData.map {
Track(it.file, it.label)
},
)
}
}
val jsE = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(m3u8)")!!.data()
val masterUrl = JsUnpacker.unpackAndCombine(jsE)?.substringAfter("{file:\"")
?.substringBefore("\"}") ?: return emptyList()
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val videoList = mutableListOf<Video>()
val subtitleRegex = Regex("""#EXT-X-MEDIA:TYPE=SUBTITLES.*?NAME="(.*?)".*?URI="(.*?)"""")
subtitleList.addAll(
subtitleRegex.findAll(masterPlaylist).map {
Track(
it.groupValues[2],
it.groupValues[1],
)
},
)
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:")
.forEach {
val quality = it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
val videoHeaders = headers.newBuilder()
.add("Accept", "*/*")
.add("Origin", "https://${url.toHttpUrl().host}")
.add("Referer", "https://${url.toHttpUrl().host}/")
.build()
videoList.add(Video(videoUrl, prefix + quality, videoUrl, headers = videoHeaders, subtitleTracks = subtitleList))
}
return videoList
}
@Serializable
data class FMoviesSubs(
val file: String,
val label: String,
)
private inline fun <reified T> Response.parseAs(): T {
val responseBody = use { it.body.string() }
return json.decodeFromString(responseBody)
}
}

View File

@ -11,6 +11,7 @@ ext {
}
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation "dev.datlag.jsunpacker:jsunpacker:1.0.1"
}

View File

@ -5,7 +5,6 @@ import android.content.SharedPreferences
import androidx.preference.ListPreference
import androidx.preference.MultiSelectListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.en.fmovies.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animeextension.en.fmovies.extractors.StreamtapeExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@ -15,6 +14,7 @@ import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.util.asJsoup
@ -266,7 +266,7 @@ class FMovies : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
)
}
"Filemoon" -> {
FilemoonExtractor(client, headers).videosFromUrl(decrypted, prefix = "Filemoon - ")
FilemoonExtractor(client).videosFromUrl(decrypted, headers = headers)
}
"Streamtape" -> {
StreamtapeExtractor(client, headers).videosFromUrl(decrypted)

View File

@ -1,77 +0,0 @@
package eu.kanade.tachiyomi.animeextension.en.fmovies.extractors
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
class FilemoonExtractor(private val client: OkHttpClient, private val headers: Headers) {
private val json: Json by injectLazy()
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val subtitleList = mutableListOf<Track>()
val subInfoUrl = url.toHttpUrl().queryParameter("sub.info")
runCatching {
if (subInfoUrl != null) {
val subData = client.newCall(GET(subInfoUrl, headers)).execute().parseAs<List<FMoviesSubs>>()
subtitleList.addAll(
subData.map {
Track(it.file, it.label)
},
)
}
}
val jsE = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(m3u8)")!!.data()
val masterUrl = JsUnpacker.unpackAndCombine(jsE)?.substringAfter("{file:\"")
?.substringBefore("\"}") ?: return emptyList()
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val videoList = mutableListOf<Video>()
val subtitleRegex = Regex("""#EXT-X-MEDIA:TYPE=SUBTITLES.*?NAME="(.*?)".*?URI="(.*?)"""")
subtitleList.addAll(
subtitleRegex.findAll(masterPlaylist).map {
Track(
it.groupValues[2],
it.groupValues[1],
)
},
)
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:")
.forEach {
val quality = it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
val videoHeaders = headers.newBuilder()
.add("Accept", "*/*")
.add("Origin", "https://${url.toHttpUrl().host}")
.add("Referer", "https://${url.toHttpUrl().host}/")
.build()
videoList.add(Video(videoUrl, prefix + quality, videoUrl, headers = videoHeaders, subtitleTracks = subtitleList))
}
return videoList
}
@Serializable
data class FMoviesSubs(
val file: String,
val label: String,
)
private inline fun <reified T> Response.parseAs(): T {
val responseBody = use { it.body.string() }
return json.decodeFromString(responseBody)
}
}

View File

@ -11,6 +11,7 @@ ext {
}
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation(project(':lib-mp4upload-extractor'))
implementation (project(':lib-streamtape-extractor'))
implementation "dev.datlag.jsunpacker:jsunpacker:1.0.1"

View File

@ -13,6 +13,7 @@ import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.mp4uploadextractor.Mp4uploadExtractor
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.network.GET
@ -301,9 +302,9 @@ class NineAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
)
}
"filemoon" -> FilemoonExtractor(client)
.videoFromUrl(embedLink, "Filemoon - ${server.first}").let {
videoList.addAll(it)
}
.videosFromUrl(embedLink, "Filemoon - ${server.first} ")
.also(videoList::addAll)
"streamtape" -> StreamTapeExtractor(client)
.videoFromUrl(embedLink, "StreamTape - ${server.first}")?.let {
videoList.add(it)

View File

@ -1,79 +0,0 @@
package eu.kanade.tachiyomi.animeextension.en.nineanime
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.OkHttpClient
@Serializable
data class CaptionElement(
val file: String,
val label: String,
val kind: String,
)
class FilemoonExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, prefix: String = "Filemoon"): List<Video> {
try {
val unpacked = client.newCall(GET(url)).execute().asJsoup().select("script:containsData(eval)").mapNotNull { element ->
element?.data()
?.let { JsUnpacker.unpackAndCombine(it) }
}.first { it.contains("{file:") }
val subtitleTracks = mutableListOf<Track>()
if (unpacked.contains("fetch('")) {
val subtitleString = unpacked.substringAfter("fetch('").substringBefore("').")
try {
if (subtitleString.isNotEmpty()) {
val subResponse = client.newCall(
GET(subtitleString),
).execute()
val subtitles = Json.decodeFromString<List<CaptionElement>>(subResponse.body.string())
for (sub in subtitles) {
subtitleTracks.add(Track(sub.file, sub.label))
}
}
} catch (_: Error) {}
}
val masterUrl = unpacked.substringAfter("{file:\"").substringBefore("\"}")
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val videoList = mutableListOf<Video>()
val subtitleRegex = Regex("""#EXT-X-MEDIA:TYPE=SUBTITLES.*?NAME="(.*?)".*?URI="(.*?)"""")
try {
subtitleTracks.addAll(
subtitleRegex.findAll(masterPlaylist).map {
Track(
it.groupValues[2],
it.groupValues[1],
)
},
)
} catch (_: Error) {}
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:")
.forEach {
val quality = "$prefix " + it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
try {
videoList.add(Video(videoUrl, quality, videoUrl, subtitleTracks = subtitleTracks))
} catch (e: Error) {
videoList.add(Video(videoUrl, quality, videoUrl))
}
}
return videoList
} catch (e: Exception) {
return emptyList()
}
}
}

View File

@ -10,6 +10,7 @@ ext {
}
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation(project(':lib-streamtape-extractor'))
implementation(project(':lib-okru-extractor'))
implementation(project(':lib-streamsb-extractor'))

View File

@ -4,7 +4,6 @@ import android.app.Application
import android.content.SharedPreferences
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.animelatinohd.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animeextension.es.animelatinohd.extractors.SolidFilesExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
@ -15,6 +14,7 @@ import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
@ -192,9 +192,8 @@ class AnimeLatinoHD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
videoList.addAll(videos)
}
if (embedUrl.contains("filemoon")) {
FilemoonExtractor(client).videoFromUrl(url, language)?.let {
videoList.addAll(it)
}
FilemoonExtractor(client).videosFromUrl(url, language)
.also(videoList::addAll)
}
if (embedUrl.contains("streamtape")) {
val video = StreamTapeExtractor(client).videoFromUrl(url, language + "Streamtape")

View File

@ -1,28 +0,0 @@
package eu.kanade.tachiyomi.animeextension.es.animelatinohd.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
class FilemoonExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, prefix: String = ""): MutableList<Video>? {
try {
val jsE = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(eval)")!!.data()
val masterUrl = JsUnpacker(jsE).unpack().toString()
.substringAfter("{file:\"").substringBefore("\"}")
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:")
.forEach {
val quality = "$prefix Filemoon:" + it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality.trim(), videoUrl))
}
return videoList
} catch (e: Exception) {
return null
}
}
}

View File

@ -10,6 +10,7 @@ ext {
}
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation(project(':lib-streamlare-extractor'))
implementation(project(':lib-yourupload-extractor'))
implementation(project(':lib-streamtape-extractor'))

View File

@ -2,13 +2,13 @@ package eu.kanade.tachiyomi.animeextension.es.pelisplushd
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
import eu.kanade.tachiyomi.lib.streamlareextractor.StreamlareExtractor
import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor
@ -184,9 +184,8 @@ class Pelisplusph(override val name: String, override val baseUrl: String) : Pel
VoeExtractor(client).videoFromUrl(url, "$prefix VoeCDN")?.let { videoList.add(it) }
}
if (embedUrl.contains("filemoon") || embedUrl.contains("moonplayer")) {
FilemoonExtractor(client).videoFromUrl(url, prefix)?.let {
videoList.addAll(it)
}
FilemoonExtractor(client).videosFromUrl(url, prefix)
.also(videoList::addAll)
}
if (embedUrl.contains("streamlare")) {
videoList.addAll(StreamlareExtractor(client).videosFromUrl(url))

View File

@ -2,13 +2,13 @@ package eu.kanade.tachiyomi.animeextension.es.pelisplushd
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
import eu.kanade.tachiyomi.lib.streamlareextractor.StreamlareExtractor
import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor
@ -179,9 +179,8 @@ class Pelisplusto(override val name: String, override val baseUrl: String) : Pel
VoeExtractor(client).videoFromUrl(url)?.let { videoList.add(it) }
}
if (embedUrl.contains("filemoon") || embedUrl.contains("moonplayer")) {
FilemoonExtractor(client).videoFromUrl(url, prefix)?.let {
videoList.addAll(it)
}
FilemoonExtractor(client).videosFromUrl(url, prefix)
.also(videoList::addAll)
}
if (embedUrl.contains("streamlare")) {
videoList.addAll(StreamlareExtractor(client).videosFromUrl(url))

View File

@ -1,28 +0,0 @@
package eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
class FilemoonExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, prefix: String = ""): MutableList<Video>? {
try {
val jsE = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(eval)")!!.data()
val masterUrl = JsUnpacker(jsE).unpack().toString()
.substringAfter("{file:\"").substringBefore("\"}")
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:")
.forEach {
val quality = "$prefix Filemoon:" + it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality.trim(), videoUrl))
}
return videoList
} catch (e: Exception) {
return null
}
}
}

View File

@ -11,6 +11,7 @@ ext {
}
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation(project(':lib-streamtape-extractor'))
implementation(project(':lib-streamsb-extractor'))
implementation(project(':lib-dood-extractor'))

View File

@ -7,7 +7,6 @@ import androidx.preference.EditTextPreference
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.AppInfo
import eu.kanade.tachiyomi.animeextension.it.animeworld.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animeextension.it.animeworld.extractors.StreamHideExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
@ -17,6 +16,7 @@ import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.network.GET
@ -169,15 +169,15 @@ class ANIMEWORLD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
listOf(Video(url, "AnimeWorld Server", url))
}
url.contains("https://doo") -> {
val video = DoodExtractor(client).videoFromUrl(url, redirect = true)
video?.let { listOf(it) }
DoodExtractor(client).videoFromUrl(url, redirect = true)
?.let(::listOf)
}
url.contains("streamtape") -> {
val video = StreamTapeExtractor(client).videoFromUrl(url.replace("/v/", "/e/"))
video?.let { listOf(it) }
StreamTapeExtractor(client).videoFromUrl(url.replace("/v/", "/e/"))
?.let(::listOf)
}
url.contains("filemoon") -> {
FilemoonExtractor(client, headers).videosFromUrl(url, prefix = "${server.first} - ")
FilemoonExtractor(client).videosFromUrl(url, prefix = "${server.first} - ", headers = headers)
}
server.first.contains("streamhide", true) -> {
StreamHideExtractor(client).videosFromUrl(url, headers)

View File

@ -1,34 +0,0 @@
package eu.kanade.tachiyomi.animeextension.it.animeworld.extractors
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
class FilemoonExtractor(private val client: OkHttpClient, private val headers: Headers) {
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val jsE = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(eval)")!!.data()
val masterUrl = JsUnpacker.unpackAndCombine(jsE)?.substringAfter("{file:\"")
?.substringBefore("\"}") ?: return emptyList()
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:")
.forEach {
val quality = "Filemoon:" + it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
val videoHeaders = headers.newBuilder()
.add("Accept", "*/*")
.add("Host", videoUrl.toHttpUrl().host)
.add("Origin", "https://${url.toHttpUrl().host}")
.add("Referer", "https://${url.toHttpUrl().host}/")
.build()
videoList.add(Video(videoUrl, prefix + quality, videoUrl, headers = videoHeaders))
}
return videoList
}
}

View File

@ -12,6 +12,7 @@ ext {
}
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation("dev.datlag.jsunpacker:jsunpacker:1.0.1")
}

View File

@ -7,13 +7,13 @@ import eu.kanade.tachiyomi.animeextension.sr.animesrbija.dto.LatestUpdatesDto
import eu.kanade.tachiyomi.animeextension.sr.animesrbija.dto.PagePropsDto
import eu.kanade.tachiyomi.animeextension.sr.animesrbija.dto.SearchAnimeDto
import eu.kanade.tachiyomi.animeextension.sr.animesrbija.dto.SearchPageDto
import eu.kanade.tachiyomi.animeextension.sr.animesrbija.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.util.asJsoup

View File

@ -1,28 +0,0 @@
package eu.kanade.tachiyomi.animeextension.sr.animesrbija.extractors
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
class FilemoonExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
return runCatching {
val doc = client.newCall(GET(url)).execute().asJsoup()
val jsEval = doc.selectFirst("script:containsData(eval)")!!.data()
val masterUrl = JsUnpacker.unpackAndCombine(jsEval)
?.substringAfter("{file:\"")
?.substringBefore("\"}")
?: return emptyList()
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val separator = "#EXT-X-STREAM-INF:"
masterPlaylist.substringAfter(separator).split(separator).map {
val quality = "Filemoon:" + it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
Video(videoUrl, quality, videoUrl)
}
}.getOrElse { emptyList() }
}
}

View File

@ -5,6 +5,7 @@ plugins {
}
dependencies {
implementation(project(':lib-filemoon-extractor'))
implementation(project(':lib-mp4upload-extractor'))
implementation(project(":lib-cryptoaes"))
implementation(project(":lib-synchrony"))

View File

@ -8,7 +8,6 @@ import androidx.preference.MultiSelectListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.tr.turkanime.extractors.AlucardExtractor
import eu.kanade.tachiyomi.animeextension.tr.turkanime.extractors.EmbedgramExtractor
import eu.kanade.tachiyomi.animeextension.tr.turkanime.extractors.FilemoonExtractor
import eu.kanade.tachiyomi.animeextension.tr.turkanime.extractors.GoogleDriveExtractor
import eu.kanade.tachiyomi.animeextension.tr.turkanime.extractors.MVidooExtractor
import eu.kanade.tachiyomi.animeextension.tr.turkanime.extractors.MailRuExtractor
@ -29,6 +28,7 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.mp4uploadextractor.Mp4uploadExtractor
import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
import eu.kanade.tachiyomi.lib.sendvidextractor.SendvidExtractor
@ -268,7 +268,7 @@ class TurkAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
videoList.addAll(EmbedgramExtractor(client, headers).videosFromUrl(hosterLink, prefix = "$subber: "))
}
"FILEMOON" -> {
videoList.addAll(FilemoonExtractor(client, headers).videosFromUrl(hosterLink, prefix = "$subber: "))
videoList.addAll(FilemoonExtractor(client).videosFromUrl(hosterLink, prefix = "$subber: ", headers = headers))
}
"GDRIVE" -> {
Regex("""[\w-]{28,}""").find(hosterLink)?.groupValues?.get(0)?.let {

View File

@ -1,34 +0,0 @@
package eu.kanade.tachiyomi.animeextension.tr.turkanime.extractors
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
class FilemoonExtractor(private val client: OkHttpClient, private val headers: Headers) {
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val jsE = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(eval)")!!.data()
val masterUrl = JsUnpacker.unpackAndCombine(jsE)?.substringAfter("{file:\"")
?.substringBefore("\"}") ?: return emptyList()
val masterPlaylist = client.newCall(GET(masterUrl)).execute().body.string()
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:")
.forEach {
val quality = "Filemoon:" + it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = it.substringAfter("\n").substringBefore("\n")
val videoHeaders = headers.newBuilder()
.add("Accept", "*/*")
.add("Host", videoUrl.toHttpUrl().host)
.add("Origin", "https://${url.toHttpUrl().host}")
.add("Referer", "https://${url.toHttpUrl().host}/")
.build()
videoList.add(Video(videoUrl, prefix + quality, videoUrl, headers = videoHeaders))
}
return videoList
}
}