Spanish extension updates (#829)

* choose best quality video

Automatically choose a server that contains the best quality video.

* Extractor standardization

* bugs resolved
This commit is contained in:
miguelantonioe
2022-09-02 03:44:40 -05:00
committed by GitHub
parent c2f68cee4f
commit fc30286f7b
101 changed files with 1688 additions and 1075 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'Animefenix'
pkgNameSuffix = 'es.animefenix'
extClass = '.Animefenix'
extVersionCode = 5
extVersionCode = 6
libVersion = '13'
}

View File

@ -6,6 +6,7 @@ import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.animefenix.extractors.FembedExtractor
import eu.kanade.tachiyomi.animeextension.es.animefenix.extractors.OkruExtractor
import eu.kanade.tachiyomi.animeextension.es.animefenix.extractors.StreamSBExtractor
import eu.kanade.tachiyomi.animeextension.es.animefenix.extractors.StreamTapeExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
@ -23,6 +24,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.net.URLDecoder
class Animefenix : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -90,18 +92,15 @@ class Animefenix : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
when {
realUrl.contains("ok.ru") -> {
val video = OkruExtractor(client).videosFromUrl(realUrl)
videoList.addAll(video)
OkruExtractor(client).videosFromUrl(realUrl).map { videoList.add(it) }
}
realUrl.contains("fembed") -> {
val video = FembedExtractor().videosFromUrl(realUrl)
videoList.addAll(video)
FembedExtractor().videosFromUrl(realUrl).map { videoList.add(it) }
}
realUrl.contains("/stream/amz.php?") -> {
val video = amazonExtractor(baseUrl + realUrl.substringAfter(".."))
if (video.isNotBlank()) {
if (realUrl.contains("&ext=es")) {
videoList.add(Video(video, "Amazon ES", video))
} else {
videoList.add(Video(video, "Amazon", video))
@ -117,14 +116,26 @@ class Animefenix : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
}
realUrl.contains("streamtape") -> {
val video = StreamTapeExtractor(client).videoFromUrl(realUrl, "Streamtape")
val video = StreamTapeExtractor(client).videoFromUrl(realUrl, "StreamTape")
if (video != null) {
videoList.add(video)
}
}
realUrl.contains("sbthe") -> {
val headers = headers.newBuilder()
.set("referer", realUrl)
.set(
"User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
)
.set("Accept-Language", "es-MX,es-419;q=0.9,es;q=0.8,en;q=0.7")
.set("watchsb", "streamsb")
.set("authority", "embedsb.com")
.build()
StreamSBExtractor(client).videosFromUrl(realUrl, headers).map { videoList.add(it) }
}
}
}
return videoList
}
@ -134,6 +145,27 @@ class Animefenix : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Amazon")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
videoSorted.toList()
} catch (e: IOException) {
this
}
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
val filterList = if (filters.isEmpty()) getFilterList() else filters
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
@ -175,6 +207,14 @@ class Animefenix : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun latestUpdatesSelector() = popularAnimeSelector()
private fun amazonExtractor(url: String): String {
val document = client.newCall(GET(url)).execute().asJsoup()
val videoURl = document.selectFirst("script:containsData(sources: [)").data()
.substringAfter("[{\"file\":\"")
.substringBefore("\",").replace("\\", "")
return if (client.newCall(GET(videoURl)).execute().code == 200) videoURl else ""
}
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
AnimeFilter.Header("La busqueda por texto ignora el filtro"),
GenreFilter()
@ -238,31 +278,23 @@ class Animefenix : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
fun toUriPart() = vals[state].second
}
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "Amazon")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
}
return newList
}
return this
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Servidor Preferido"
entries = arrayOf("Amazon", "Fembed:480p", "Fembed:720p", "Amazon", "AmazonES", "FireLoad")
entryValues = arrayOf("Amazon", "Fembed:480p", "Fembed:720p", "Amazon", "AmazonES", "FireLoad")
title = "Preferred quality"
entries = arrayOf(
"Okru:1080p", "Okru:720p", "Okru:480p", "Okru:360p", "Okru:240p", "Okru:144p", // Okru
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", "Fembed:144p", // Fembed
"StreamSB:1080p", "StreamSB:720p", "StreamSB:480p", "StreamSB:360p", "StreamSB:240p", "StreamSB:144p", // StreamSB
"Amazon", "AmazonES", "StreamTape"
) // video servers without resolution
entryValues = arrayOf(
"Okru:1080p", "Okru:720p", "Okru:480p", "Okru:360p", "Okru:240p", "Okru:144p", // Okru
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", "Fembed:144p", // Fembed
"StreamSB:1080p", "StreamSB:720p", "StreamSB:480p", "StreamSB:360p", "StreamSB:240p", "StreamSB:144p", // StreamSB
"Amazon", "AmazonES", "StreamTape"
) // video servers without resolution
setDefaultValue("Amazon")
summary = "%s"
@ -275,12 +307,4 @@ class Animefenix : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
screen.addPreference(videoQualityPref)
}
private fun amazonExtractor(url: String): String {
val document = client.newCall(GET(url)).execute().asJsoup()
val videoURl = document.selectFirst("script:containsData(sources: [)").data()
.substringAfter("[{\"file\":\"")
.substringBefore("\",").replace("\\", "")
return if (client.newCall(GET(videoURl)).execute().code == 200) videoURl else ""
}
}

View File

@ -4,27 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,23 +4,37 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,20 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class SolidFilesExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val url = data.replace("\"", "")
val videoUrl = url
val quality = "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val url = data.replace("\"", "")
val videoUrl = url
val quality = prefix + "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -0,0 +1,54 @@
package eu.kanade.tachiyomi.animeextension.es.animefenix.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class StreamSBExtractor(private val client: OkHttpClient) {
private val hexArray = "0123456789ABCDEF".toCharArray()
private fun bytesToHex(bytes: ByteArray): String {
val hexChars = CharArray(bytes.size * 2)
for (j in bytes.indices) {
val v = bytes[j].toInt() and 0xFF
hexChars[j * 2] = hexArray[v ushr 4]
hexChars[j * 2 + 1] = hexArray[v and 0x0F]
}
return String(hexChars)
}
fun videosFromUrl(url: String, headers: Headers, prefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
return try {
val sbUrl = url.substringBefore("/e/")
val id = url.substringAfter("/e/").substringBefore(".html")
val bytes = id.toByteArray()
val bytesToHex = bytesToHex(bytes)
val master =
"$sbUrl/sources43/416f794d637048744d4565577c7c${bytesToHex}7c7c776e6c7a365964385a484b767c7c73747265616d7362/656d5a62394f713230524a667c7c373635353537333734623561373634613330353134633631376337633339353037343631363934393335363434333730373633363763376337613737353836323434353534363431343633323533376137633763373337343732363536313664373336327c7c59304b7778506d424c4c32767c7c73747265616d7362"
val json = Json.decodeFromString<JsonObject>(
client.newCall(GET(master, headers))
.execute().body!!.string()
)
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:").forEach {
val quality = prefix + "StreamSB:" + it.substringAfter("RESOLUTION=").substringAfter("x")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = headers))
}
videoList
} catch (e: IOException) {
videoList
}
}
}

View File

@ -4,15 +4,21 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class StreamTapeExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val document = client.newCall(GET(url)).execute().asJsoup()
val script = document.select("script:containsData(document.getElementById('robotlink'))")
.firstOrNull()?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '")
?: return null
val videoUrl = "https:" + script.substringBefore("'") +
script.substringAfter("+ ('xcd").substringBefore("'")
return Video(url, quality, videoUrl)
fun videoFromUrl(url: String, quality: String = "StreamTape"): Video? {
return try {
val linkRegex = "https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}/[a-z]/".toRegex()
val mainUrl = "https://streamtape.com/e/${ url.replace(linkRegex, "") }"
val document = client.newCall(GET(mainUrl)).execute().asJsoup()
val script = document.selectFirst("script:containsData(document.getElementById('robotlink'))")
?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '//")
?: return null
val videoUrl = "https://" + script.substringBefore("'+ ('xcd") + script.substringAfter("+ ('xcd").substringBefore("')")
Video(videoUrl, quality, videoUrl, headers = null)
} catch (i: IOException) {
null
}
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'AnimeFLV'
pkgNameSuffix = 'es.animeflv'
extClass = '.AnimeFlv'
extVersionCode = 25
extVersionCode = 26
libVersion = '13'
}

View File

@ -33,6 +33,7 @@ import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.io.IOException
import java.lang.Exception
class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -104,10 +105,6 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun episodeFromElement(element: Element) = throw Exception("not used")
private fun getNumberFromEpsString(epsStr: String): String {
return epsStr.filter { it.isDigit() }
}
override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
val videoList = mutableListOf<Video>()
@ -119,7 +116,6 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val json = servers!!.jsonObject
val quality = json!!["title"]!!.jsonPrimitive!!.content
var url = json!!["code"]!!.jsonPrimitive!!.content
if (quality == "SB") {
val headers = headers.newBuilder()
.set("referer", url)
@ -131,29 +127,19 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
.set("watchsb", "streamsb")
.set("authority", "embedsb.com")
.build()
val videos = StreamSBExtractor(client).videosFromUrl(url, headers)
videoList.addAll(videos)
StreamSBExtractor(client).videosFromUrl(url, headers).map { videoList.add(it) }
}
if (quality == "Fembed") {
val videos = FembedExtractor().videosFromUrl(url)
videoList.addAll(videos)
FembedExtractor().videosFromUrl(url).map { videoList.add(it) }
}
if (quality == "Stape") {
val url1 = json!!["url"]!!.jsonPrimitive!!.content
val video = StreamTapeExtractor(client).videoFromUrl(url1, quality)
if (video != null) {
videoList.add(video)
}
val video = StreamTapeExtractor(client).videoFromUrl(url1, "StreamTape")
if (video != null) videoList.add(video)
}
if (quality == "Doodstream") {
val video = try {
DoodExtractor(client).videoFromUrl(url, "DoodStream")
} catch (e: Exception) {
null
}
if (video != null) {
videoList.add(video)
}
val video = DoodExtractor(client).videoFromUrl(url, "DoodStream")
if (video != null) videoList.add(video)
}
if (quality == "Okru") {
val videos = OkruExtractor(client).videosFromUrl(url)
@ -161,8 +147,7 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
if (quality == "YourUpload") {
val headers = headers.newBuilder().add("referer", "https://www.yourupload.com/").build()
val videos = YourUploadExtractor(client).videoFromUrl(url, headers = headers)
if (!videos.isEmpty()) videoList.addAll(videos)
YourUploadExtractor(client).videoFromUrl(url, headers = headers).map { videoList.add(it) }
}
}
}
@ -177,21 +162,24 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "Stape")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Fembed:720p")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -304,8 +292,18 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("Fembed:480p", "Fembed:720p", "Stape", "hd", "sd", "low", "lowest", "mobile")
entryValues = arrayOf("Fembed:480p", "Fembed:720p", "Stape", "hd", "sd", "low", "lowest", "mobile")
entries = arrayOf(
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", "Fembed:144p", // Fembed
"Okru:1080p", "Okru:720p", "Okru:480p", "Okru:360p", "Okru:240p", "Okru:144p", // Okru
"StreamSB:1080p", "StreamSB:720p", "StreamSB:480p", "StreamSB:360p", "StreamSB:240p", "StreamSB:144p", // StreamSB
"YourUpload", "DoodStream", "StreamTape"
) // video servers without resolution
entryValues = arrayOf(
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", "Fembed:144p", // Fembed
"Okru:1080p", "Okru:720p", "Okru:480p", "Okru:360p", "Okru:240p", "Okru:144p", // Okru
"StreamSB:1080p", "StreamSB:720p", "StreamSB:480p", "StreamSB:360p", "StreamSB:240p", "StreamSB:144p", // StreamSB
"YourUpload", "DoodStream", "StreamTape"
) // video servers without resolution
setDefaultValue("Fembed:720p")
summary = "%s"

View File

@ -4,26 +4,30 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class DoodExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val response = client.newCall(GET(url)).execute()
val doodTld = url.substringAfter("https://dood.").substringBefore("/")
val content = response.body!!.string()
if (!content.contains("'/pass_md5/")) return null
val md5 = content.substringAfter("'/pass_md5/").substringBefore("',")
val token = md5.substringAfterLast("/")
val randomString = getRandomString()
val expiry = System.currentTimeMillis()
val videoUrlStart = client.newCall(
GET(
"https://dood.$doodTld/pass_md5/$md5",
Headers.headersOf("referer", url)
)
).execute().body!!.string()
val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry"
return Video(url, quality, videoUrl, headers = doodHeaders(doodTld))
return try {
val response = client.newCall(GET(url)).execute()
val doodTld = url.substringAfter("https://dood.").substringBefore("/")
val content = response.body!!.string()
if (!content.contains("'/pass_md5/")) return null
val md5 = content.substringAfter("'/pass_md5/").substringBefore("',")
val token = md5.substringAfterLast("/")
val randomString = getRandomString()
val expiry = System.currentTimeMillis()
val videoUrlStart = client.newCall(
GET(
"https://dood.$doodTld/pass_md5/$md5",
Headers.headersOf("referer", url)
)
).execute().body!!.string()
val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry"
Video(url, quality, videoUrl, headers = doodHeaders(doodTld))
} catch (e: IOException) {
null
}
}
private fun getRandomString(length: Int = 10): String {

View File

@ -4,28 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val prefix = qualityPrefix
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = prefix + "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,23 +4,37 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = qualityPrefix + "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.animeextension.es.animeflv.extractors
import android.util.Log
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import kotlinx.serialization.decodeFromString
@ -9,9 +8,9 @@ import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class StreamSBExtractor(private val client: OkHttpClient) {
private val hexArray = "0123456789ABCDEF".toCharArray()
private fun bytesToHex(bytes: ByteArray): String {
@ -25,27 +24,31 @@ class StreamSBExtractor(private val client: OkHttpClient) {
return String(hexChars)
}
fun videosFromUrl(url: String, headers: Headers): List<Video> {
val sbUrl = url.substringBefore("/e/")
val id = url.substringAfter("/e/").substringBefore(".html")
val bytes = id.toByteArray()
val bytesToHex = bytesToHex(bytes)
val master =
"$sbUrl/sources43/416f794d637048744d4565577c7c${bytesToHex}7c7c776e6c7a365964385a484b767c7c73747265616d7362/656d5a62394f713230524a667c7c373635353537333734623561373634613330353134633631376337633339353037343631363934393335363434333730373633363763376337613737353836323434353534363431343633323533376137633763373337343732363536313664373336327c7c59304b7778506d424c4c32767c7c73747265616d7362"
Log.i("bruh sb", master)
val json = Json.decodeFromString<JsonObject>(
client.newCall(GET(master, headers))
.execute().body!!.string()
)
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
fun videosFromUrl(url: String, headers: Headers, prefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:").forEach {
val quality = "StreamSB:" + it.substringAfter("RESOLUTION=").substringAfter("x")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = headers))
return try {
val sbUrl = url.substringBefore("/e/")
val id = url.substringAfter("/e/").substringBefore(".html")
val bytes = id.toByteArray()
val bytesToHex = bytesToHex(bytes)
val master =
"$sbUrl/sources43/416f794d637048744d4565577c7c${bytesToHex}7c7c776e6c7a365964385a484b767c7c73747265616d7362/656d5a62394f713230524a667c7c373635353537333734623561373634613330353134633631376337633339353037343631363934393335363434333730373633363763376337613737353836323434353534363431343633323533376137633763373337343732363536313664373336327c7c59304b7778506d424c4c32767c7c73747265616d7362"
val json = Json.decodeFromString<JsonObject>(
client.newCall(GET(master, headers))
.execute().body!!.string()
)
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:").forEach {
val quality = prefix + "StreamSB:" + it.substringAfter("RESOLUTION=").substringAfter("x")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = headers))
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,15 +4,21 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class StreamTapeExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val document = client.newCall(GET(url)).execute().asJsoup()
val script = document.select("script:containsData(document.getElementById('robotlink'))")
.firstOrNull()?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '")
?: return null
val videoUrl = "https:" + script.substringBefore("'") +
script.substringAfter("+ ('xcd").substringBefore("'")
return Video(url, quality, videoUrl)
fun videoFromUrl(url: String, quality: String = "StreamTape"): Video? {
return try {
val linkRegex = "https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}/[a-z]/".toRegex()
val mainUrl = "https://streamtape.com/e/${ url.replace(linkRegex, "") }"
val document = client.newCall(GET(mainUrl)).execute().asJsoup()
val script = document.selectFirst("script:containsData(document.getElementById('robotlink'))")
?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '//")
?: return null
val videoUrl = "https://" + script.substringBefore("'+ ('xcd") + script.substringAfter("+ ('xcd").substringBefore("')")
Video(videoUrl, quality, videoUrl, headers = null)
} catch (i: IOException) {
null
}
}
}

View File

@ -10,7 +10,7 @@ import java.io.IOException
class YourUploadExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, headers: Headers): List<Video> {
val videoList = mutableListOf<Video>()
try {
return try {
val document = client.newCall(GET(url)).execute()
if (document.isSuccessful) {
val content = document.asJsoup()
@ -21,8 +21,9 @@ class YourUploadExtractor(private val client: OkHttpClient) {
videoList.add(Video(basicUrl, "YourUpload", basicUrl, headers = headers))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'AnimeID'
pkgNameSuffix = 'es.animeid'
extClass = '.AnimeID'
extVersionCode = 3
extVersionCode = 4
libVersion = '13'
}

View File

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.animeextension.es.animeid
import android.app.Application
import android.content.SharedPreferences
import android.util.Log
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.animeid.extractors.StreamTapeExtractor
@ -29,6 +28,7 @@ import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.io.IOException
import java.net.URI
import java.text.SimpleDateFormat
import java.util.Date
@ -130,9 +130,7 @@ class AnimeID : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
var jsonString = script.attr("data")
val jsonUnescape = unescapeJava(jsonString)!!.replace("\\", "")
val url = jsonUnescape!!.substringAfter("src=\"").substringBefore("\"").replace("\\\\", "\\")
Log.i("bruh url", url)
val quality = getDomainName(url)
Log.i("bruh domain", quality.toString())
if (quality == "streamtape") {
val video = StreamTapeExtractor(client).videoFromUrl(url, "Streamtape")
if (video != null) {
@ -185,21 +183,24 @@ class AnimeID : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "Streamtape")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "StreamTape")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -211,7 +212,6 @@ class AnimeID : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
genreFilter.state != 0 -> GET("$baseUrl/genero/${genreFilter.toUriPart()}?pag=$page&sort=newest")
else -> GET("$baseUrl/series?sort=newest&pag=$page")
}
Log.i("genero", request.url.toString())
return request
}

View File

@ -4,15 +4,21 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class StreamTapeExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val document = client.newCall(GET(url)).execute().asJsoup()
val script = document.select("script:containsData(document.getElementById('robotlink'))")
.firstOrNull()?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '")
?: return null
val videoUrl = "https:" + script.substringBefore("'") +
script.substringAfter("+ ('xcd").substringBefore("'")
return Video(url, quality, videoUrl)
fun videoFromUrl(url: String, quality: String = "StreamTape"): Video? {
return try {
val linkRegex = "https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}/[a-z]/".toRegex()
val mainUrl = "https://streamtape.com/e/${ url.replace(linkRegex, "") }"
val document = client.newCall(GET(mainUrl)).execute().asJsoup()
val script = document.selectFirst("script:containsData(document.getElementById('robotlink'))")
?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '//")
?: return null
val videoUrl = "https://" + script.substringBefore("'+ ('xcd") + script.substringAfter("+ ('xcd").substringBefore("')")
Video(videoUrl, quality, videoUrl, headers = null)
} catch (i: IOException) {
null
}
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'AnimeLatinoHD'
pkgNameSuffix = 'es.animelatinohd'
extClass = '.AnimeLatinoHD'
extVersionCode = 3
extVersionCode = 4
libVersion = '13'
}

View File

@ -36,6 +36,7 @@ import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.io.IOException
class AnimeLatinoHD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -221,21 +222,24 @@ class AnimeLatinoHD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "[Sub] Fembed:720p")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "[Sub] Fembed:720p")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -365,11 +369,24 @@ class AnimeLatinoHD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun latestUpdatesNextPageSelector() = popularAnimeNextPageSelector()
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val options = arrayOf(
"[Sub] Fembed:1080p", "[Sub] Fembed:720p", "[Sub] Fembed:480p", "[Sub] Fembed:360p", "[Sub] Fembed:240p", // Fembed [Sub]
"[Lat] Fembed:1080p", "[Lat] Fembed:720p", "[Lat] Fembed:480p", "[Lat] Fembed:360p", "[Lat] Fembed:240p", // Fembed [Lat]
"[Sub] Okru:1080p", "[Sub] Okru:720p", "[Sub] Okru:480p", "[Sub] Okru:360p", "[Sub] Okru:240p", // Okru [Sub]
"[Lat] Okru:1080p", "[Lat] Okru:720p", "[Lat] Okru:480p", "[Lat] Okru:360p", "[Lat] Okru:240p", // Okru [Lat]
"[Sub] StreamSB:1080p", "[Sub] StreamSB:720p", "[Sub] StreamSB:480p", "[Sub] StreamSB:360p", "[Sub] StreamSB:240p", // StreamSB [Sub]
"[Lat] StreamSB:1080p", "[Lat] StreamSB:720p", "[Lat] StreamSB:480p", "[Lat] StreamSB:360p", "[Lat] StreamSB:240p", // StreamSB [Lat]
"[Sub] StreamTape", "[Lat] StreamTape", // video servers without resolution
"[Sub] DoodStream", "[Lat] DoodStream", // video servers without resolution
"[Sub] SolidFiles", "[Lat] SolidFiles", // video servers without resolution
"[Sub] Od.lk", "[Lat] Od.lk", // video servers without resolution
"[Sub] CldUp", "[Lat] CldUp"
) // video servers without resolution
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("[Sub] Od.lk", "[Sub] CldUp", "[Sub] SolidFiles", "[Sub] Fembed:720p", "[Sub] Fembed:480p", "[Lat] Od.lk", "[Lat] CldUp", "[Lat] SolidFiles", "[Lat] Fembed:720p", "[Lat] Fembed:480p")
entryValues = arrayOf("[Sub] Od.lk", "[Sub] CldUp", "[Sub] SolidFiles", "[Sub] Fembed:720p", "[Sub] Fembed:480p", "[Lat] Od.lk", "[Lat] CldUp", "[Lat] SolidFiles", "[Lat] Fembed:720p", "[Lat] Fembed:480p")
entries = options
entryValues = options
setDefaultValue("[Sub] Fembed:720p")
summary = "%s"

View File

@ -4,26 +4,30 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class DoodExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val response = client.newCall(GET(url)).execute()
val doodTld = url.substringAfter("https://dood.").substringBefore("/")
val content = response.body!!.string()
if (!content.contains("'/pass_md5/")) return null
val md5 = content.substringAfter("'/pass_md5/").substringBefore("',")
val token = md5.substringAfterLast("/")
val randomString = getRandomString()
val expiry = System.currentTimeMillis()
val videoUrlStart = client.newCall(
GET(
"https://dood.$doodTld/pass_md5/$md5",
Headers.headersOf("referer", url)
)
).execute().body!!.string()
val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry"
return Video(url, quality, videoUrl, headers = doodHeaders(doodTld))
return try {
val response = client.newCall(GET(url)).execute()
val doodTld = url.substringAfter("https://dood.").substringBefore("/")
val content = response.body!!.string()
if (!content.contains("'/pass_md5/")) return null
val md5 = content.substringAfter("'/pass_md5/").substringBefore("',")
val token = md5.substringAfterLast("/")
val randomString = getRandomString()
val expiry = System.currentTimeMillis()
val videoUrlStart = client.newCall(
GET(
"https://dood.$doodTld/pass_md5/$md5",
Headers.headersOf("referer", url)
)
).execute().body!!.string()
val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry"
Video(url, quality, videoUrl, headers = doodHeaders(doodTld))
} catch (e: IOException) {
null
}
}
private fun getRandomString(length: Int = 10): String {

View File

@ -4,28 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val prefix = qualityPrefix
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = prefix + "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,23 +4,37 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = qualityPrefix + "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,20 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class SolidFilesExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
val videoList = mutableListOf<Video>()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val url = data.replace("\"", "")
val videoUrl = url
val quality = prefix + "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val url = data.replace("\"", "")
val videoUrl = url
val quality = prefix + "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -8,9 +8,9 @@ import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class StreamSBExtractor(private val client: OkHttpClient) {
private val hexArray = "0123456789ABCDEF".toCharArray()
private fun bytesToHex(bytes: ByteArray): String {
@ -25,25 +25,30 @@ class StreamSBExtractor(private val client: OkHttpClient) {
}
fun videosFromUrl(url: String, headers: Headers, prefix: String = ""): List<Video> {
val sbUrl = url.substringBefore("/e")
val id = url.substringAfter("e/").substringBefore(".html")
val bytes = id.toByteArray()
val bytesToHex = bytesToHex(bytes)
val master =
"$sbUrl/sources43/416f794d637048744d4565577c7c${bytesToHex}7c7c776e6c7a365964385a484b767c7c73747265616d7362/656d5a62394f713230524a667c7c373635353537333734623561373634613330353134633631376337633339353037343631363934393335363434333730373633363763376337613737353836323434353534363431343633323533376137633763373337343732363536313664373336327c7c59304b7778506d424c4c32767c7c73747265616d7362"
val json = Json.decodeFromString<JsonObject>(
client.newCall(GET(master, headers))
.execute().body!!.string()
)
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:").forEach {
val quality = prefix + "StreamSB:" + it.substringAfter("RESOLUTION=").substringAfter("x")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = headers))
return try {
val sbUrl = url.substringBefore("/e/")
val id = url.substringAfter("/e/").substringBefore(".html")
val bytes = id.toByteArray()
val bytesToHex = bytesToHex(bytes)
val master =
"$sbUrl/sources43/416f794d637048744d4565577c7c${bytesToHex}7c7c776e6c7a365964385a484b767c7c73747265616d7362/656d5a62394f713230524a667c7c373635353537333734623561373634613330353134633631376337633339353037343631363934393335363434333730373633363763376337613737353836323434353534363431343633323533376137633763373337343732363536313664373336327c7c59304b7778506d424c4c32767c7c73747265616d7362"
val json = Json.decodeFromString<JsonObject>(
client.newCall(GET(master, headers))
.execute().body!!.string()
)
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:").forEach {
val quality = prefix + "StreamSB:" + it.substringAfter("RESOLUTION=").substringAfter("x")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = headers))
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,15 +4,21 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class StreamTapeExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val document = client.newCall(GET(url)).execute().asJsoup()
val script = document.select("script:containsData(document.getElementById('robotlink'))")
.firstOrNull()?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '")
?: return null
val videoUrl = "https:" + script.substringBefore("'") +
script.substringAfter("+ ('xcd").substringBefore("'")
return Video(url, quality, videoUrl)
fun videoFromUrl(url: String, quality: String = "StreamTape"): Video? {
return try {
val linkRegex = "https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}/[a-z]/".toRegex()
val mainUrl = "https://streamtape.com/e/${ url.replace(linkRegex, "") }"
val document = client.newCall(GET(mainUrl)).execute().asJsoup()
val script = document.selectFirst("script:containsData(document.getElementById('robotlink'))")
?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '//")
?: return null
val videoUrl = "https://" + script.substringBefore("'+ ('xcd") + script.substringAfter("+ ('xcd").substringBefore("')")
Video(videoUrl, quality, videoUrl, headers = null)
} catch (i: IOException) {
null
}
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'AnimeonlineNinja'
pkgNameSuffix = 'es.animeonlineninja'
extClass = '.AnimeonlineNinja'
extVersionCode = 7
extVersionCode = 8
libVersion = '13'
}

View File

@ -9,7 +9,7 @@ import eu.kanade.tachiyomi.animeextension.es.animeonlineninja.extractors.FembedE
import eu.kanade.tachiyomi.animeextension.es.animeonlineninja.extractors.JsUnpacker
import eu.kanade.tachiyomi.animeextension.es.animeonlineninja.extractors.StreamSBExtractor
import eu.kanade.tachiyomi.animeextension.es.animeonlineninja.extractors.StreamTapeExtractor
import eu.kanade.tachiyomi.animeextension.es.animeonlineninja.extractors.uploadExtractor
import eu.kanade.tachiyomi.animeextension.es.animeonlineninja.extractors.UploadExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@ -27,6 +27,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.lang.Exception
class AnimeonlineNinja : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -102,7 +103,7 @@ class AnimeonlineNinja : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val iframeLink = apiCall.toString().substringAfter("{\"embed_url\":\"").substringBefore("\"")
val sDocument = client.newCall(GET(iframeLink)).execute().asJsoup()
sDocument.select("div.ODDIV div").forEach {
val lang = it.attr("class").toString().substringAfter("OD OD_").replace("REactiv", "")
val lang = it.attr("class").toString().substringAfter("OD OD_").replace("REactiv", "").trim()
it.select("li").forEach { source ->
val sourceUrl = source.attr("onclick").toString().substringAfter("go_to_player('").substringBefore("')")
serverslangParse(sourceUrl, lang).map { video -> videoList.add(video) }
@ -116,7 +117,7 @@ class AnimeonlineNinja : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val apiCall = client.newCall(GET("https://www1.animeonline.ninja/wp-json/dooplayer/v1/post/$datapost?type=$datatype&source=$sourceId")).execute().asJsoup().body()
val sourceUrl = apiCall.toString().substringAfter("{\"embed_url\":\"").substringBefore("\"").replace("\\/", "/")
val lang2 = preferences.getString("preferred_lang", "SUB").toString()
val lang2 = preferences.getString("preferred_lang", "SUB").toString().trim()
serverslangParse(sourceUrl, lang2).map { video -> videoList.add(video) }
}
}
@ -184,8 +185,8 @@ class AnimeonlineNinja : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
serverUrl.contains("uqload") && lang.contains(langSelect) -> {
val headers = headers.newBuilder().add("referer", "https://uqload.com/").build()
val video = uploadExtractor(client).videofromurl(serverUrl, headers, lang)
videos.add(video)
val video = UploadExtractor(client).videoFromUrl(serverUrl, headers, lang)
if (video != null) videos.add(video)
}
}
@ -199,21 +200,24 @@ class AnimeonlineNinja : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "Mixdrop")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "SUB Fembed:1080p")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -337,7 +341,7 @@ class AnimeonlineNinja : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
title = "Preferred quality"
entries = arrayOf("SUB Fembed:480p", "SUB Fembed:720p", "SUB Fembed:1080p")
entryValues = arrayOf("SUB Fembed:480p", "SUB Fembed:720p", "SUB Fembed:1080p")
setDefaultValue("SUB Fembed:720p")
setDefaultValue("SUB Fembed:1080p")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->

View File

@ -4,26 +4,30 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class DoodExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val response = client.newCall(GET(url)).execute()
val doodTld = url.substringAfter("https://dood.").substringBefore("/")
val content = response.body!!.string()
if (!content.contains("'/pass_md5/")) return null
val md5 = content.substringAfter("'/pass_md5/").substringBefore("',")
val token = md5.substringAfterLast("/")
val randomString = getRandomString()
val expiry = System.currentTimeMillis()
val videoUrlStart = client.newCall(
GET(
"https://dood.$doodTld/pass_md5/$md5",
Headers.headersOf("referer", url)
)
).execute().body!!.string()
val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry"
return Video(url, quality, videoUrl, headers = doodHeaders(doodTld))
return try {
val response = client.newCall(GET(url)).execute()
val doodTld = url.substringAfter("https://dood.").substringBefore("/")
val content = response.body!!.string()
if (!content.contains("'/pass_md5/")) return null
val md5 = content.substringAfter("'/pass_md5/").substringBefore("',")
val token = md5.substringAfterLast("/")
val randomString = getRandomString()
val expiry = System.currentTimeMillis()
val videoUrlStart = client.newCall(
GET(
"https://dood.$doodTld/pass_md5/$md5",
Headers.headersOf("referer", url)
)
).execute().body!!.string()
val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry"
Video(url, quality, videoUrl, headers = doodHeaders(doodTld))
} catch (e: IOException) {
null
}
}
private fun getRandomString(length: Int = 10): String {

View File

@ -4,28 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val prefix = qualityPrefix
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = prefix + "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,23 +4,37 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,20 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class SolidFilesExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val url = data.replace("\"", "")
val videoUrl = url
val quality = "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val url = data.replace("\"", "")
val videoUrl = url
val quality = prefix + "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -8,9 +8,9 @@ import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class StreamSBExtractor(private val client: OkHttpClient) {
private val hexArray = "0123456789ABCDEF".toCharArray()
private fun bytesToHex(bytes: ByteArray): String {
@ -24,27 +24,31 @@ class StreamSBExtractor(private val client: OkHttpClient) {
return String(hexChars)
}
fun videosFromUrl(url: String, headers: Headers): List<Video> {
val sbUrl = url.substringBefore("/e/")
val id = url.substringAfter("/e/").substringBefore(".html")
val bytes = id.toByteArray()
val bytesToHex = bytesToHex(bytes)
val master =
"$sbUrl/sources43/416f794d637048744d4565577c7c${bytesToHex}7c7c776e6c7a365964385a484b767c7c73747265616d7362/656d5a62394f713230524a667c7c373635353537333734623561373634613330353134633631376337633339353037343631363934393335363434333730373633363763376337613737353836323434353534363431343633323533376137633763373337343732363536313664373336327c7c59304b7778506d424c4c32767c7c73747265616d7362"
val json = Json.decodeFromString<JsonObject>(
client.newCall(GET(master, headers))
.execute().body!!.string()
)
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
fun videosFromUrl(url: String, headers: Headers, prefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:").forEach {
val quality = "StreamSB:" + it.substringAfter("RESOLUTION=").substringAfter("x")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = headers))
return try {
val sbUrl = url.substringBefore("/e/")
val id = url.substringAfter("/e/").substringBefore(".html")
val bytes = id.toByteArray()
val bytesToHex = bytesToHex(bytes)
val master =
"$sbUrl/sources43/416f794d637048744d4565577c7c${bytesToHex}7c7c776e6c7a365964385a484b767c7c73747265616d7362/656d5a62394f713230524a667c7c373635353537333734623561373634613330353134633631376337633339353037343631363934393335363434333730373633363763376337613737353836323434353534363431343633323533376137633763373337343732363536313664373336327c7c59304b7778506d424c4c32767c7c73747265616d7362"
val json = Json.decodeFromString<JsonObject>(
client.newCall(GET(master, headers))
.execute().body!!.string()
)
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:").forEach {
val quality = prefix + "StreamSB:" + it.substringAfter("RESOLUTION=").substringAfter("x")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = headers))
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,15 +4,21 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class StreamTapeExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val document = client.newCall(GET(url)).execute().asJsoup()
val script = document.select("script:containsData(document.getElementById('robotlink'))")
.firstOrNull()?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '")
?: return null
val videoUrl = "https:" + script.substringBefore("'") +
script.substringAfter("+ ('xcd").substringBefore("'")
return Video(url, quality, videoUrl)
fun videoFromUrl(url: String, quality: String = "StreamTape"): Video? {
return try {
val linkRegex = "https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}/[a-z]/".toRegex()
val mainUrl = "https://streamtape.com/e/${ url.replace(linkRegex, "") }"
val document = client.newCall(GET(mainUrl)).execute().asJsoup()
val script = document.selectFirst("script:containsData(document.getElementById('robotlink'))")
?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '//")
?: return null
val videoUrl = "https://" + script.substringBefore("'+ ('xcd") + script.substringAfter("+ ('xcd").substringBefore("')")
Video(videoUrl, quality, videoUrl, headers = null)
} catch (i: IOException) {
null
}
}
}

View File

@ -0,0 +1,20 @@
package eu.kanade.tachiyomi.animeextension.es.animeonlineninja.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class UploadExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, headers: Headers, quality: String): Video? {
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val basicUrl = document.selectFirst("script:containsData(var player =)").data().substringAfter("sources: [\"").substringBefore("\"],")
return Video(basicUrl, "$quality Uqload", basicUrl, headers = headers)
} catch (e: IOException) {
null
}
}
}

View File

@ -1,15 +0,0 @@
package eu.kanade.tachiyomi.animeextension.es.animeonlineninja.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
class uploadExtractor(private val client: OkHttpClient) {
fun videofromurl(url: String, headers: Headers, quality: String): Video {
val document = client.newCall(GET(url)).execute().asJsoup()
val basicUrl = document.selectFirst("script:containsData(var player =)").data().substringAfter("sources: [\"").substringBefore("\"],")
return Video(basicUrl, "$quality Uqload", basicUrl, headers = headers)
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'Animeyt'
pkgNameSuffix = 'es.animeyt'
extClass = '.Animeyt'
extVersionCode = 3
extVersionCode = 4
libVersion = '13'
}

View File

@ -22,6 +22,7 @@ import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.io.IOException
import java.lang.Exception
class Animeyt : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -98,21 +99,24 @@ class Animeyt : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "fastream")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Fastream:720p")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request = GET("$baseUrl/search?q=$query&page=$page")
@ -155,9 +159,9 @@ class Animeyt : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("Fembed:480p", "Fembed:720p", "Stape", "hd", "sd", "low", "lowest", "mobile")
entryValues = arrayOf("Fembed:480p", "Fembed:720p", "Stape", "hd", "sd", "low", "lowest", "mobile")
setDefaultValue("fastream")
entries = arrayOf("Fastream:720p", "Fastream:480p", "Fastream:360p")
entryValues = arrayOf("Fastream:720p", "Fastream:480p", "Fastream:360p")
setDefaultValue("Fastream:720p")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->

View File

@ -1,12 +1,19 @@
package eu.kanade.tachiyomi.animeextension.es.animeyt.extractors
import android.util.Log
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject
import okhttp3.OkHttpClient
import uy.kohesive.injekt.injectLazy
import java.io.IOException
class FastreamExtractor(private val client: OkHttpClient) {
private val json: Json by injectLazy()
private fun fetchUrls(text: String?): List<String> {
if (text.isNullOrEmpty()) return listOf()
val linkRegex = "(http|ftp|https):\\/\\/([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:\\/~+#-]*[\\w@?^=%&\\/~+#-])".toRegex()
@ -25,12 +32,38 @@ class FastreamExtractor(private val client: OkHttpClient) {
videoList.add(Video(basicUrl, server, basicUrl, headers = null))
} else {
val packedRegex = Regex("eval\\(function\\(p,a,c,k,e,.*\\)\\)")
val qualities = listOf(
Pair("Low", "360p"),
Pair("Normal", "480p"),
Pair("HD", "720p"),
Pair("Full", "1080p"),
)
packedRegex.findAll(it!!.data()).map { packed -> packed.value }.toList().map { eval ->
val fastreamRegex = "fastream.*?\\.m3u8([^&\">]?)".toRegex()
val unpack = JsUnpacker.unpack(eval)
fetchUrls(unpack!!.first()).map { url ->
val fastreamRegex = "fastream.*?\\.m3u8([^&\">]?)".toRegex()
if (fastreamRegex.containsMatchIn(url)) {
videoList.add(Video(url, server, url, headers = null))
val urlQualities = url.split(",").filter { p -> !p.contains("m3u8") }
val baseUrl = urlQualities.first()
val jsonQualities = "{ \"qualityLabels\": { ${unpack.first().substringAfter("\\'qualityLabels\\':{").substringBefore("},")} }}"
val jObject = json.decodeFromString<JsonObject>(jsonQualities)
val jQualities = jObject["qualityLabels"]!!.jsonObject.map { jsonElement ->
val jQuality = jsonElement.value.toString().replace("\"", "")
qualities.find { q -> q.first.contains(jQuality) }?.second
}.toTypedArray()
Log.i("bruh jQuality join", jQualities.joinToString())
var qualityIdx = 0
urlQualities.map { _url ->
if (!_url.contains("http")) {
Log.i("bruh _url", "$_url $qualityIdx")
val quality = "$server:${jQualities[qualityIdx]}"
Log.i("bruh quality", quality)
val videoUrl = "$baseUrl$_url/master.m3u8"
Log.i("bruh videoUrl", videoUrl)
qualityIdx++
videoList.add(Video(videoUrl, quality, videoUrl, headers = null))
}
}
}
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'AsiaLiveAction'
pkgNameSuffix = 'es.asialiveaction'
extClass = '.AsiaLiveAction'
extVersionCode = 3
extVersionCode = 4
libVersion = '13'
}

View File

@ -23,6 +23,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.lang.Exception
import java.util.Calendar
@ -59,10 +60,10 @@ class AsiaLiveAction : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun animeDetailsParse(document: Document): SAnime {
val anime = SAnime.create()
anime.thumbnail_url = document.selectFirst("header div.Image figure img").attr("src").trim().replace("//", "https://")
anime.title = document.selectFirst("header div.asia-post-header div h1.Title").text()
anime.title = document.selectFirst("header div.asia-post-header h1.Title").text()
anime.description = document.selectFirst("header div.asia-post-main div.Description p:nth-child(2)").text().removeSurrounding("\"")
anime.genre = document.select("div.asia-post-header div:nth-child(2) p.Info span.tags a").joinToString { it.text() }
val year = document.select("div.asia-post-header div:nth-child(2) p.Info span.Date a").text().toInt()
anime.genre = document.select("div.asia-post-main p.Info span.tags a").joinToString { it.text() }
val year = document.select("header div.asia-post-main p.Info span.Date a").text().toInt()
val currentYear = Calendar.getInstance().get(Calendar.YEAR)
anime.status = when {
(year < currentYear) -> SAnime.COMPLETED
@ -80,13 +81,13 @@ class AsiaLiveAction : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun episodeFromElement(element: Element): SEpisode {
val episode = SEpisode.create()
val epNum = getNumberFromEpsString(element.select("div.flex-grow-1 p span").text())
val epNum = getNumberFromEpsString(element.select("div.flex-grow-1 p").text())
episode.setUrlWithoutDomain(element.attr("href"))
episode.episode_number = when {
(epNum.isNotEmpty()) -> epNum.toFloat()
else -> 1F
}
episode.name = element.select("div.flex-grow-1 p span").text().trim()
episode.name = element.select("div.flex-grow-1 p").text().trim()
return episode
}
@ -98,9 +99,10 @@ class AsiaLiveAction : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val document = response.asJsoup()
val videoList = mutableListOf<Video>()
document.select("script").forEach { script ->
if (script.data().contains("var videosJap = [")) {
if (script.data().contains("var videosJap = [") || script.data().contains("var videosCor = [")) {
val content = script.data()
if (content.contains("sbfull")) {
val sbDomains = arrayOf("sbfull", "sbplay", "cloudemb", "sbplay", "embedsb", "pelistop", "streamsb", "sbplay", "sbspeed")
if (sbDomains.any { s -> content.contains(s) }) {
val url = content.substringAfter(",['SB','").substringBefore("',0,0]")
val headers = headers.newBuilder()
.set("Referer", url)
@ -136,21 +138,24 @@ class AsiaLiveAction : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "Fembed:1080p")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Fembed:1080p")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -218,11 +223,16 @@ class AsiaLiveAction : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun latestUpdatesSelector() = popularAnimeSelector()
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualities = arrayOf(
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", // Fembed
"Okru:1080p", "Okru:720p", "Okru:480p", "Okru:360p", "Okru:240p", // Okru
"StreamSB:1080p", "StreamSB:720p", "StreamSB:480p", "StreamSB:360p", "StreamSB:240p" // StreamSB
)
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("Fembed:480p", "Fembed:720p", "Stape", "hd", "sd", "low", "lowest", "mobile")
entryValues = arrayOf("Fembed:480p", "Fembed:720p", "Stape", "hd", "sd", "low", "lowest", "mobile")
entries = qualities
entryValues = qualities
setDefaultValue("Fembed:1080p")
summary = "%s"

View File

@ -4,27 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,23 +4,37 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -8,9 +8,9 @@ import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class StreamSBExtractor(private val client: OkHttpClient) {
private val hexArray = "0123456789ABCDEF".toCharArray()
private fun bytesToHex(bytes: ByteArray): String {
@ -24,26 +24,30 @@ class StreamSBExtractor(private val client: OkHttpClient) {
return String(hexChars)
}
fun videosFromUrl(url: String, headers: Headers): List<Video> {
val sbUrl = url.substringBefore("/e")
val id = url.substringAfter("e/").substringBefore(".html")
val bytes = id.toByteArray()
val bytesToHex = bytesToHex(bytes)
val master =
"$sbUrl/sources43/566d337678566f743674494a7c7c${bytesToHex}7c7c346b6767586d6934774855537c7c73747265616d7362/6565417268755339773461447c7c346133383438333436313335376136323337373433383634376337633465366534393338373136643732373736343735373237613763376334363733353737303533366236333463353333363534366137633763373337343732363536313664373336327c7c6b586c3163614468645a47617c7c73747265616d7362"
val json = Json.decodeFromString<JsonObject>(
client.newCall(GET(master, headers))
.execute().body!!.string()
)
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
fun videosFromUrl(url: String, headers: Headers, prefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:").forEach {
val quality = "StreamSB:" + it.substringAfter("RESOLUTION=").substringAfter("x")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = headers))
return try {
val sbUrl = url.substringBefore("/e/")
val id = url.substringAfter("/e/").substringBefore(".html")
val bytes = id.toByteArray()
val bytesToHex = bytesToHex(bytes)
val master = "$sbUrl/sources43/674a44656e7654507975614b7c7c${bytesToHex}7c7c4a6d665478704f786e5a464f7c7c73747265616d7362/384c6d46545332726b3171787c7c373637333438343737393661363735343538366434353730376337633734353037393332353734333638363436643730363637373763376336363631346634353732366333323635343933343537346637633763373337343732363536313664373336327c7c5154416f774c34306d4877387c7c73747265616d7362"
val json = Json.decodeFromString<JsonObject>(
client.newCall(GET(master, headers))
.execute().body!!.string()
)
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:").forEach {
val quality = prefix + "StreamSB:" + it.substringAfter("RESOLUTION=").substringAfter("x")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = headers))
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'Doramasyt'
pkgNameSuffix = 'es.doramasyt'
extClass = '.Doramasyt'
extVersionCode = 2
extVersionCode = 3
libVersion = '13'
}

View File

@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.animeextension.es.doramasyt.extractors.FembedExtracto
import eu.kanade.tachiyomi.animeextension.es.doramasyt.extractors.OkruExtractor
import eu.kanade.tachiyomi.animeextension.es.doramasyt.extractors.SolidFilesExtractor
import eu.kanade.tachiyomi.animeextension.es.doramasyt.extractors.StreamTapeExtractor
import eu.kanade.tachiyomi.animeextension.es.doramasyt.extractors.UqloadExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@ -25,6 +26,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
class Doramasyt : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -91,26 +93,33 @@ class Doramasyt : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val server = players.text()
val urlEncoded = players.attr("data-player")
val byte = android.util.Base64.decode(urlEncoded, android.util.Base64.DEFAULT)
val url = String(byte, charset("UTF-8")).replace("https://doramasyt.com/reproductor?url=", "")
Log.i("bruh server", url)
if (server == "fembed") {
val url = String(byte, charset("UTF-8")).substringAfter("?url=")
if (server.contains("fembed")) {
val videos = FembedExtractor().videosFromUrl(url)
videoList.addAll(videos)
}
if (server == "streamtape") {
val video = StreamTapeExtractor(client).videoFromUrl(url, "Streamtape")
if (server.contains("streamtape")) {
val video = StreamTapeExtractor(client).videoFromUrl(url)
if (video != null) {
videoList.add(video)
}
}
if (server == "ok") {
if (server.contains("ok")) {
val videos = OkruExtractor(client).videosFromUrl(url)
videoList.addAll(videos)
}
if (server == "zeus") {
if (server.contains("zeus")) {
val videos = SolidFilesExtractor(client).videosFromUrl(url)
videoList.addAll(videos)
}
if (server.contains("uqload")) {
val headers = headers.newBuilder().add("referer", "https://uqload.com/").build()
UqloadExtractor(client).videoFromUrl(url, headers, "Uqload").map { videoList.add(it) }
}
if (server.contains("upload")) {
val headers = headers.newBuilder().add("referer", "https://upload.com/").build()
UqloadExtractor(client).videoFromUrl(url, headers, "Upload").map { videoList.add(it) }
}
}
return videoList
}
@ -122,21 +131,24 @@ class Doramasyt : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "fembed")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Fembed:720p")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -148,7 +160,6 @@ class Doramasyt : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
genreFilter.state != 0 -> GET("$baseUrl/doramas?categoria=false&genero=${genreFilter.toUriPart()}&fecha=false&letra=false&p=$page")
else -> GET("$baseUrl/doramas/?p=$page")
}
// GET("$baseUrl/buscar?q=$query&p=$page")
}
override fun searchAnimeFromElement(element: Element): SAnime {
@ -267,11 +278,16 @@ class Doramasyt : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualities = arrayOf(
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", // Fembed
"Okru:1080p", "Okru:720p", "Okru:480p", "Okru:360p", "Okru:240p", "Okru:144p", // Okru
"Uqload", "Upload", "SolidFiles", "StreamTape", // video servers without resolution
)
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("Fembed:480p", "Fembed:720p", "Fembed:1080p", "Streamtape", "SolidFiles", "Okru: mobile", "Okru: lowest", "Okru: low", "Okru: sd", "Okru: hd")
entryValues = arrayOf("Fembed:480p", "Fembed:720p", "Fembed:1080p", "Streamtape", "SolidFiles", "Okru: mobile", "Okru: lowest", "Okru: low", "Okru: sd", "Okru: hd")
entries = qualities
entryValues = qualities
setDefaultValue("Fembed:720p")
summary = "%s"

View File

@ -4,27 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,23 +4,37 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,19 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class SolidFilesExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val videoUrl = data.replace("\"", "")
val quality = "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val url = data.replace("\"", "")
val videoUrl = url
val quality = prefix + "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,15 +4,21 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class StreamTapeExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val document = client.newCall(GET(url)).execute().asJsoup()
val script = document.select("script:containsData(document.getElementById('robotlink'))")
.firstOrNull()?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '")
?: return null
val videoUrl = "https:" + script.substringBefore("'") +
script.substringAfter("+ ('xcd").substringBefore("'")
return Video(url, quality, videoUrl)
fun videoFromUrl(url: String, quality: String = "StreamTape"): Video? {
return try {
val linkRegex = "https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}/[a-z]/".toRegex()
val mainUrl = "https://streamtape.com/e/${ url.replace(linkRegex, "") }"
val document = client.newCall(GET(mainUrl)).execute().asJsoup()
val script = document.selectFirst("script:containsData(document.getElementById('robotlink'))")
?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '//")
?: return null
val videoUrl = "https://" + script.substringBefore("'+ ('xcd") + script.substringAfter("+ ('xcd").substringBefore("')")
Video(videoUrl, quality, videoUrl, headers = null)
} catch (i: IOException) {
null
}
}
}

View File

@ -0,0 +1,29 @@
package eu.kanade.tachiyomi.animeextension.es.doramasyt.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class UqloadExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, headers: Headers, quality: String): List<Video> {
val videoList = mutableListOf<Video>()
return try {
val document = client.newCall(GET(url)).execute()
if (document.isSuccessful) {
val response = document.asJsoup()
response.select("script").map {
if (it.data().contains("var player =")) {
val basicUrl = it.data().substringAfter("sources: [\"").substringBefore("\"],")
videoList.add(Video(basicUrl, quality, basicUrl, headers = headers))
}
}
}
videoList
} catch (e: IOException) {
videoList
}
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'Hentaijk'
pkgNameSuffix = 'es.hentaijk'
extClass = '.Hentaijk'
extVersionCode = 3
extVersionCode = 4
libVersion = '13'
containsNsfw = true
}

View File

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.animeextension.es.hentaijk
import android.app.Application
import android.content.SharedPreferences
import android.util.Log
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.hentaijk.extractors.FembedExtractor
@ -26,6 +25,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.lang.Exception
class Hentaijk : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -75,12 +75,10 @@ class Hentaijk : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
?.replace("#pag", "")
val firstPage = pageNumber.first()?.attr("href")
?.replace("#pag", "")
Log.i("bruh", "ULTIMA: $lastPage")
if (firstPage != lastPage) {
var checkLast = 0
for (i in 1 until lastPage?.toInt()!!) {
Log.i("bruh", "aaa")
for (j in 1..12) {
// Log.i("bruh", (j + checkLast).toString())
val episode = SEpisode.create().apply {
@ -96,7 +94,6 @@ class Hentaijk : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
Jsoup.connect("https://hentaijk.com/ajax/pagination_episodes/$animeId/$lastPage").get()
.body().select("body").text().replace("}]", "").split("}").forEach { json ->
val number = json.substringAfter("\"number\":\"").substringBefore("\"")
Log.i("bruh", number)
val episode = SEpisode.create().apply {
episode_number = number.toFloat()
name = "Episodio $number"
@ -111,7 +108,6 @@ class Hentaijk : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
Jsoup.connect("https://hentaijk.com/ajax/pagination_episodes/$animeId/$lastPage").get()
.body().select("body").text().replace("}]", "").split("}").forEach { json ->
val number = json.substringAfter("\"number\":\"").substringBefore("\"")
Log.i("bruh", number)
val episode = SEpisode.create().apply {
episode_number = number.toFloat()
name = "Episodio $number"
@ -210,21 +206,24 @@ class Hentaijk : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "Sabrosio")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Sabrosio")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -262,7 +261,7 @@ class Hentaijk : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val animeList = mutableListOf<SAnime>()
val document = jsonLine.asJsoup()
val hasNextPage = document.select("section.contenido.spad div.container div.navigation a.nav-next").any()
var isSearchLayer = document.select(".col-lg-2.col-md-6.col-sm-6").any()
val isSearchLayer = document.select(".col-lg-2.col-md-6.col-sm-6").any()
val isFilterLayer = document.select(".card.mb-3.custom_item2").any()
if (isSearchLayer) {
document.select(".col-lg-2.col-md-6.col-sm-6").forEach { animeData ->
@ -288,7 +287,6 @@ class Hentaijk : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
animeList.add(anime)
}
}
Log.i("bruh parseSearchJson", hasNextPage.toString())
return AnimesPage(animeList, hasNextPage)
}
@ -443,11 +441,16 @@ class Hentaijk : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualities = arrayOf(
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", // Fembed
"Okru:1080p", "Okru:720p", "Okru:480p", "Okru:360p", "Okru:240p", // Okru
"Xtreme S", "HentaiJk", "Nozomi", "Desu" // video servers without resolution
)
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("Sabrosio", "Desu", "Xtreme S", "Fembed:480p", "Fembed:720p", "Fembed:1080p", "Okru: full", "Okru: sd", "Okru: low", "Okru: lowest", "Okru: mobile")
entryValues = arrayOf("Sabrosio", "Desu", "Xtreme S", "Fembed:480p", "Fembed:720p", "Fembed:1080p", "Okru: full", "Okru: sd", "Okru: low", "Okru: lowest", "Okru: mobile")
entries = qualities
entryValues = qualities
setDefaultValue("Sabrosio")
summary = "%s"

View File

@ -4,27 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,23 +4,37 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'Hentaila'
pkgNameSuffix = 'es.hentaila'
extClass = '.Hentaila'
extVersionCode = 6
extVersionCode = 7
libVersion = '13'
containsNsfw = true
}

View File

@ -30,6 +30,7 @@ import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.io.IOException
import java.lang.Exception
class Hentaila : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -120,21 +121,24 @@ class Hentaila : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "Fembed:480p")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Fembed:1080p")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
@OptIn(ExperimentalSerializationApi::class)
@ -251,12 +255,16 @@ class Hentaila : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualities = arrayOf(
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", // Fembed
"Arc" // video servers without resolution
)
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("Arc", "Fembed:480p", "Fembed:720p", "Fembed:1080p")
entryValues = arrayOf("Arc", "Fembed:480p", "Fembed:720p", "Fembed:1080p")
setDefaultValue("Fembed:480p")
entries = qualities
entryValues = qualities
setDefaultValue("Fembed:1080p")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->

View File

@ -4,27 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,23 +4,37 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'Jkanime'
pkgNameSuffix = 'es.jkanime'
extClass = '.Jkanime'
extVersionCode = 4
extVersionCode = 5
libVersion = '13'
}

View File

@ -26,6 +26,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.lang.Exception
class Jkanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -205,21 +206,24 @@ class Jkanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "Nozomi")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Nozomi")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -437,11 +441,16 @@ class Jkanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualities = arrayOf(
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", // Fembed
"Okru:1080p", "Okru:720p", "Okru:480p", "Okru:360p", "Okru:240p", // Okru
"Xtreme S", "HentaiJk", "Nozomi", "Desu" // video servers without resolution
)
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("Nozomi", "Desu", "Xtreme S", "Fembed:480p", "Fembed:720p", "Fembed:1080p", "Okru: full", "Okru: sd", "Okru: low", "Okru: lowest", "Okru: mobile")
entryValues = arrayOf("Nozomi", "Desu", "Xtreme S", "Fembed:480p", "Fembed:720p", "Fembed:1080p", "Okru: full", "Okru: sd", "Okru: low", "Okru: lowest", "Okru: mobile")
entries = qualities
entryValues = qualities
setDefaultValue("Nozomi")
summary = "%s"

View File

@ -4,27 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,23 +4,37 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'Jkhentai'
pkgNameSuffix = 'es.jkhentai'
extClass = '.Jkhentai'
extVersionCode = 5
extVersionCode = 6
libVersion = '13'
containsNsfw = true
}

View File

@ -5,6 +5,7 @@ import android.content.SharedPreferences
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.jkhentai.extractors.StreamTapeExtractor
import eu.kanade.tachiyomi.animeextension.es.jkhentai.extractors.YourUploadExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@ -21,6 +22,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.lang.Exception
class Jkhentai : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -91,6 +93,11 @@ class Jkhentai : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
videoList.add(video)
}
}
if (server == "Upload") {
val url = it.select("div.player-content iframe").attr("src")
val headers = headers.newBuilder().add("referer", "https://www.yourupload.com/").build()
YourUploadExtractor(client).videoFromUrl(url, headers = headers).map { vid -> videoList.add(vid) }
}
}
}
return videoList
@ -103,21 +110,24 @@ class Jkhentai : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "StreamTape")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "StreamTape")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -219,8 +229,8 @@ class Jkhentai : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("StreamTape")
entryValues = arrayOf("StreamTape")
entries = arrayOf("StreamTape", "YourUpload")
entryValues = arrayOf("StreamTape", "YourUpload")
setDefaultValue("StreamTape")
summary = "%s"

View File

@ -4,27 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,23 +4,37 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,20 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class SolidFilesExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val url = data.replace("\"", "")
val videoUrl = url
val quality = "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val url = data.replace("\"", "")
val videoUrl = url
val quality = prefix + "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,15 +4,21 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class StreamTapeExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val document = client.newCall(GET(url)).execute().asJsoup()
val script = document.select("script:containsData(document.getElementById('robotlink'))")
.firstOrNull()?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '")
?: return null
val videoUrl = "https:" + script.substringBefore("'") +
script.substringAfter("+ ('xcd").substringBefore("'")
return Video(url, quality, videoUrl)
fun videoFromUrl(url: String, quality: String = "StreamTape"): Video? {
return try {
val linkRegex = "https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}/[a-z]/".toRegex()
val mainUrl = "https://streamtape.com/e/${ url.replace(linkRegex, "") }"
val document = client.newCall(GET(mainUrl)).execute().asJsoup()
val script = document.selectFirst("script:containsData(document.getElementById('robotlink'))")
?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '//")
?: return null
val videoUrl = "https://" + script.substringBefore("'+ ('xcd") + script.substringAfter("+ ('xcd").substringBefore("')")
Video(videoUrl, quality, videoUrl, headers = null)
} catch (i: IOException) {
null
}
}
}

View File

@ -0,0 +1,29 @@
package eu.kanade.tachiyomi.animeextension.es.jkhentai.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class YourUploadExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, headers: Headers): List<Video> {
val videoList = mutableListOf<Video>()
return try {
val document = client.newCall(GET(url)).execute()
if (document.isSuccessful) {
val content = document.asJsoup()
val baseData =
content!!.selectFirst("script:containsData(jwplayerOptions)")!!.data()
if (!baseData.isNullOrEmpty()) {
val basicUrl = baseData.substringAfter("file: '").substringBefore("',")
videoList.add(Video(basicUrl, "YourUpload", basicUrl, headers = headers))
}
}
videoList
} catch (e: IOException) {
videoList
}
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'MonosChinos'
pkgNameSuffix = 'es.monoschinos'
extClass = '.MonosChinos'
extVersionCode = 12
extVersionCode = 13
libVersion = '13'
}

View File

@ -8,7 +8,7 @@ import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.monoschinos.extractors.FembedExtractor
import eu.kanade.tachiyomi.animeextension.es.monoschinos.extractors.OkruExtractor
import eu.kanade.tachiyomi.animeextension.es.monoschinos.extractors.SolidFilesExtractor
import eu.kanade.tachiyomi.animeextension.es.monoschinos.extractors.uploadExtractor
import eu.kanade.tachiyomi.animeextension.es.monoschinos.extractors.UploadExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@ -25,6 +25,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.lang.Exception
class MonosChinos : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -52,7 +53,7 @@ class MonosChinos : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
return SAnime.create().apply {
setUrlWithoutDomain(element.select("a").attr("href"))
title = element.select("a div.series div.seriesdetails h3").text()
thumbnail_url = if(thumbDiv.attr("src").contains("/public/img")){
thumbnail_url = if (thumbDiv.attr("src").contains("/public/img")) {
thumbDiv.attr("data-src")
} else {
thumbDiv.attr("src")
@ -91,7 +92,10 @@ class MonosChinos : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
url.contains("fembed") -> videoList.addAll(FembedExtractor().videosFromUrl(url))
url.contains("ok") -> if (!url.contains("streamcherry")) videoList.addAll(OkruExtractor(client).videosFromUrl(url))
url.contains("solidfiles") -> videoList.addAll(SolidFilesExtractor(client).videosFromUrl(url))
url.contains("uqload") -> videoList.add(uploadExtractor(client).videofromurl(url, headers))
url.contains("uqload") -> {
val video = UploadExtractor(client).videoFromUrl(url, headers)
if (video != null) videoList.add(video)
}
}
}
return videoList
@ -104,21 +108,24 @@ class MonosChinos : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "SolidFiles")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Fembed:720p")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -139,6 +146,7 @@ class MonosChinos : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
else -> GET("$baseUrl/animes?categoria=false&genero=${genreFilter.toUriPart()}&fecha=$yearFilter&letra=$letterFilter&p=$page")
}
}
override fun searchAnimeFromElement(element: Element): SAnime {
return popularAnimeFromElement(element)
}
@ -242,11 +250,16 @@ class MonosChinos : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualities = arrayOf(
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", // Fembed
"Okru:1080p", "Okru:720p", "Okru:480p", "Okru:360p", "Okru:240p", // Okru
"SolidFiles", "Upload" // video servers without resolution
)
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("Fembed:480p", "Fembed:720p", "Fembed:1080p", "SolidFiles", "Okru: full", "Okru: sd", "Okru: low", "Okru: lowest", "Okru: mobile")
entryValues = arrayOf("Fembed:480p", "Fembed:720p", "Fembed:1080p", "SolidFiles", "Okru: full", "Okru: sd", "Okru: low", "Okru: lowest", "Okru: mobile")
entries = qualities
entryValues = qualities
setDefaultValue("Fembed:720p")
summary = "%s"

View File

@ -4,27 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,23 +4,37 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,19 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class SolidFilesExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val videoUrl = data.replace("\"", "")
val quality = "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
document.select("script").forEach { script ->
if (script.data().contains("\"downloadUrl\":")) {
val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
val url = data.replace("\"", "")
val videoUrl = url
val quality = prefix + "SolidFiles"
videoList.add(Video(videoUrl, quality, videoUrl))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -0,0 +1,20 @@
package eu.kanade.tachiyomi.animeextension.es.monoschinos.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class UploadExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, headers: Headers): Video? {
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val basicUrl = document.selectFirst("script:containsData(var player =)").data().substringAfter("sources: [\"").substringBefore("\"],")
return Video(basicUrl, "Uqload", basicUrl, headers = headers)
} catch (e: IOException) {
null
}
}
}

View File

@ -1,21 +0,0 @@
package eu.kanade.tachiyomi.animeextension.es.monoschinos.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
class uploadExtractor(private val client: OkHttpClient) {
fun videofromurl(url: String, headers: Headers): Video {
val document = client.newCall(GET(url)).execute().asJsoup()
val basicUrl = try {
document.selectFirst("script:containsData(var player =)").data().substringAfter("sources: [\"").substringBefore("\"],")
} catch (e: Exception) {
""
}
return if (basicUrl.isNotEmpty()) Video(basicUrl, "video/mp4", basicUrl, headers) else {
Video("not used", "File Deleted", "not used", headers)
}
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'MundoDonghua'
pkgNameSuffix = 'es.mundodonghua'
extClass = '.MundoDonghua'
extVersionCode = 3
extVersionCode = 4
libVersion = '13'
}

View File

@ -23,6 +23,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.lang.Exception
class MundoDonghua : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -113,8 +114,7 @@ class MundoDonghua : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
fetchUrls(unpack!!.first()).map { url ->
if (url.contains("diasfem")) {
var serverUrl = url.replace("diasfem", "embedsito")
var videos = FembedExtractor().videosFromUrl(serverUrl)
videoList.addAll(videos)
FembedExtractor().videosFromUrl(serverUrl).map { vid -> videoList.add(vid) }
}
}
if (unpack!!.first()!!.contains("protea_tab")) {
@ -138,9 +138,7 @@ class MundoDonghua : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
.set("referer", response!!.request!!.url!!.toString())
.set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36")
.build()
ProteaExtractor().videosFromUrl(requestlink, "Protea", headers = headers, baseUrl).forEach {
videoList.add(it)
}
ProteaExtractor().videosFromUrl(requestlink, "Protea", headers = headers).map { vid -> videoList.add(vid) }
}
}
}
@ -155,23 +153,24 @@ class MundoDonghua : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
var quality = preferences.getString("preferred_quality", "Protea:720p")
if (quality == null) quality = preferences.getString("preferred_quality", "Fembed:720p")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Fembed:720p")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -271,11 +270,15 @@ class MundoDonghua : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun latestUpdatesSelector() = popularAnimeSelector()
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualities = arrayOf(
"Protea:1080p", "Protea:720p", "Protea:480p", "Protea:380p", "Protea:360p",
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:380p", "Fembed:360p"
)
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("Protea:1080p", "Protea:720p", "Protea:480p", "Protea:380p", "Protea:360p", "Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:380p", "Fembed:360p")
entryValues = arrayOf("Protea:1080p", "Protea:720p", "Protea:480p", "Protea:380p", "Protea:360p", "Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:380p", "Fembed:360p")
entries = qualities
entryValues = qualities
setDefaultValue("Fembed:720p")
summary = "%s"

View File

@ -4,28 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
var videoApi = url.replace("/v/", "/api/source/")
var json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val prefix = qualityPrefix
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = prefix + "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -15,7 +15,7 @@ import java.io.IOException
class ProteaExtractor() {
private val json: Json by injectLazy()
fun videosFromUrl(url: String, qualityPrefix: String = "Protea", headers: Headers, baseUrl: String): List<Video> {
fun videosFromUrl(url: String, qualityPrefix: String = "Protea", headers: Headers): List<Video> {
val videoList = mutableListOf<Video>()
try {
val document = Jsoup.connect(url).headers(headers.toMap()).ignoreContentType(true).method(Connection.Method.POST).execute()
@ -49,15 +49,4 @@ class ProteaExtractor() {
}
return videoList
}
private fun fixUrl(url: String, baseUrl: String,): String {
if (url.startsWith("http")) return url
if (url.isEmpty()) return ""
val startsWithNoHttp = url.startsWith("//")
if (startsWithNoHttp) return "https:$url"
else {
if (url.startsWith('/')) return baseUrl + url
return "$baseUrl/$url"
}
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'Pelisflix'
pkgNameSuffix = 'es.pelisflix'
extClass = '.PelisflixFactory'
extVersionCode = 1
extVersionCode = 2
libVersion = '13'
}

View File

@ -154,21 +154,24 @@ open class Pelisflix(override val name: String, override val baseUrl: String) :
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "LAT Nupload")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "LAT Nupload")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {

View File

@ -1,5 +1,9 @@
package eu.kanade.tachiyomi.animeextension.es.pelisflix
import android.app.Application
import android.content.SharedPreferences
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.pelisflix.extractors.DoodExtractor
import eu.kanade.tachiyomi.animeextension.es.pelisflix.extractors.FembedExtractor
import eu.kanade.tachiyomi.animeextension.es.pelisflix.extractors.StreamTapeExtractor
@ -18,6 +22,9 @@ import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
class PelisflixFactory : AnimeSourceFactory {
override fun createSources(): List<AnimeSource> = listOf(PelisflixClass(), SeriesflixClass())
@ -30,6 +37,10 @@ class SeriesflixClass : Pelisflix("Seriesflix", "https://seriesflix.video") {
override fun popularAnimeSelector() = "li[id*=post-] > article"
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
override fun popularAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create()
anime.setUrlWithoutDomain(element.select("a").attr("href"))
@ -168,4 +179,48 @@ class SeriesflixClass : Pelisflix("Seriesflix", "https://seriesflix.video") {
AnimeFilter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
fun toUriPart() = vals[state].second
}
override fun List<Video>.sort(): List<Video> {
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Fembed:1080p")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
videoSorted.toList()
} catch (e: IOException) {
this
}
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualities = arrayOf(
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", // Fembed
"DoodStream", "StreamTape" // video servers without resolution
)
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = qualities
entryValues = qualities
setDefaultValue("Fembed:1080p")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
val index = findIndexOfValue(selected)
val entry = entryValues[index] as String
preferences.edit().putString(key, entry).commit()
}
}
screen.addPreference(videoQualityPref)
}
}

View File

@ -7,24 +7,27 @@ import okhttp3.OkHttpClient
import java.io.IOException
class DoodExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, qualityPrefix: String = ""): Video? {
val response = client.newCall(GET(url)).execute()
val doodTld = url.substringAfter("https://dood.").substringBefore("/")
val content = response.body!!.string()
if (!content.contains("'/pass_md5/")) return null
val quality = try { "\\d{3,4}p".toRegex().find(content)!!.value.trim() } catch (e: IOException) { "" }
val md5 = content.substringAfter("'/pass_md5/").substringBefore("',")
val token = md5.substringAfterLast("/")
val randomString = getRandomString()
val expiry = System.currentTimeMillis()
val videoUrlStart = client.newCall(
GET(
"https://dood.$doodTld/pass_md5/$md5",
Headers.headersOf("referer", url)
)
).execute().body!!.string()
val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry"
return Video(url, "$qualityPrefix Doodstream:$quality", videoUrl, headers = doodHeaders(doodTld))
fun videoFromUrl(url: String, quality: String): Video? {
return try {
val response = client.newCall(GET(url)).execute()
val doodTld = url.substringAfter("https://dood.").substringBefore("/")
val content = response.body!!.string()
if (!content.contains("'/pass_md5/")) return null
val md5 = content.substringAfter("'/pass_md5/").substringBefore("',")
val token = md5.substringAfterLast("/")
val randomString = getRandomString()
val expiry = System.currentTimeMillis()
val videoUrlStart = client.newCall(
GET(
"https://dood.$doodTld/pass_md5/$md5",
Headers.headersOf("referer", url)
)
).execute().body!!.string()
val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry"
Video(url, quality, videoUrl, headers = doodHeaders(doodTld))
} catch (e: IOException) {
null
}
}
private fun getRandomString(length: Int = 10): String {

View File

@ -4,27 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
var videoApi = url.replace("/v/", "/api/source/")
var json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = "$qualityPrefix Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,15 +4,21 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class StreamTapeExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String = "StreamTape"): Video? {
val document = client.newCall(GET(url)).execute().asJsoup()
val script = document.select("script:containsData(document.getElementById('robotlink'))")
.firstOrNull()?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '")
?: return null
val videoUrl = "https:" + script.substringBefore("'") +
script.substringAfter("+ ('xcd").substringBefore("'")
return Video(url, quality, videoUrl)
return try {
val linkRegex = "https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}/[a-z]/".toRegex()
val mainUrl = "https://streamtape.com/e/${ url.replace(linkRegex, "") }"
val document = client.newCall(GET(mainUrl)).execute().asJsoup()
val script = document.selectFirst("script:containsData(document.getElementById('robotlink'))")
?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '//")
?: return null
val videoUrl = "https://" + script.substringBefore("'+ ('xcd") + script.substringAfter("+ ('xcd").substringBefore("')")
Video(videoUrl, quality, videoUrl, headers = null)
} catch (i: IOException) {
null
}
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'Pelisplushd'
pkgNameSuffix = 'es.pelisplushd'
extClass = '.Pelisplushd'
extVersionCode = 15
extVersionCode = 16
libVersion = '13'
}

View File

@ -32,6 +32,7 @@ import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.io.IOException
import java.lang.Exception
class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -179,7 +180,7 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val epId = amazonApiJson.toString().substringAfter("\"id\":\"").substringBefore("\"")
val amazonApi = client.newCall(GET("https://www.amazon.com/drive/v1/nodes/$epId/children?resourceVersion=V2&ContentType=JSON&limit=200&sort=%5B%22kind+DESC%22%2C+%22modifiedDate+DESC%22%5D&asset=ALL&tempLink=true&shareId=$shareId")).execute().asJsoup()
val videoUrl = amazonApi.toString().substringAfter("\"FOLDER\":").substringAfter("tempLink\":\"").substringBefore("\"")
videoList.add(Video(videoUrl, "uwu", videoUrl))
videoList.add(Video(videoUrl, "Amazon", videoUrl))
}
}
}
@ -221,21 +222,24 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "StreamTape")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Voex")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -313,12 +317,18 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualities = arrayOf(
"StreamSB:1080p", "StreamSB:720p", "StreamSB:480p", "StreamSB:360p", "StreamSB:240p", "StreamSB:144p", // StreamSB
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", "Fembed:144p", // Fembed
"Streamlare:1080p", "Streamlare:720p", "Streamlare:480p", "Streamlare:360p", "Streamlare:240p", // Streamlare
"StreamTape", "Amazon", "Voex", "DoodStream", "YourUpload"
)
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("StreamSB:360p", "StreamSB:720p", "StreamSB:1080p", "Fembed:480p", "Fembed:720p", "Fembed:1080p", "DoodStream")
entryValues = arrayOf("StreamSB:360p", "StreamSB:720p", "StreamSB:1080p", "Fembed:480p", "Fembed:720p", "Fembed:1080p", "DoodStream")
setDefaultValue("DoodStream")
entries = qualities
entryValues = qualities
setDefaultValue("Voex")
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->

View File

@ -4,26 +4,30 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class DoodExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val response = client.newCall(GET(url)).execute()
val doodTld = url.substringAfter("https://dood.").substringBefore("/")
val content = response.body!!.string()
if (!content.contains("'/pass_md5/")) return null
val md5 = content.substringAfter("'/pass_md5/").substringBefore("',")
val token = md5.substringAfterLast("/")
val randomString = getRandomString()
val expiry = System.currentTimeMillis()
val videoUrlStart = client.newCall(
GET(
"https://dood.$doodTld/pass_md5/$md5",
Headers.headersOf("referer", url)
)
).execute().body!!.string()
val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry"
return Video(url, quality, videoUrl, headers = doodHeaders(doodTld))
return try {
val response = client.newCall(GET(url)).execute()
val doodTld = url.substringAfter("https://dood.").substringBefore("/")
val content = response.body!!.string()
if (!content.contains("'/pass_md5/")) return null
val md5 = content.substringAfter("'/pass_md5/").substringBefore("',")
val token = md5.substringAfterLast("/")
val randomString = getRandomString()
val expiry = System.currentTimeMillis()
val videoUrlStart = client.newCall(
GET(
"https://dood.$doodTld/pass_md5/$md5",
Headers.headersOf("referer", url)
)
).execute().body!!.string()
val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry"
Video(url, quality, videoUrl, headers = doodHeaders(doodTld))
} catch (e: IOException) {
null
}
}
private fun getRandomString(length: Int = 10): String {

View File

@ -4,23 +4,25 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class FembedExtractor {
fun videosFromUrl(url: String): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
return if (json.getBoolean("success")) {
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
val `object` = jsonArray.getJSONObject(i)
val videoUrl = `object`.getString("file")
val quality = "Fembed:" + `object`.getString("label")
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
videoList.reversed()
} else {
emptyList()
videoList
} catch (e: IOException) {
videoList
}
}
}

View File

@ -8,9 +8,9 @@ import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonObject
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class StreamSBExtractor(private val client: OkHttpClient) {
private val hexArray = "0123456789ABCDEF".toCharArray()
private fun bytesToHex(bytes: ByteArray): String {
@ -24,25 +24,31 @@ class StreamSBExtractor(private val client: OkHttpClient) {
return String(hexChars)
}
fun videosFromUrl(url: String, headers: Headers): List<Video> {
val id = url.substringAfter("embed-").substringBefore(".html").substringAfter("/e/")
val bytes = id.toByteArray()
val bytesToHex = bytesToHex(bytes)
val master =
"https://embedsb.com/sources43/566d337678566f743674494a7c7c${bytesToHex}7c7c346b6767586d6934774855537c7c73747265616d7362/6565417268755339773461447c7c346133383438333436313335376136323337373433383634376337633465366534393338373136643732373736343735373237613763376334363733353737303533366236333463353333363534366137633763373337343732363536313664373336327c7c6b586c3163614468645a47617c7c73747265616d7362"
val json = Json.decodeFromString<JsonObject>(
client.newCall(GET(master, headers))
.execute().body!!.string()
)
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
fun videosFromUrl(url: String, headers: Headers, prefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:").forEach {
val quality = "StreamSB:" + it.substringAfter("RESOLUTION=").substringAfter("x")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = headers))
return try {
val sbUrl = url.substringBefore("/e/")
val id = url.substringAfter("/e/").substringBefore(".html")
val bytes = id.toByteArray()
val bytesToHex = bytesToHex(bytes)
val master =
"$sbUrl/sources43/416f794d637048744d4565577c7c${bytesToHex}7c7c776e6c7a365964385a484b767c7c73747265616d7362/656d5a62394f713230524a667c7c373635353537333734623561373634613330353134633631376337633339353037343631363934393335363434333730373633363763376337613737353836323434353534363431343633323533376137633763373337343732363536313664373336327c7c59304b7778506d424c4c32767c7c73747265616d7362"
val json = Json.decodeFromString<JsonObject>(
client.newCall(GET(master, headers))
.execute().body!!.string()
)
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:").split("#EXT-X-STREAM-INF:").forEach {
val quality = prefix + "StreamSB:" + it.substringAfter("RESOLUTION=").substringAfter("x")
.substringBefore(",") + "p"
val videoUrl = it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = headers))
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -4,15 +4,21 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class StreamTapeExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String): Video? {
val document = client.newCall(GET(url)).execute().asJsoup()
val script = document.select("script:containsData(document.getElementById('robotlink'))")
.firstOrNull()?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '")
?: return null
val videoUrl = "https:" + script.substringBefore("'") +
script.substringAfter("+ ('xcd").substringBefore("'")
return Video(url, quality, videoUrl)
fun videoFromUrl(url: String, quality: String = "StreamTape"): Video? {
return try {
val linkRegex = "https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}/[a-z]/".toRegex()
val mainUrl = "https://streamtape.com/e/${ url.replace(linkRegex, "") }"
val document = client.newCall(GET(mainUrl)).execute().asJsoup()
val script = document.selectFirst("script:containsData(document.getElementById('robotlink'))")
?.data()?.substringAfter("document.getElementById('robotlink').innerHTML = '//")
?: return null
val videoUrl = "https://" + script.substringBefore("'+ ('xcd") + script.substringAfter("+ ('xcd").substringBefore("')")
Video(videoUrl, quality, videoUrl, headers = null)
} catch (i: IOException) {
null
}
}
}

View File

@ -10,7 +10,7 @@ import java.io.IOException
class YourUploadExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, headers: Headers): List<Video> {
val videoList = mutableListOf<Video>()
try {
return try {
val document = client.newCall(GET(url)).execute()
if (document.isSuccessful) {
val content = document.asJsoup()
@ -21,8 +21,9 @@ class YourUploadExtractor(private val client: OkHttpClient) {
videoList.add(Video(basicUrl, "YourUpload", basicUrl, headers = headers))
}
}
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'TioanimeH'
pkgNameSuffix = 'es.tioanimeh'
extClass = '.TioanimeHFactory'
extVersionCode = 5
extVersionCode = 6
libVersion = '13'
}

View File

@ -4,9 +4,9 @@ import android.app.Application
import android.content.SharedPreferences
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.tioanimeh.extractors.fembedExtractor
import eu.kanade.tachiyomi.animeextension.es.tioanimeh.extractors.okruExtractor
import eu.kanade.tachiyomi.animeextension.es.tioanimeh.extractors.yourUploadExtractor
import eu.kanade.tachiyomi.animeextension.es.tioanimeh.extractors.FembedExtractor
import eu.kanade.tachiyomi.animeextension.es.tioanimeh.extractors.OkruExtractor
import eu.kanade.tachiyomi.animeextension.es.tioanimeh.extractors.YourUploadExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@ -23,6 +23,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.lang.Exception
open class TioanimeH(override val name: String, override val baseUrl: String) : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -86,17 +87,14 @@ open class TioanimeH(override val name: String, override val baseUrl: String) :
val serverUrl = servers[1].replace("\\/", "/")
when (serverName.lowercase()) {
"fembed" -> {
val videos = fembedExtractor().videosFromUrl(serverUrl)
videoList.addAll(videos)
FembedExtractor().videosFromUrl(serverUrl).map { vid -> videoList.add(vid) }
}
"okru" -> {
val videos = okruExtractor(client).videosFromUrl(serverUrl)
videoList.addAll(videos)
OkruExtractor(client).videosFromUrl(serverUrl).map { vid -> videoList.add(vid) }
}
"yourupload" -> {
val headers = headers.newBuilder().add("referer", "https://www.yourupload.com/").build()
val video = yourUploadExtractor(client).videofromurl(serverUrl, headers = headers)
videoList.add(video)
YourUploadExtractor(client).videoFromUrl(serverUrl, headers = headers).map { vid -> videoList.add(vid) }
}
}
}
@ -111,21 +109,24 @@ open class TioanimeH(override val name: String, override val baseUrl: String) :
override fun videoFromElement(element: Element) = throw Exception("not used")
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString("preferred_quality", "Fembed: 720p")
if (quality != null) {
val newList = mutableListOf<Video>()
var preferred = 0
for (video in this) {
if (video.quality == quality) {
newList.add(preferred, video)
preferred++
} else {
newList.add(video)
}
return try {
val videoSorted = this.sortedWith(
compareBy<Video> { it.quality.replace("[0-9]".toRegex(), "") }.thenByDescending { getNumberFromString(it.quality) }
).toTypedArray()
val userPreferredQuality = preferences.getString("preferred_quality", "Fembed:720p")
val preferredIdx = videoSorted.indexOfFirst { x -> x.quality == userPreferredQuality }
if (preferredIdx != -1) {
videoSorted.drop(preferredIdx + 1)
videoSorted[0] = videoSorted[preferredIdx]
}
return newList
videoSorted.toList()
} catch (e: IOException) {
this
}
return this
}
private fun getNumberFromString(epsStr: String): String {
return epsStr.filter { it.isDigit() }.ifEmpty { "0" }
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
@ -211,11 +212,16 @@ open class TioanimeH(override val name: String, override val baseUrl: String) :
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val qualities = arrayOf(
"Fembed:1080p", "Fembed:720p", "Fembed:480p", "Fembed:360p", "Fembed:240p", "Fembed:144p", // Fembed
"Okru:1080p", "Okru:720p", "Okru:480p", "Okru:360p", "Okru:240p", "Okru:144p", // Okru
"YourUpload" // video servers without resolution
)
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"
title = "Preferred quality"
entries = arrayOf("Fembed:480p", "Fembed:720p", "Fembed:1080p", "SolidFiles", "Okru: full", "Okru: sd", "Okru: low", "Okru: lowest", "Okru: mobile")
entryValues = arrayOf("Fembed:480p", "Fembed:720p", "Fembed:1080p", "SolidFiles", "Okru: full", "Okru: sd", "Okru: low", "Okru: lowest", "Okru: mobile")
entries = qualities
entryValues = qualities
setDefaultValue("Fembed:720p")
summary = "%s"

View File

@ -3,13 +3,14 @@ import eu.kanade.tachiyomi.animesource.model.Video
import org.json.JSONObject
import org.jsoup.Connection
import org.jsoup.Jsoup
import java.io.IOException
class fembedExtractor {
class FembedExtractor {
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
if (json.getBoolean("success")) {
return try {
val videoApi = url.replace("/v/", "/api/source/")
val json = JSONObject(Jsoup.connect(videoApi).ignoreContentType(true).method(Connection.Method.POST).execute().body())
val videoList = mutableListOf<Video>()
val jsonArray = json.getJSONArray("data")
for (i in 0 until jsonArray.length()) {
@ -18,12 +19,9 @@ class fembedExtractor {
val quality = qualityPrefix + "Fembed:" + `object`.getString("label")
videoList.add(Video(videoUrl, quality, videoUrl))
}
return videoList
} else {
val videoUrl = "not used"
val quality = "Video taken down for dmca"
videoList.add(Video(videoUrl, quality, videoUrl))
videoList
} catch (e: IOException) {
videoList
}
return videoList
}
}

View File

@ -0,0 +1,40 @@
package eu.kanade.tachiyomi.animeextension.es.tioanimeh.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import java.io.IOException
class OkruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>()
return try {
val document = client.newCall(GET(url)).execute().asJsoup()
val qualities = listOf(
Pair("full", "1080p"),
Pair("hd", "720p"),
Pair("sd", "480p"),
Pair("low", "360p"),
Pair("lowest", "240p"),
Pair("mobile", "144p")
)
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val quality = try { qualities.find { q -> q.first == it.substringBefore("\\\"") }?.second } catch (e: IOException) { it.substringBefore("\\\"") }
val videoQuality = qualityPrefix + "Okru:" + quality
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl, headers = null))
}
}
videoList
} catch (e: IOException) {
videoList
}
}
}

View File

@ -0,0 +1,29 @@
package eu.kanade.tachiyomi.animeextension.es.tioanimeh.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
import java.io.IOException
class YourUploadExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, headers: Headers): List<Video> {
val videoList = mutableListOf<Video>()
return try {
val document = client.newCall(GET(url)).execute()
if (document.isSuccessful) {
val content = document.asJsoup()
val baseData =
content!!.selectFirst("script:containsData(jwplayerOptions)")!!.data()
if (!baseData.isNullOrEmpty()) {
val basicUrl = baseData.substringAfter("file: '").substringBefore("',")
videoList.add(Video(basicUrl, "YourUpload", basicUrl, headers = headers))
}
}
videoList
} catch (e: IOException) {
videoList
}
}
}

View File

@ -1,25 +0,0 @@
package eu.kanade.tachiyomi.animeextension.es.tioanimeh.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
class okruExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String, qualityPrefix: String = ""): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
val videoList = mutableListOf<Video>()
val videosString = document.select("div[data-options]").attr("data-options")
.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")
videosString.split("{\\\"name\\\":\\\"").reversed().forEach {
val videoUrl = it.substringAfter("url\\\":\\\"")
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
val videoQuality = qualityPrefix + "Okru: " + it.substringBefore("\\\"")
if (videoUrl.startsWith("https://")) {
videoList.add(Video(videoUrl, videoQuality, videoUrl))
}
}
return videoList
}
}

Some files were not shown because too many files have changed in this diff Show More