refactor(global): Adapt to extlib v14 (#2759)

This commit is contained in:
Claudemirovsky
2024-01-16 11:18:47 -03:00
committed by GitHub
parent 0ea1468261
commit 50577ef826
386 changed files with 1122 additions and 2640 deletions

View File

@ -238,10 +238,10 @@ apply from: "$rootDir/common.gradle"
| `pkgNameSuffix` | A unique suffix added to `eu.kanade.tachiyomi.animeextension`. The language and the site name should be enough. Remember your extension code implementation must be placed in this package. |
| `extClass` | Points to the class that implements `AnimeSource`. You can use a relative path starting with a dot (the package name is the base path). This is used to find and instantiate the source(s). |
| `extVersionCode` | The extension version code. This must be a positive integer and incremented with any change to the code. |
| `libVersion` | (Optional, defaults to `13`) The version of the [extensions library](https://github.com/aniyomiorg/extensions-lib) used. |
| `libVersion` | (Optional, defaults to `14`) The version of the [extensions library](https://github.com/aniyomiorg/extensions-lib) used. |
| `containsNsfw` | (Optional, defaults to `false`) Flag to indicate that a source contains NSFW content. |
The extension's version name is generated automatically by concatenating `libVersion` and `extVersionCode`. With the example used above, the version would be `13`.
The extension's version name is generated automatically by concatenating `libVersion` and `extVersionCode`. With the example used above, the version would be `14`.
### Core dependencies
@ -680,7 +680,7 @@ class AnimeSource : AnimeTheme(
return this
}
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
override val client: OkHttpClient = network.client.newBuilder()
.ignoreAllSSLErrors()
.proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress("10.0.2.2", 8080)))
.build()

View File

@ -38,7 +38,6 @@ class BurstCloudExtractor(private val client: OkHttpClient) {
} else {
null
}
}.getOrNull().orEmpty()
}
}

View File

@ -100,7 +100,6 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea
return bits.joinToString("") { Char(it.toInt(index) - offset).toString() }
}
@Serializable
data class CryptoInfo(
@SerialName("ct")

View File

@ -5,7 +5,7 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import kotlinx.serialization.decodeFromString
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.json.Json
import okhttp3.FormBody
import okhttp3.Headers
@ -13,7 +13,6 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
class DailymotionExtractor(private val client: OkHttpClient, private val headers: Headers) {
@ -133,8 +132,4 @@ class DailymotionExtractor(private val client: OkHttpClient, private val headers
videoNameGen = { "$prefix$it" },
)
}
private inline fun <reified T> Response.parseAs(): T {
return use { it.body.string() }.let(json::decodeFromString)
}
}

View File

@ -1,15 +1,15 @@
package eu.kanade.tachiyomi.lib.fastreamextractor
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import okhttp3.FormBody
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.internal.commonEmptyHeaders
import dev.datlag.jsunpacker.JsUnpacker
class FastreamExtractor(private val client: OkHttpClient, private val headers: Headers = commonEmptyHeaders) {
private val videoHeaders by lazy {
@ -35,8 +35,7 @@ class FastreamExtractor(private val client: OkHttpClient, private val headers: H
}.build()
val doc = client.newCall(POST(url, videoHeaders, body = form)).execute().use { it.asJsoup() }
doc.selectFirst("script:containsData(jwplayer):containsData(vplayer)") ?: return emptyList()
}
else {
} else {
firstDoc.selectFirst("script:containsData(jwplayer):containsData(vplayer)") ?: return emptyList()
}

View File

@ -3,11 +3,11 @@ package eu.kanade.tachiyomi.lib.filemoonextractor
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient

View File

@ -1,10 +1,10 @@
package eu.kanade.tachiyomi.lib.fusevideoextractor
import android.util.Base64
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import android.util.Base64
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
@ -28,5 +28,4 @@ class FusevideoExtractor(private val client: OkHttpClient, private val headers:
PlaylistUtils(client, newHeaders).extractFromHls(videoUrl, videoNameGen = { "${prefix}Fusevideo - $it" })
}.getOrDefault(emptyList())
}
}

View File

@ -2,20 +2,19 @@ package eu.kanade.tachiyomi.lib.gogostreamextractor
import android.util.Base64
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.json.Json
import okhttp3.Headers
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import java.lang.Exception
import java.util.Locale
import org.jsoup.nodes.Element
import uy.kohesive.injekt.injectLazy
import java.lang.Exception
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import uy.kohesive.injekt.injectLazy
class GogoStreamExtractor(private val client: OkHttpClient) {
private val json: Json by injectLazy()

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.lib.gogostreamextractor
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable

View File

@ -7,8 +7,8 @@ import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.internal.commonEmptyRequestBody
@ -37,7 +37,7 @@ class GoogleDriveExtractor(private val client: OkHttpClient, private val headers
}.build()
val docResp = noRedirectClient.newCall(
GET(itemUrl, headers = docHeaders)
GET(itemUrl, headers = docHeaders),
).execute()
if (docResp.isRedirect) {
@ -60,7 +60,7 @@ class GoogleDriveExtractor(private val client: OkHttpClient, private val headers
}.build()
val newUrl = noRedirectClient.newCall(
POST(downloadUrl, headers = postHeaders, body = commonEmptyRequestBody)
POST(downloadUrl, headers = postHeaders, body = commonEmptyRequestBody),
).execute().use { it.headers["location"] ?: downloadUrl }
return videoFromRedirect(newUrl, videoName, itemSize, cookieJar)
@ -70,7 +70,7 @@ class GoogleDriveExtractor(private val client: OkHttpClient, private val headers
downloadUrl: String,
videoName: String,
itemSize: String,
cookieJar: GDriveCookieJar
cookieJar: GDriveCookieJar,
): List<Video> {
var newUrl = downloadUrl
@ -82,7 +82,7 @@ class GoogleDriveExtractor(private val client: OkHttpClient, private val headers
}.build()
var newResp = noRedirectClient.newCall(
GET(newUrl, headers = newHeaders)
GET(newUrl, headers = newHeaders),
).execute()
var redirectCounter = 1
@ -101,7 +101,7 @@ class GoogleDriveExtractor(private val client: OkHttpClient, private val headers
}.build()
newResp = noRedirectClient.newCall(
GET(newUrl, headers = newHeaders)
GET(newUrl, headers = newHeaders),
).execute()
redirectCounter += 1
}
@ -120,8 +120,8 @@ class GoogleDriveExtractor(private val client: OkHttpClient, private val headers
videoUrl.toString(),
videoName + itemSize,
videoUrl.toString(),
headers = videoHeaders
)
headers = videoHeaders,
),
)
}

View File

@ -2,6 +2,8 @@ package eu.kanade.tachiyomi.lib.javcoverfetcher
import android.content.SharedPreferences
import android.util.Log
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.POST
@ -13,13 +15,11 @@ import okhttp3.internal.commonEmptyHeaders
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
object JavCoverFetcher {
private val CLIENT by lazy {
Injekt.get<NetworkHelper>().cloudflareClient.newBuilder()
Injekt.get<NetworkHelper>().client.newBuilder()
.addInterceptor(::amazonAgeVerifyIntercept)
.build()
}
@ -149,5 +149,4 @@ object JavCoverFetcher {
val SharedPreferences.fetchHDCovers
get() = getBoolean("JavCoverFetcherPref", false)
}

View File

@ -24,7 +24,7 @@ import uy.kohesive.injekt.injectLazy
class MegaCloudExtractor(
private val client: OkHttpClient,
private val headers: Headers,
private val preferences: SharedPreferences
private val preferences: SharedPreferences,
) {
private val json: Json by injectLazy()
@ -59,7 +59,7 @@ class MegaCloudExtractor(
shouldUpdateKey = false
}
json.decodeFromString<List<List<Int>>>(
preferences.getString(PREF_KEY_KEY + type, PREF_KEY_DEFAULT)!!
preferences.getString(PREF_KEY_KEY + type, PREF_KEY_DEFAULT)!!,
)
}
@ -79,8 +79,8 @@ class MegaCloudExtractor(
val var1 = match.groupValues[1]
val var2 = match.groupValues[2]
val regexVar1 = Regex(",${var1}=((?:0x)?([0-9a-fA-F]+))")
val regexVar2 = Regex(",${var2}=((?:0x)?([0-9a-fA-F]+))")
val regexVar1 = Regex(",$var1=((?:0x)?([0-9a-fA-F]+))")
val regexVar2 = Regex(",$var2=((?:0x)?([0-9a-fA-F]+))")
val matchVar1 = regexVar1.find(script)?.groupValues?.get(1)?.removePrefix("0x")
val matchVar2 = regexVar2.find(script)?.groupValues?.get(1)?.removePrefix("0x")
@ -135,7 +135,7 @@ class MegaCloudExtractor(
masterUrl,
videoNameGen = { "$name - $it - $type" },
subtitleList = subs2,
referer = "https://${url.toHttpUrl().host}/"
referer = "https://${url.toHttpUrl().host}/",
)
}
@ -159,7 +159,6 @@ class MegaCloudExtractor(
return VideoDto(decrypted, data.tracks)
}
@Serializable
data class VideoDto(
val sources: List<VideoLink>,

View File

@ -15,7 +15,7 @@ class MixDropExtractor(private val client: OkHttpClient) {
lang: String = "",
prefix: String = "",
externalSubs: List<Track> = emptyList(),
referer: String = DEFAULT_REFERER
referer: String = DEFAULT_REFERER,
): List<Video> {
val headers = Headers.headersOf("Referer", referer)
val doc = client.newCall(GET(url, headers)).execute().use { it.asJsoup() }

View File

@ -1,11 +1,11 @@
package eu.kanade.tachiyomi.lib.mp4uploadextractor
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
import dev.datlag.jsunpacker.JsUnpacker
class Mp4uploadExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String, headers: Headers, prefix: String = "", suffix: String = ""): List<Video> {

View File

@ -1,9 +1,9 @@
package eu.kanade.tachiyomi.lib.okruextractor
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import okhttp3.OkHttpClient
class OkruExtractor(private val client: OkHttpClient) {
@ -37,7 +37,6 @@ class OkruExtractor(private val client: OkHttpClient) {
"ondemandDash" in videoString -> {
val playlistUrl = videoString.extractLink("ondemandDash")
playlistUtils.extractFromDash(playlistUrl, videoNameGen = { it -> "Okru:$it".addPrefix(prefix) })
}
else -> videosFromJson(videoString, prefix, fixQualities)
}
@ -53,7 +52,6 @@ class OkruExtractor(private val client: OkHttpClient) {
.substringBefore("\\\"")
.replace("\\\\u0026", "&")
private fun videosFromJson(videoString: String, prefix: String = "", fixQualities: Boolean = true): List<Video> {
val arrayData = videoString.substringAfter("\\\"videos\\\":[{\\\"name\\\":\\\"")
.substringBefore("]")

View File

@ -43,7 +43,7 @@ class PlaylistUtils(private val client: OkHttpClient, private val headers: Heade
{ _, _, _ -> videoHeaders },
videoNameGen,
subtitleList,
audioList
audioList,
)
}
@ -90,8 +90,13 @@ class PlaylistUtils(private val client: OkHttpClient, private val headers: Heade
if (PLAYLIST_SEPARATOR !in masterPlaylist) {
return listOf(
Video(
playlistUrl, videoNameGen("Video"), playlistUrl, headers = masterHeaders, subtitleTracks = subtitleList, audioTracks = audioList
)
playlistUrl,
videoNameGen("Video"),
playlistUrl,
headers = masterHeaders,
subtitleTracks = subtitleList,
audioTracks = audioList,
),
)
}
@ -108,7 +113,7 @@ class PlaylistUtils(private val client: OkHttpClient, private val headers: Heade
val subtitleTracks = subtitleList + SUBTITLE_REGEX.findAll(masterPlaylist).mapNotNull {
Track(
getAbsoluteUrl(it.groupValues[2], playlistUrl, masterUrlBasePath) ?: return@mapNotNull null,
it.groupValues[1]
it.groupValues[1],
)
}.toList()
@ -116,7 +121,7 @@ class PlaylistUtils(private val client: OkHttpClient, private val headers: Heade
val audioTracks = audioList + AUDIO_REGEX.findAll(masterPlaylist).mapNotNull {
Track(
getAbsoluteUrl(it.groupValues[2], playlistUrl, masterUrlBasePath) ?: return@mapNotNull null,
it.groupValues[1]
it.groupValues[1],
)
}.toList()
@ -130,12 +135,13 @@ class PlaylistUtils(private val client: OkHttpClient, private val headers: Heade
getAbsoluteUrl(url, playlistUrl, masterUrlBasePath)
} ?: return@mapNotNull null
Video(
videoUrl, videoNameGen(resolution), videoUrl,
videoUrl,
videoNameGen(resolution),
videoUrl,
headers = videoHeadersGen(headers, referer, videoUrl),
subtitleTracks = subtitleTracks, audioTracks = audioTracks
subtitleTracks = subtitleTracks,
audioTracks = audioTracks,
)
}
}
@ -195,7 +201,7 @@ class PlaylistUtils(private val client: OkHttpClient, private val headers: Heade
{ _, _ -> mpdHeaders },
{ _, _, _ -> videoHeaders },
subtitleList,
audioList
audioList,
)
}
@ -242,7 +248,7 @@ class PlaylistUtils(private val client: OkHttpClient, private val headers: Heade
mpdHeadersGen,
videoHeadersGen,
subtitleList,
audioList
audioList,
)
}

View File

@ -36,5 +36,4 @@ class SibnetExtractor(private val client: OkHttpClient) {
return videoList
}
}

View File

@ -12,8 +12,8 @@ class StreamHubExtractor(private val client: OkHttpClient) {
val document = client.newCall(GET(url)).execute().use { it.body.string() }
val id = REGEX_ID.find(document)?.groupValues?.get(1)
val sub = REGEX_SUB.find(document)?.groupValues?.get(1)
val masterUrl = "https://${sub}.streamhub.ink/hls/,${id},.urlset/master.m3u8"
return playlistUtils.extractFromHls(masterUrl, videoNameGen = { "${prefix}StreamHub - (${it})" })
val masterUrl = "https://$sub.streamhub.ink/hls/,$id,.urlset/master.m3u8"
return playlistUtils.extractFromHls(masterUrl, videoNameGen = { "${prefix}StreamHub - ($it)" })
}
companion object {

View File

@ -21,7 +21,9 @@ class StreamWishExtractor(private val client: OkHttpClient, private val headers:
?.let { script ->
if (script.contains("eval(function(p,a,c")) {
JsUnpacker.unpackAndCombine(script)
} else script
} else {
script
}
}
val masterUrl = scriptBody

View File

@ -5,9 +5,7 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.internal.commonEmptyHeaders
class UpstreamExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String, prefix: String = ""): List<Video> =

View File

@ -16,7 +16,7 @@ class VidoExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
val document = client.newCall(GET(url)).execute().use { it.body.string() }
val id = REGEX_ID.find(document)?.groupValues?.get(1)
val masterUrl = "$VIDO_URL/hls/${id}/master.m3u8"
return playlistUtils.extractFromHls(masterUrl, videoNameGen = { "${prefix}Vido - (${it})" })
val masterUrl = "$VIDO_URL/hls/$id/master.m3u8"
return playlistUtils.extractFromHls(masterUrl, videoNameGen = { "${prefix}Vido - ($it)" })
}
}

View File

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.lib.vkextractor
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
class VkExtractor(private val client: OkHttpClient, private val headers: Headers) {

View File

@ -4,6 +4,7 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
@ -16,7 +17,6 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
class CDAExtractor(private val client: OkHttpClient, private val headers: Headers, private val referer: String) {
@ -102,9 +102,4 @@ class CDAExtractor(private val client: OkHttpClient, private val headers: Header
val resp: String,
)
}
private inline fun <reified T> Response.parseAs(transform: (String) -> String = { it }): T {
val responseBody = use { transform(it.body.string()) }
return json.decodeFromString(responseBody)
}
}

View File

@ -5,12 +5,12 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
class StreamPlayExtractor(private val client: OkHttpClient, private val headers: Headers) {
@ -68,9 +68,4 @@ class StreamPlayExtractor(private val client: OkHttpClient, private val headers:
val label: String,
)
}
private inline fun <reified T> Response.parseAs(transform: (String) -> String = { it }): T {
val responseBody = use { transform(it.body.string()) }
return json.decodeFromString(responseBody)
}
}

View File

@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.lib.mp4uploadextractor.Mp4uploadExtractor
import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
import eu.kanade.tachiyomi.multisrc.animestream.AnimeStream
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.Response
class LMAnime : AnimeStream(
@ -27,11 +28,11 @@ class LMAnime : AnimeStream(
.filter { element ->
val text = element.text()
allowed.any { it in text }
}.parallelMap {
}.parallelCatchingFlatMapBlocking {
val language = it.text().substringBefore(" ")
val url = getHosterUrl(it)
getVideoList(url, language)
}.flatten().ifEmpty { throw Exception("Empty video list!") }
}
}
private val streamwishExtractor by lazy { StreamWishExtractor(client, headers) }

View File

@ -15,11 +15,11 @@ import eu.kanade.tachiyomi.lib.vudeoextractor.VudeoExtractor
import eu.kanade.tachiyomi.multisrc.datalifeengine.DataLifeEngine
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parallelCatchingFlatMap
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import java.lang.Exception
class FrenchAnime : DataLifeEngine(
@ -87,8 +87,7 @@ class FrenchAnime : DataLifeEngine(
override fun episodeFromElement(element: Element): SEpisode = throw Exception("not used")
// ============================ Video Links =============================
override fun fetchVideoList(episode: SEpisode): Observable<List<Video>> {
override suspend fun getVideoList(episode: SEpisode): List<Video> {
val list = episode.url.split(",").filter { it.isNotBlank() }.parallelCatchingFlatMap {
with(it) {
when {
@ -107,8 +106,7 @@ class FrenchAnime : DataLifeEngine(
}
}
}.sort()
if (list.isEmpty()) throw Exception("no player found")
return Observable.just(list)
return list
}
override fun videoFromElement(element: Element): Video = throw Exception("Not Used")

View File

@ -12,11 +12,11 @@ import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.lib.vudeoextractor.VudeoExtractor
import eu.kanade.tachiyomi.multisrc.datalifeengine.DataLifeEngine
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.parallelCatchingFlatMap
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
class Wiflix : DataLifeEngine(
"Wiflix",
@ -74,8 +74,7 @@ class Wiflix : DataLifeEngine(
}
// ============================ Video Links =============================
override fun fetchVideoList(episode: SEpisode): Observable<List<Video>> {
override suspend fun getVideoList(episode: SEpisode): List<Video> {
val list = episode.url.split(",").filter { it.isNotBlank() }.parallelCatchingFlatMap {
with(it) {
when {
@ -93,7 +92,7 @@ class Wiflix : DataLifeEngine(
}
}.sort()
if (list.isEmpty()) throw Exception("no player found")
return Observable.just(list)
return list
}
override fun videoFromElement(element: Element): Video = throw Exception("Not Used")

View File

@ -26,11 +26,11 @@ class AnimeOnlineNinja : DooPlay(
) {
override val client by lazy {
if (preferences.getBoolean(PREF_VRF_INTERCEPT_KEY, PREF_VRF_INTERCEPT_DEFAULT)) {
network.cloudflareClient.newBuilder()
network.client.newBuilder()
.addInterceptor(VrfInterceptor())
.build()
} else {
network.cloudflareClient
network.client
}
}

View File

@ -13,7 +13,6 @@ class AnimePlayer : DooPlay(
"AnimePlayer",
"https://animeplayer.com.br",
) {
override val client = network.cloudflareClient
// ============================== Popular ===============================
override fun popularAnimeSelector() = "div#featured-titles article div.poster"

View File

@ -13,10 +13,7 @@ import eu.kanade.tachiyomi.multisrc.dooplay.DooPlay
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.FormBody
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Response
@ -60,7 +57,7 @@ class AnimesOnline : DooPlay(
override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
val players = document.select("ul#playeroptionsul li")
return players.parallelMap(::getPlayerVideos).flatten()
return players.parallelCatchingFlatMapBlocking(::getPlayerVideos)
}
override val prefQualityValues = arrayOf("360p", "480p", "720p", "1080p")
@ -138,11 +135,6 @@ class AnimesOnline : DooPlay(
}
// ============================= Utilities ==============================
private inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
override fun getRealAnimeDoc(document: Document): Document {
if (!document.location().contains("/episodio/")) return document

View File

@ -27,7 +27,7 @@ class AnimesHouse : DooPlay(
// ============================== Popular ===============================
// This source does not have a "popular" animes page, so we're going to
// use latest updates page instead.
override fun fetchPopularAnime(page: Int) = fetchLatestUpdates(page)
override suspend fun getPopularAnime(page: Int) = getLatestUpdates(page)
// =============================== Latest ===============================
override fun latestUpdatesNextPageSelector(): String = "div.resppages > a > span.icon-chevron-right"

View File

@ -11,11 +11,9 @@ import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
import eu.kanade.tachiyomi.multisrc.dooplay.DooPlay
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
@ -49,21 +47,19 @@ class Cinemathek : DooPlay(
override fun videoListParse(response: Response): List<Video> {
val players = response.use { it.asJsoup().select("ul#playeroptionsul li") }
val hosterSelection = preferences.getStringSet(PREF_HOSTER_SELECTION_KEY, PREF_HOSTER_SELECTION_DEFAULT)!!
return players.parallelMapNotNull { player ->
runCatching {
val url = getPlayerUrl(player).ifEmpty { return@parallelMapNotNull null }
return players.parallelCatchingFlatMapBlocking { player ->
val url = getPlayerUrl(player).takeUnless(String::isEmpty)!!
getPlayerVideos(url, hosterSelection)
}.getOrNull()
}.flatten()
}
}
private fun getPlayerUrl(player: Element): String {
private suspend fun getPlayerUrl(player: Element): String {
val type = player.attr("data-type")
val id = player.attr("data-post")
val num = player.attr("data-nume")
if (num == "trailer") return ""
return client.newCall(GET("$baseUrl/wp-json/dooplayer/v2/$id/$type/$num"))
.execute()
.await()
.use { it.body.string() }
.substringAfter("\"embed_url\":\"")
.substringBefore("\",")
@ -76,7 +72,7 @@ class Cinemathek : DooPlay(
private val streamtapeExtractor by lazy { StreamTapeExtractor(client) }
private val streamwishExtractor by lazy { StreamWishExtractor(client, headers) }
private fun getPlayerVideos(url: String, hosterSelection: Set<String>): List<Video>? {
private fun getPlayerVideos(url: String, hosterSelection: Set<String>): List<Video> {
return when {
url.contains("https://streamlare.com") && hosterSelection.contains("slare") -> {
streamlareExtractor.videosFromUrl(url)
@ -95,7 +91,7 @@ class Cinemathek : DooPlay(
streamwishExtractor.videosFromUrl(url)
}
else -> null
}
}.orEmpty()
}
// ============================== Settings ==============================
@ -163,11 +159,6 @@ class Cinemathek : DooPlay(
).reversed()
}
private inline fun <A, B> Iterable<A>.parallelMapNotNull(crossinline f: suspend (A) -> B?): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll().filterNotNull()
}
companion object {
private const val PREF_HOSTER_KEY = "preferred_hoster"
private const val PREF_HOSTER_TITLE = "Standard-Hoster"

View File

@ -10,11 +10,9 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.bloggerextractor.BloggerExtractor
import eu.kanade.tachiyomi.multisrc.dooplay.DooPlay
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.Response
import org.jsoup.nodes.Element
@ -76,10 +74,10 @@ class GoAnimes : DooPlay(
override fun videoListParse(response: Response): List<Video> {
val document = response.use { it.asJsoup() }
val players = document.select("ul#playeroptionsul li")
return players.parallelCatchingFlatMap(::getPlayerVideos)
return players.parallelCatchingFlatMapBlocking(::getPlayerVideos)
}
private fun getPlayerVideos(player: Element): List<Video> {
private suspend fun getPlayerVideos(player: Element): List<Video> {
val url = getPlayerUrl(player)
return when {
"player5.goanimes.net" in url -> goanimesExtractor.videosFromUrl(url)
@ -88,7 +86,7 @@ class GoAnimes : DooPlay(
.set("referer", url)
.build()
val script = client.newCall(GET(url, headers)).execute()
val script = client.newCall(GET(url, headers)).await()
.use { it.body.string() }
.let { JsDecoder.decodeScript(it, false) }
@ -111,7 +109,7 @@ class GoAnimes : DooPlay(
}
}
listOf("/bloggerjwplayer", "/m3u8", "/multivideo").any { it in url } -> {
val script = client.newCall(GET(url)).execute()
val script = client.newCall(GET(url)).await()
.use { it.body.string() }
.let(JsDecoder::decodeScript)
when {
@ -132,12 +130,12 @@ class GoAnimes : DooPlay(
}
}
private fun getPlayerUrl(player: Element): String {
private suspend fun getPlayerUrl(player: Element): String {
val type = player.attr("data-type")
val id = player.attr("data-post")
val num = player.attr("data-nume")
val url = client.newCall(GET("$baseUrl/wp-json/dooplayer/v2/$id/$type/$num"))
.execute()
.await()
.use { it.body.string() }
.substringAfter("\"embed_url\":\"")
.substringBefore("\",")
@ -145,24 +143,14 @@ class GoAnimes : DooPlay(
return when {
"/protetorlinks/" in url -> {
val link = client.newCall(GET(url)).execute()
val link = client.newCall(GET(url)).await()
.use { it.asJsoup() }
.selectFirst("a[href]")!!.attr("href")
client.newCall(GET(link)).execute()
client.newCall(GET(link)).await()
.use(linkfunBypasser::getIframeUrl)
}
else -> url
}
}
// ============================= Utilities ==============================
private inline fun <A, B> Iterable<A>.parallelCatchingFlatMap(crossinline f: suspend (A) -> Iterable<B>): List<B> =
runBlocking {
map {
async(Dispatchers.Default) {
runCatching { f(it) }.getOrElse { emptyList() }
}
}.awaitAll().flatten()
}
}

View File

@ -35,8 +35,6 @@ class Kinoking : DooPlay(
override val videoSortPrefKey = PREF_HOSTER_KEY
override val videoSortPrefDefault = PREF_HOSTER_DEFAULT
override val client = network.cloudflareClient
// ============================== Popular ===============================
override fun popularAnimeSelector(): String = "div#featured-titles div.poster"

View File

@ -30,7 +30,6 @@ class Multimovies : DooPlay(
"Multimovies",
"https://multimovies.live",
) {
override val client = network.cloudflareClient
private val defaultBaseUrl = "https://multimovies.live"

View File

@ -689,10 +689,7 @@ import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
@ -733,8 +730,7 @@ class AutoEmbedExtractor(private val client: OkHttpClient) {
}
// Get video servers from containers
val serverList = containerList.parallelMap { container ->
runCatching {
val serverList = containerList.parallelCatchingFlatMapBlocking { container ->
when (container.name) {
"2embed" -> {
getTwoEmbedServers(container.url, headers = headers)
@ -743,16 +739,14 @@ class AutoEmbedExtractor(private val client: OkHttpClient) {
getGomoStreamServers(container.url, headers = headers)
}
else -> null
}.orEmpty()
}
}.getOrNull() ?: emptyList()
}.flatten()
val videoHeaders = headers.newBuilder()
.add("Referer", "https://www.2embed.to/")
.build()
return serverList.parallelMap { server ->
runCatching {
return serverList.parallelCatchingFlatMapBlocking { server ->
val prefix = server.name
val videoUrl = server.url
@ -775,9 +769,8 @@ class AutoEmbedExtractor(private val client: OkHttpClient) {
?.let(::listOf)
}
else -> null
}.orEmpty()
}
}.getOrNull() ?: emptyList()
}.flatten()
}
data class Server(
@ -892,10 +885,4 @@ class AutoEmbedExtractor(private val client: OkHttpClient) {
}
}.getOrNull()
}
// From Dopebox
private fun <A, B> Iterable<A>.parallelMap(f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
}

View File

@ -3,12 +3,11 @@ package eu.kanade.tachiyomi.animeextension.pt.pifansubs.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
class BlembedExtractor(private val client: OkHttpClient, private val headers: Headers) {
@ -32,10 +31,6 @@ class BlembedExtractor(private val client: OkHttpClient, private val headers: He
return res.sources.map { Video(it.file, "Blembed - ${it.label}", it.file, headers) }
}
private inline fun <reified T> Response.parseAs(): T = use {
json.decodeFromStream(it.body.byteStream())
}
}
@Serializable

View File

@ -3,11 +3,9 @@ package eu.kanade.tachiyomi.animeextension.pt.pobreflix.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import okhttp3.FormBody
@ -26,7 +24,7 @@ class SuperFlixExtractor(
fun videosFromUrl(url: String): List<Video> {
val links = linksFromUrl(url)
val fixedLinks = links.parallelCatchingFlatMap {
val fixedLinks = links.parallelCatchingFlatMapBlocking {
val (language, linkUrl) = it
when {
linkUrl.contains("?vid=") -> linksFromPlayer(linkUrl, language)
@ -34,10 +32,10 @@ class SuperFlixExtractor(
}
}
return fixedLinks.parallelCatchingFlatMap { genericExtractor(it.second, it.first) }
return fixedLinks.parallelCatchingFlatMapBlocking { genericExtractor(it.second, it.first) }
}
private fun linksFromPlayer(url: String, language: String): List<Pair<String, String>> {
private suspend fun linksFromPlayer(url: String, language: String): List<Pair<String, String>> {
val httpUrl = url.toHttpUrl()
val id = httpUrl.queryParameter("vid")!!
val headers = defaultHeaders.newBuilder()
@ -45,7 +43,7 @@ class SuperFlixExtractor(
.set("origin", API_DOMAIN)
.build()
val doc = client.newCall(GET(url, headers)).execute().use { it.asJsoup() }
val doc = client.newCall(GET(url, headers)).await().use { it.asJsoup() }
val baseUrl = "https://" + httpUrl.host
val apiUrl = "$baseUrl/ajax_sources.php"
@ -66,7 +64,7 @@ class SuperFlixExtractor(
.add("ord", order)
.build()
val req = client.newCall(POST(apiUrl, apiHeaders, formBody)).execute()
val req = client.newCall(POST(apiUrl, apiHeaders, formBody)).await()
.use { it.body.string() }
runCatching {
@ -125,15 +123,6 @@ class SuperFlixExtractor(
@Serializable
data class DataDto(val video_url: String? = null)
private inline fun <A, B> Iterable<A>.parallelCatchingFlatMap(crossinline f: suspend (A) -> Iterable<B>): List<B> =
runBlocking {
map {
async(Dispatchers.Default) {
runCatching { f(it) }.getOrElse { emptyList() }
}
}.awaitAll().flatten()
}
}
private const val API_DOMAIN = "https://superflixapi.top"

View File

@ -16,7 +16,6 @@ import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import org.jsoup.nodes.Element
import rx.Observable
import uy.kohesive.injekt.injectLazy
class UniqueStream : DooPlay(
@ -24,7 +23,6 @@ class UniqueStream : DooPlay(
"UniqueStream",
"https://uniquestream.net",
) {
override val client = network.cloudflareClient
private val json: Json by injectLazy()
@ -183,7 +181,7 @@ class UniqueStream : DooPlay(
// ============================ Video Links =============================
override fun fetchVideoList(episode: SEpisode): Observable<List<Video>> {
override suspend fun getVideoList(episode: SEpisode): List<Video> {
val videoList = mutableListOf<Video>()
val document = client.newCall(
GET(baseUrl + episode.url, headers = headers),
@ -290,7 +288,7 @@ class UniqueStream : DooPlay(
require(videoList.isNotEmpty()) { "Failed to fetch videos" }
return Observable.just(videoList.sort())
return videoList.sort()
}
// ============================== Settings ==============================

View File

@ -21,11 +21,10 @@ import eu.kanade.tachiyomi.multisrc.animestream.AnimeStreamFilters.StudioFilter
import eu.kanade.tachiyomi.multisrc.animestream.AnimeStreamFilters.SubFilter
import eu.kanade.tachiyomi.multisrc.animestream.AnimeStreamFilters.TypeFilter
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
@ -34,7 +33,6 @@ import okhttp3.Response
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat
@ -48,8 +46,6 @@ abstract class AnimeStream(
override val supportsLatest = true
override val client = network.cloudflareClient
protected open val preferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
@ -81,9 +77,9 @@ abstract class AnimeStream(
protected open val animeListUrl = "$baseUrl/anime"
// ============================== Popular ===============================
override fun fetchPopularAnime(page: Int): Observable<AnimesPage> {
override suspend fun getPopularAnime(page: Int): AnimesPage {
fetchFilterList()
return super.fetchPopularAnime(page)
return super.getPopularAnime(page)
}
override fun popularAnimeRequest(page: Int) = GET("$animeListUrl/?page=$page&order=popular")
@ -95,9 +91,9 @@ abstract class AnimeStream(
override fun popularAnimeNextPageSelector(): String? = searchAnimeNextPageSelector()
// =============================== Latest ===============================
override fun fetchLatestUpdates(page: Int): Observable<AnimesPage> {
override suspend fun getLatestUpdates(page: Int): AnimesPage {
fetchFilterList()
return super.fetchLatestUpdates(page)
return super.getLatestUpdates(page)
}
override fun latestUpdatesRequest(page: Int) = GET("$animeListUrl/?page=$page&order=update")
@ -109,14 +105,14 @@ abstract class AnimeStream(
override fun latestUpdatesNextPageSelector(): String? = searchAnimeNextPageSelector()
// =============================== Search ===============================
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage {
return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
val path = query.removePrefix(PREFIX_SEARCH)
client.newCall(GET("$baseUrl/$path"))
.asObservableSuccess()
.map(::searchAnimeByPathParse)
.awaitSuccess()
.use(::searchAnimeByPathParse)
} else {
super.fetchSearchAnime(page, query, filters)
super.getSearchAnime(page, query, filters)
}
}
@ -320,13 +316,11 @@ abstract class AnimeStream(
override fun videoListParse(response: Response): List<Video> {
val items = response.use { it.asJsoup() }.select(videoListSelector())
return items.parallelMap { element ->
runCatching {
return items.parallelCatchingFlatMapBlocking { element ->
val name = element.text()
val url = getHosterUrl(element)
getVideoList(url, name)
}.onFailure { it.printStackTrace() }.getOrElse { emptyList() }
}.flatten()
}
}
protected open fun getHosterUrl(element: Element): String {
@ -422,11 +416,6 @@ abstract class AnimeStream(
} ?: 0L
}
protected inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
/**
* Tries to get the image url via various possible attributes.
* Taken from Tachiyomi's Madara multisrc.

View File

@ -12,21 +12,15 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -38,8 +32,6 @@ abstract class DataLifeEngine(
override val supportsLatest = false
override val client: OkHttpClient = network.cloudflareClient
private val preferences by lazy { Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) }
// ============================== Popular ===============================
@ -139,10 +131,10 @@ abstract class DataLifeEngine(
}
// =========================== Anime Details ============================
override fun fetchAnimeDetails(anime: SAnime): Observable<SAnime> {
override suspend fun getAnimeDetails(anime: SAnime): SAnime {
return client.newCall(animeDetailsRequest(anime))
.asObservableSuccess()
.map { response ->
.awaitSuccess()
.use { response ->
animeDetailsParse(response, anime).apply { initialized = true }
}
}
@ -183,11 +175,6 @@ abstract class DataLifeEngine(
).reversed()
}
inline fun <A, B> Iterable<A>.parallelCatchingFlatMap(crossinline f: suspend (A) -> Iterable<B>): List<B> =
runBlocking {
map { async(Dispatchers.Default) { runCatching { f(it) }.getOrElse { emptyList() } } }.awaitAll().flatten()
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val videoQualityPref = ListPreference(screen.context).apply {
key = "preferred_quality"

View File

@ -13,14 +13,12 @@ import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.lang.Exception
@ -39,8 +37,6 @@ abstract class DooPlay(
override val supportsLatest = true
override val client: OkHttpClient = network.client
override fun headersBuilder() = super.headersBuilder().add("Referer", baseUrl)
protected open val preferences: SharedPreferences by lazy {
@ -185,16 +181,14 @@ abstract class DooPlay(
return AnimesPage(animes, hasNextPage)
}
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage {
return if (query.startsWith(PREFIX_SEARCH)) {
val path = query.removePrefix(PREFIX_SEARCH)
client.newCall(GET("$baseUrl/$path", headers))
.asObservableSuccess()
.map { response ->
searchAnimeByPathParse(response)
}
.awaitSuccess()
.use(::searchAnimeByPathParse)
} else {
super.fetchSearchAnime(page, query, filters)
super.getSearchAnime(page, query, filters)
}
}

View File

@ -17,14 +17,10 @@ import eu.kanade.tachiyomi.multisrc.dopeflix.dto.VideoDto
import eu.kanade.tachiyomi.multisrc.dopeflix.extractors.DopeFlixExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -45,8 +41,6 @@ abstract class DopeFlix(
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
@ -191,7 +185,7 @@ abstract class DopeFlix(
val doc = response.asJsoup()
val episodeReferer = Headers.headersOf("Referer", response.request.header("referer")!!)
return doc.select("ul.fss-list a.btn-play")
.parallelMap { server ->
.parallelCatchingFlatMapBlocking { server ->
val name = server.selectFirst("span")!!.text()
val id = server.attr("data-id")
val url = "$baseUrl/ajax/sources/$id"
@ -199,7 +193,6 @@ abstract class DopeFlix(
.use { it.body.string() }
val sourceUrl = reqBody.substringAfter("\"link\":\"")
.substringBefore("\"")
runCatching {
when {
"DoodStream" in name ->
DoodExtractor(client).videoFromUrl(sourceUrl)
@ -209,9 +202,8 @@ abstract class DopeFlix(
getVideosFromServer(video, name)
}
else -> null
}.orEmpty()
}
}.getOrNull() ?: emptyList()
}.flatten()
}
private fun getVideosFromServer(video: VideoDto, name: String): List<Video> {
@ -343,11 +335,6 @@ abstract class DopeFlix(
}
// ============================= Utilities ==============================
private inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
private fun HttpUrl.Builder.addIfNotBlank(query: String, value: String): HttpUrl.Builder {
if (value.isNotBlank()) {
addQueryParameter(query, value)

View File

@ -16,13 +16,14 @@ import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.multisrc.zorotheme.dto.HtmlResponse
import eu.kanade.tachiyomi.multisrc.zorotheme.dto.SourcesResponse
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.util.parallelCatchingFlatMap
import eu.kanade.tachiyomi.util.parallelMapNotNull
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.json.Json
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -39,8 +40,6 @@ abstract class ZoroTheme(
override val supportsLatest = true
override val client: OkHttpClient = network.client
private val json: Json by injectLazy()
val preferences: SharedPreferences by lazy {
@ -210,7 +209,7 @@ abstract class ZoroTheme(
)
override suspend fun getVideoList(episode: SEpisode): List<Video> {
val response = client.newCall(videoListRequest(episode)).execute()
val response = client.newCall(videoListRequest(episode)).await()
val episodeReferer = response.request.header("referer")!!
val typeSelection = preferences.typeToggle
@ -230,7 +229,7 @@ abstract class ZoroTheme(
val link = client.newCall(
GET("$baseUrl/ajax$ajaxRoute/episode/sources?id=$id", apiHeaders(episodeReferer)),
).execute().parseAs<SourcesResponse>().link ?: ""
).await().parseAs<SourcesResponse>().link ?: ""
VideoData(type, link, name)
}
@ -250,11 +249,6 @@ abstract class ZoroTheme(
override fun videoUrlParse(document: Document) = throw Exception("not used")
// ============================= Utilities ==============================
private inline fun <reified T> Response.parseAs(): T {
return use { it.body.string() }.let(json::decodeFromString)
}
private fun Set<String>.contains(s: String, ignoreCase: Boolean): Boolean {
return any { it.equals(s, ignoreCase) }
}

View File

@ -81,7 +81,6 @@ interface ThemeSourceGenerator {
| extClass = '.${source.className}'
| extFactory = '$themePkg'
| extVersionCode = ${baseVersionCode + source.overrideVersionCode + MULTISRC_LIBRARY_VERSION}
| libVersion = '13'
| ${if (source.isNsfw) "containsNsfw = true\n" else ""}
|}
|$defaultAdditionalGradleText

View File

@ -9,7 +9,6 @@ ext {
pkgNameSuffix = 'all.animeonsen'
extClass = '.AnimeOnsen'
extVersionCode = 7
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -18,14 +18,12 @@ import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import kotlinx.serialization.decodeFromString
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.boolean
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Headers
import okhttp3.Response
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -43,11 +41,9 @@ class AnimeOnsen : ConfigurableAnimeSource, AnimeHttpSource() {
override val supportsLatest = false
private val cfClient = network.cloudflareClient
override val client by lazy {
network.client.newBuilder()
.addInterceptor(AOAPIInterceptor(cfClient))
.addInterceptor(AOAPIInterceptor(network.client))
.build()
}
@ -88,15 +84,9 @@ class AnimeOnsen : ConfigurableAnimeSource, AnimeHttpSource() {
}
// =========================== Anime Details ============================
override fun fetchAnimeDetails(anime: SAnime): Observable<SAnime> {
return client.newCall(GET("$apiUrl/content/${anime.url}/extensive"))
.asObservableSuccess()
.map { response ->
animeDetailsParse(response).apply { initialized = true }
}
}
override fun animeDetailsRequest(anime: SAnime) = GET("$apiUrl/content/${anime.url}/extensive")
override fun animeDetailsRequest(anime: SAnime) = GET("$baseUrl/details/${anime.url}")
override fun getAnimeUrl(anime: SAnime) = "$baseUrl/details/${anime.url}"
override fun animeDetailsParse(response: Response) = SAnime.create().apply {
val details = response.parseAs<AnimeDetails>()
@ -165,10 +155,6 @@ class AnimeOnsen : ConfigurableAnimeSource, AnimeHttpSource() {
}
// ============================= Utilities ==============================
private inline fun <reified T> Response.parseAs(): T {
return use { it.body.string() }.let(json::decodeFromString)
}
private fun parseStatus(statusString: String?): Int {
return when (statusString?.trim()) {
"finished_airing" -> SAnime.COMPLETED

View File

@ -9,7 +9,6 @@ ext {
pkgNameSuffix = 'all.animeworldindia'
extClass = '.AnimeWorldIndiaFactory'
extVersionCode = 7
libVersion = '13'
}
dependencies {

View File

@ -34,8 +34,6 @@ class AnimeWorldIndia(
override val supportsLatest = true
override val client = network.cloudflareClient
private val json: Json by injectLazy()
private val preferences by lazy {

View File

@ -9,7 +9,6 @@ ext {
pkgNameSuffix = 'all.googledrive'
extClass = '.GoogleDrive'
extVersionCode = 13
libVersion = '13'
}
dependencies {

View File

@ -22,18 +22,17 @@ import eu.kanade.tachiyomi.lib.googledriveextractor.GoogleDriveExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.ProtocolException
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.internal.commonEmptyRequestBody
import org.jsoup.nodes.Document
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -63,8 +62,6 @@ class GoogleDrive : ConfigurableAnimeSource, AnimeHttpSource() {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
override val client: OkHttpClient = network.client
// Overriding headersBuilder() seems to cause issues with webview
private val getHeaders = headers.newBuilder().apply {
add("Accept", "*/*")
@ -77,8 +74,8 @@ class GoogleDrive : ConfigurableAnimeSource, AnimeHttpSource() {
// ============================== Popular ===============================
override fun fetchPopularAnime(page: Int): Observable<AnimesPage> =
Observable.just(parsePage(popularAnimeRequest(page), page))
override suspend fun getPopularAnime(page: Int): AnimesPage =
parsePage(popularAnimeRequest(page), page)
override fun popularAnimeRequest(page: Int): Request {
require(!baseUrlInternal.isNullOrEmpty()) { "Enter drive path(s) in extension settings." }
@ -106,11 +103,11 @@ class GoogleDrive : ConfigurableAnimeSource, AnimeHttpSource() {
override fun searchAnimeParse(response: Response): AnimesPage = throw Exception("Not used")
override fun fetchSearchAnime(
override suspend fun getSearchAnime(
page: Int,
query: String,
filters: AnimeFilterList,
): Observable<AnimesPage> {
): AnimesPage {
val filterList = if (filters.isEmpty()) getFilterList() else filters
val urlFilter = filterList.find { it is URLFilter } as URLFilter
@ -118,16 +115,16 @@ class GoogleDrive : ConfigurableAnimeSource, AnimeHttpSource() {
val req = searchAnimeRequest(page, query, filters)
if (query.isEmpty()) {
Observable.just(parsePage(req, page))
parsePage(req, page)
} else {
val parentId = req.url.pathSegments.last()
val cleanQuery = URLEncoder.encode(query, "UTF-8")
val genMultiFormReq = searchReq(parentId, cleanQuery)
Observable.just(parsePage(req, page, genMultiFormReq))
parsePage(req, page, genMultiFormReq)
}
} else {
Observable.just(addSinglePage(urlFilter.state))
addSinglePage(urlFilter.state)
}
}
@ -187,10 +184,10 @@ class GoogleDrive : ConfigurableAnimeSource, AnimeHttpSource() {
return GET(parsed.url, headers = getHeaders)
}
override fun fetchAnimeDetails(anime: SAnime): Observable<SAnime> {
override suspend fun getAnimeDetails(anime: SAnime): SAnime {
val parsed = json.decodeFromString<LinkData>(anime.url)
if (parsed.type == "single") return Observable.just(anime)
if (parsed.type == "single") return anime
val folderId = DRIVE_FOLDER_REGEX.matchEntire(parsed.url)!!.groups["id"]!!.value
@ -198,7 +195,7 @@ class GoogleDrive : ConfigurableAnimeSource, AnimeHttpSource() {
client.newCall(GET(parsed.url, headers = getHeaders)).execute().asJsoup()
} catch (a: ProtocolException) {
null
} ?: return Observable.just(anime)
} ?: return anime
// Get cover
@ -251,20 +248,19 @@ class GoogleDrive : ConfigurableAnimeSource, AnimeHttpSource() {
}
}
return Observable.just(anime)
return anime
}
override fun animeDetailsParse(response: Response): SAnime = throw Exception("Not used")
// ============================== Episodes ==============================
override fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>> {
override suspend fun getEpisodeList(anime: SAnime): List<SEpisode> {
val episodeList = mutableListOf<SEpisode>()
val parsed = json.decodeFromString<LinkData>(anime.url)
if (parsed.type == "single") {
return Observable.just(
listOf(
return listOf(
SEpisode.create().apply {
name = "Video"
scanlator = parsed.info!!.size
@ -272,7 +268,6 @@ class GoogleDrive : ConfigurableAnimeSource, AnimeHttpSource() {
episode_number = 1F
date_upload = -1L
},
),
)
}
@ -354,15 +349,15 @@ class GoogleDrive : ConfigurableAnimeSource, AnimeHttpSource() {
traverseFolder(parsed.url, "")
return Observable.just(episodeList.reversed())
return episodeList.reversed()
}
override fun episodeListParse(response: Response): List<SEpisode> = throw Exception("Not used")
// ============================ Video Links =============================
override fun fetchVideoList(episode: SEpisode): Observable<List<Video>> =
Observable.just(GoogleDriveExtractor(client, headers).videosFromUrl(episode.url))
override suspend fun getVideoList(episode: SEpisode): List<Video> =
GoogleDriveExtractor(client, headers).videosFromUrl(episode.url)
// ============================= Utilities ==============================
@ -508,11 +503,6 @@ class GoogleDrive : ConfigurableAnimeSource, AnimeHttpSource() {
return AnimesPage(animeList, nextPageToken != null)
}
private inline fun <reified T> Response.parseAs(transform: (String) -> String = { it }): T {
val responseBody = use { transform(it.body.string()) }
return json.decodeFromString(responseBody)
}
// https://github.com/yt-dlp/yt-dlp/blob/8f0be90ecb3b8d862397177bb226f17b245ef933/yt_dlp/extractor/youtube.py#L573
private fun generateSapisidhashHeader(
SAPISID: String,

View File

@ -7,7 +7,6 @@ ext {
pkgNameSuffix = 'all.googledriveindex'
extClass = '.GoogleDriveIndex'
extVersionCode = 7
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -21,19 +21,18 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import okhttp3.Credentials
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -59,7 +58,7 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
override val client = network.client.newBuilder()
.addInterceptor { chain ->
var request = chain.request()
@ -119,29 +118,22 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
override fun searchAnimeParse(response: Response): AnimesPage = throw Exception("Not used")
override fun fetchSearchAnime(
override suspend fun getSearchAnime(
page: Int,
query: String,
filters: AnimeFilterList,
): Observable<AnimesPage> {
): AnimesPage {
val filterList = if (filters.isEmpty()) getFilterList() else filters
val urlFilter = filterList.find { it is URLFilter } as URLFilter
return if (urlFilter.state.isEmpty()) {
val req = searchAnimeRequest(page, query, filters)
Observable.defer {
try {
client.newCall(req).asObservableSuccess()
} catch (e: NoClassDefFoundError) {
// RxJava doesn't handle Errors, which tends to happen during global searches
// if an old extension using non-existent classes is still around
throw RuntimeException(e)
}
}.map { response ->
client.newCall(req).awaitSuccess()
.use { response ->
searchAnimeParse(response, req.url.toString())
}
} else {
Observable.just(addSinglePage(urlFilter.state))
addSinglePage(urlFilter.state)
}
}
@ -237,7 +229,7 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
// =========================== Anime Details ============================
override fun fetchAnimeDetails(anime: SAnime): Observable<SAnime> {
override suspend fun getAnimeDetails(anime: SAnime): SAnime {
val parsed = json.decodeFromString<LinkData>(anime.url)
val newParsed = if (parsed.type != "search") {
parsed
@ -265,7 +257,7 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
}
if (newParsed.type == "single") {
return Observable.just(anime)
return anime
}
var newToken: String? = ""
@ -309,14 +301,14 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
newPageIndex += 1
}
return Observable.just(anime)
return anime
}
override fun animeDetailsParse(response: Response): SAnime = throw Exception("Not used")
// ============================== Episodes ==============================
override fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>> {
override suspend fun getEpisodeList(anime: SAnime): List<SEpisode> {
val episodeList = mutableListOf<SEpisode>()
val parsed = json.decodeFromString<LinkData>(anime.url)
var counter = 1
@ -446,14 +438,14 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
traverseDirectory(newParsed.url)
}
return Observable.just(episodeList.reversed())
return episodeList.reversed()
}
override fun episodeListParse(response: Response): List<SEpisode> = throw Exception("Not used")
// ============================ Video Links =============================
override fun fetchVideoList(episode: SEpisode): Observable<List<Video>> {
override suspend fun getVideoList(episode: SEpisode): List<Video> {
val url = episode.url
val doc = client.newCall(
@ -462,10 +454,10 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
val script = doc.selectFirst("script:containsData(videodomain)")?.data()
?: doc.selectFirst("script:containsData(downloaddomain)")?.data()
?: return Observable.just(listOf(Video(url, "Video", url)))
?: return listOf(Video(url, "Video", url))
if (script.contains("\"second_domain_for_dl\":false")) {
return Observable.just(listOf(Video(url, "Video", url)))
return listOf(Video(url, "Video", url))
}
val domainUrl = if (script.contains("videodomain", true)) {
@ -484,18 +476,10 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
domainUrl + url.toHttpUrl().encodedPath
}
return Observable.just(
listOf(Video(videoUrl, "Video", videoUrl)),
)
return listOf(Video(videoUrl, "Video", videoUrl))
}
// ============================= Utilities ==============================
private inline fun <reified T> Response.parseAs(transform: (String) -> String = { it }): T {
val responseBody = use { transform(it.body.string()) }
return json.decodeFromString(responseBody)
}
private fun HttpUrl.hostAndCred(): String {
return if (this.password.isNotBlank() && this.username.isNotBlank()) {
"${this.username}:${this.password}@${this.host}"

View File

@ -8,7 +8,6 @@ ext {
pkgNameSuffix = 'all.javguru'
extClass = '.JavGuru'
extVersionCode = 9
libVersion = '13'
containsNsfw = true
}

View File

@ -20,20 +20,16 @@ import eu.kanade.tachiyomi.lib.mixdropextractor.MixDropExtractor
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservable
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.Call
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.Request
import okhttp3.Response
import org.jsoup.select.Elements
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import kotlin.math.min
@ -48,8 +44,6 @@ class JavGuru : AnimeHttpSource(), ConfigurableAnimeSource {
override val supportsLatest = true
override val client = network.cloudflareClient
private val noRedirectClient = client.newBuilder()
.followRedirects(false)
.build()
@ -60,13 +54,13 @@ class JavGuru : AnimeHttpSource(), ConfigurableAnimeSource {
private lateinit var popularElements: Elements
override fun fetchPopularAnime(page: Int): Observable<AnimesPage> {
override suspend fun getPopularAnime(page: Int): AnimesPage {
return if (page == 1) {
client.newCall(popularAnimeRequest(page))
.asObservableSuccess()
.map(::popularAnimeParse)
.awaitSuccess()
.use(::popularAnimeParse)
} else {
Observable.just(cachedPopularAnimeParse(page))
cachedPopularAnimeParse(page)
}
}
@ -126,22 +120,22 @@ class JavGuru : AnimeHttpSource(), ConfigurableAnimeSource {
return AnimesPage(entries, page < lastPage)
}
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage {
if (query.startsWith(PREFIX_ID)) {
val id = query.substringAfter(PREFIX_ID)
if (id.toIntOrNull() == null) {
return Observable.just(AnimesPage(emptyList(), false))
return AnimesPage(emptyList(), false)
}
val url = "/$id/"
val tempAnime = SAnime.create().apply { this.url = url }
return fetchAnimeDetails(tempAnime).map {
return getAnimeDetails(tempAnime).let {
val anime = it.apply { this.url = url }
AnimesPage(listOf(anime), false)
}
} else if (query.isNotEmpty()) {
return client.newCall(searchAnimeRequest(page, query, filters))
.asObservableSuccess()
.map(::searchAnimeParse)
.awaitSuccess()
.use(::searchAnimeParse)
} else {
filters.forEach { filter ->
when (filter) {
@ -152,8 +146,8 @@ class JavGuru : AnimeHttpSource(), ConfigurableAnimeSource {
val url = "$baseUrl${filter.toUrlPart()}" + if (page > 1) "page/$page/" else ""
val request = GET(url, headers)
return client.newCall(request)
.asObservableSuccess()
.map(::searchAnimeParse)
.awaitSuccess()
.use(::searchAnimeParse)
}
}
is ActressFilter,
@ -165,8 +159,8 @@ class JavGuru : AnimeHttpSource(), ConfigurableAnimeSource {
val url = "$baseUrl${filter.toUrlPart()}" + if (page > 1) "page/$page/" else ""
val request = GET(url, headers)
return client.newCall(request)
.asObservableIgnoreCode(404)
.map(::searchAnimeParse)
.awaitIgnoreCode(404)
.use(::searchAnimeParse)
}
}
else -> { }
@ -218,14 +212,12 @@ class JavGuru : AnimeHttpSource(), ConfigurableAnimeSource {
}
}
override fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>> {
return Observable.just(
listOf(
override suspend fun getEpisodeList(anime: SAnime): List<SEpisode> {
return listOf(
SEpisode.create().apply {
url = anime.url
name = "Episode"
},
),
)
}
@ -242,8 +234,7 @@ class JavGuru : AnimeHttpSource(), ConfigurableAnimeSource {
return iframeUrls
.mapNotNull(::resolveHosterUrl)
.parallelMap(::getVideos)
.flatten()
.parallelCatchingFlatMapBlocking(::getVideos)
}
private fun resolveHosterUrl(iframeUrl: String): String? {
@ -289,8 +280,7 @@ class JavGuru : AnimeHttpSource(), ConfigurableAnimeSource {
private val emTurboExtractor by lazy { EmTurboExtractor(client, headers) }
private fun getVideos(hosterUrl: String): List<Video> {
return runCatching {
when {
return when {
hosterUrl.contains("javplaya") -> {
streamWishExtractor.videosFromUrl(hosterUrl)
}
@ -315,12 +305,9 @@ class JavGuru : AnimeHttpSource(), ConfigurableAnimeSource {
emTurboExtractor.getVideos(hosterUrl)
}
else -> {
emptyList()
else -> emptyList()
}
}
}.getOrDefault(emptyList())
}
override fun List<Video>.sort(): List<Video> {
val quality = preference.getString(PREF_QUALITY, PREF_QUALITY_DEFAULT)!!
@ -330,11 +317,6 @@ class JavGuru : AnimeHttpSource(), ConfigurableAnimeSource {
).reversed()
}
private fun <A, B> Iterable<A>.parallelMap(f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
private fun getIDFromUrl(element: Elements): String? {
return element.attr("abs:href")
.toHttpUrlOrNull()
@ -353,8 +335,8 @@ class JavGuru : AnimeHttpSource(), ConfigurableAnimeSource {
?.last()
?.toIntOrNull()
private fun Call.asObservableIgnoreCode(code: Int): Observable<Response> {
return asObservable().doOnNext { response ->
private suspend fun Call.awaitIgnoreCode(code: Int): Response {
return await().also { response ->
if (!response.isSuccessful && response.code != code) {
response.close()
throw Exception("HTTP error ${response.code}")

View File

@ -9,7 +9,6 @@ ext {
pkgNameSuffix = 'all.jellyfin'
extClass = '.JellyfinFactory'
extVersionCode = 11
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -19,7 +19,8 @@ import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
@ -31,7 +32,6 @@ import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.Jsoup
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -135,10 +135,10 @@ class Jellyfin(private val suffix: String) : ConfigurableAnimeSource, AnimeHttpS
override fun popularAnimeParse(response: Response): AnimesPage = throw Exception("Not used")
override fun fetchPopularAnime(page: Int): Observable<AnimesPage> {
override suspend fun getPopularAnime(page: Int): AnimesPage {
return client.newCall(popularAnimeRequest(page))
.asObservableSuccess()
.map { response ->
.awaitSuccess()
.use { response ->
popularAnimeParsePage(response, page)
}
}
@ -175,10 +175,10 @@ class Jellyfin(private val suffix: String) : ConfigurableAnimeSource, AnimeHttpS
override fun latestUpdatesParse(response: Response) = throw Exception("Not used")
override fun fetchLatestUpdates(page: Int): Observable<AnimesPage> {
override suspend fun getLatestUpdates(page: Int): AnimesPage {
return client.newCall(latestUpdatesRequest(page))
.asObservableSuccess()
.map { response ->
.awaitSuccess()
.use { response ->
latestUpdatesParsePage(response, page)
}
}
@ -211,7 +211,7 @@ class Jellyfin(private val suffix: String) : ConfigurableAnimeSource, AnimeHttpS
override fun searchAnimeParse(response: Response) = throw Exception("Not used")
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage {
require(parentId.isNotEmpty()) { "Select library in the extension settings." }
val startIndex = (page - 1) * 5
@ -240,7 +240,7 @@ class Jellyfin(private val suffix: String) : ConfigurableAnimeSource, AnimeHttpS
getAnimeFromId(it.Id)
}
return Observable.just(AnimesPage(animeList, 5 * page < items.TotalRecordCount))
return AnimesPage(animeList, 5 * page < items.TotalRecordCount)
}
private fun getAnimeFromMovie(movieList: List<ItemsResponse.Item>): List<SAnime> {
@ -557,11 +557,6 @@ class Jellyfin(private val suffix: String) : ConfigurableAnimeSource, AnimeHttpS
return json.encodeToString(this)
}
private inline fun <reified T> Response.parseAs(transform: (String) -> String = { it }): T {
val responseBody = use { transform(it.body.string()) }
return json.decodeFromString(responseBody)
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val mediaLibPref = medialibPreference(screen)
screen.addPreference(

View File

@ -5,6 +5,7 @@ import android.os.Build
import android.util.Log
import eu.kanade.tachiyomi.AppInfo
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.buildJsonObject
@ -13,7 +14,6 @@ import okhttp3.Headers
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
class JellyfinAuthenticator(
@ -84,11 +84,6 @@ class JellyfinAuthenticator(
value,
).apply()
private inline fun <reified T> Response.parseAs(transform: (String) -> String = { it }): T {
val responseBody = use { transform(it.body.string()) }
return json.decodeFromString(responseBody)
}
companion object {
private const val DEVICEID_KEY = "device_id"
private const val CLIENT = "Aniyomi"

View File

@ -9,7 +9,6 @@ ext {
pkgNameSuffix = 'all.kamyroll'
extClass = '.Yomiroll'
extVersionCode = 29
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -16,12 +16,12 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.parallelCatchingFlatMap
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import eu.kanade.tachiyomi.util.parallelMapNotNullBlocking
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.encodeToString
@ -30,7 +30,6 @@ import kotlinx.serialization.json.jsonObject
import okhttp3.FormBody
import okhttp3.Request
import okhttp3.Response
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@ -176,7 +175,7 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
}
}
override fun fetchAnimeDetails(anime: SAnime): Observable<SAnime> {
override suspend fun getAnimeDetails(anime: SAnime): SAnime {
val mediaId = json.decodeFromString<LinkData>(anime.url)
val resp = client.newCall(
if (mediaId.media_type == "series") {
@ -186,9 +185,7 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
},
).execute().use { it.body.string() }
val info = json.decodeFromString<AnimeResult>(resp)
return Observable.just(
info.data.first().toSAnimeOrNull(anime) ?: anime,
)
return info.data.first().toSAnimeOrNull(anime) ?: anime
}
override fun animeDetailsParse(response: Response): SAnime = throw Exception("not used")
@ -210,11 +207,7 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
val chunkSize = Runtime.getRuntime().availableProcessors()
return if (series) {
seasons.data.sortedBy { it.season_number }.chunked(chunkSize).flatMap { chunk ->
chunk.parallelMap { seasonData ->
runCatching {
getEpisodes(seasonData)
}.getOrNull()
}.filterNotNull().flatten()
chunk.parallelCatchingFlatMapBlocking(::getEpisodes)
}.reversed()
} else {
seasons.data.mapIndexed { index, movie ->
@ -263,7 +256,7 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
// ============================ Video Links =============================
override fun fetchVideoList(episode: SEpisode): Observable<List<Video>> {
override suspend fun getVideoList(episode: SEpisode): List<Video> {
val urlJson = json.decodeFromString<EpisodeData>(episode.url)
val dubLocale = preferences.getString(PREF_AUD_KEY, PREF_AUD_DEFAULT)!!
@ -276,13 +269,9 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
it.second == "en-US" ||
it.second == "" ||
if (isUsingLocalToken) it.second == urlJson.ids.first().second else false
}.parallelMap { media ->
runCatching {
extractVideo(media)
}.getOrNull()
}.filterNotNull().flatten()
}.parallelCatchingFlatMap(::extractVideo)
return Observable.just(videoList.sort())
return videoList.sort()
}
// ============================= Utilities ==============================
@ -314,11 +303,11 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
audLang: String,
subsList: List<Track>,
): List<Video> {
return streams.streams?.adaptive_hls?.entries?.parallelMap { (_, value) ->
return streams.streams?.adaptive_hls?.entries?.parallelMapNotNullBlocking { (_, value) ->
val stream = json.decodeFromString<HlsLinks>(value.jsonObject.toString())
runCatching {
val playlist = client.newCall(GET(stream.url)).execute()
if (playlist.code != 200) return@parallelMap null
if (playlist.code != 200) return@parallelMapNotNullBlocking null
playlist.use { it.body.string() }.substringAfter("#EXT-X-STREAM-INF:")
.split("#EXT-X-STREAM-INF:").map {
val hardsub = stream.hardsub_locale.let { hs ->
@ -342,7 +331,7 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
}
}
}.getOrNull()
}?.filterNotNull()?.flatten() ?: emptyList()
}?.flatten() ?: emptyList()
}
private fun getVideoRequest(mediaId: String): Request {
@ -421,7 +410,9 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
val media = json.decodeFromString<LinkData>(anime.url)
if (media.media_type == "series") {
fetchStatusByTitle(this@toSAnime.title)
} else SAnime.COMPLETED
} else {
SAnime.COMPLETED
}
} ?: SAnime.UNKNOWN
author = content_provider
description = anime?.description ?: StringBuilder().apply {
@ -600,12 +591,6 @@ class Yomiroll : ConfigurableAnimeSource, AnimeHttpSource() {
}
}.apply { reload() }
// From Dopebox
private inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
private fun getTokenDetail(force: Boolean = false): String {
return runCatching {
val storedToken = tokenInterceptor.getAccessToken(force)

View File

@ -20,7 +20,6 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Element
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -34,8 +33,6 @@ class MissAV : AnimeHttpSource(), ConfigurableAnimeSource {
override val supportsLatest = true
override val client = network.cloudflareClient
override fun headersBuilder() = super.headersBuilder()
.add("Referer", "$baseUrl/")
@ -136,14 +133,12 @@ class MissAV : AnimeHttpSource(), ConfigurableAnimeSource {
.joinToString()
.takeIf(String::isNotBlank)
override fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>> {
return Observable.just(
listOf(
override suspend fun getEpisodeList(anime: SAnime): List<SEpisode> {
return listOf(
SEpisode.create().apply {
url = anime.url
name = "Episode"
},
),
)
}

View File

@ -8,7 +8,6 @@ ext {
pkgNameSuffix = 'all.supjav'
extClass = '.SupJavFactory'
extVersionCode = 1
libVersion = '13'
containsNsfw = true
}

View File

@ -15,18 +15,14 @@ import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.select.Elements
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -38,8 +34,6 @@ class SupJav(override val lang: String = "en") : ConfigurableAnimeSource, Parsed
override val supportsLatest = false
override val client = network.cloudflareClient
override fun headersBuilder() = super.headersBuilder()
.set("Referer", "$baseUrl/")
.set("Origin", baseUrl)
@ -87,14 +81,14 @@ class SupJav(override val lang: String = "en") : ConfigurableAnimeSource, Parsed
}
// =============================== Search ===============================
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage {
return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
val id = query.removePrefix(PREFIX_SEARCH)
client.newCall(GET("$baseUrl/$id"))
.asObservableSuccess()
.map(::searchAnimeByIdParse)
.awaitSuccess()
.use(::searchAnimeByIdParse)
} else {
super.fetchSearchAnime(page, query, filters)
super.getSearchAnime(page, query, filters)
}
}
@ -129,14 +123,14 @@ class SupJav(override val lang: String = "en") : ConfigurableAnimeSource, Parsed
private fun Elements.textsOrNull() = eachText().joinToString().takeUnless(String::isEmpty)
// ============================== Episodes ==============================
override fun fetchEpisodeList(anime: SAnime): Observable<List<SEpisode>> {
override suspend fun getEpisodeList(anime: SAnime): List<SEpisode> {
val episode = SEpisode.create().apply {
name = "JAV"
episode_number = 1F
url = anime.url
}
return Observable.just(listOf(episode))
return listOf(episode)
}
override fun episodeListSelector(): String {
@ -155,7 +149,7 @@ class SupJav(override val lang: String = "en") : ConfigurableAnimeSource, Parsed
.filter { it.text() in SUPPORTED_PLAYERS }
.map { it.text() to it.attr("data-link").reversed() }
return players.parallelCatchingFlatMap(::videosFromPlayer)
return players.parallelCatchingFlatMapBlocking(::videosFromPlayer)
}
private val playlistUtils by lazy { PlaylistUtils(client, headers) }
@ -227,15 +221,6 @@ class SupJav(override val lang: String = "en") : ConfigurableAnimeSource, Parsed
}
// ============================= Utilities ==============================
private inline fun <A, B> Iterable<A>.parallelCatchingFlatMap(crossinline f: suspend (A) -> Iterable<B>): List<B> =
runBlocking {
map {
async(Dispatchers.Default) {
runCatching { f(it) }.getOrElse { emptyList() }
}
}.awaitAll().flatten()
}
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!

View File

@ -6,7 +6,6 @@ ext {
pkgNameSuffix = 'ar.akwam'
extClass = '.Akwam'
extVersionCode = 9
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -34,8 +33,6 @@ class Akwam : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = false
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}

View File

@ -9,7 +9,6 @@ ext {
pkgNameSuffix = 'ar.anime4up'
extClass = '.Anime4Up'
extVersionCode = 52
libVersion = '13'
}
dependencies {

View File

@ -22,10 +22,7 @@ import eu.kanade.tachiyomi.lib.vidbomextractor.VidBomExtractor
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
@ -48,8 +45,6 @@ class Anime4Up : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = false
override val client = network.cloudflareClient
private val json: Json by injectLazy()
private val preferences by lazy {
@ -159,7 +154,7 @@ class Anime4Up : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val parsedData = json.decodeFromString<Qualities>(base64)
val streamLinks = with(parsedData) { fhd + hd + sd }
return streamLinks.values.distinct().parallelCatchingFlatMap(::extractVideos)
return streamLinks.values.distinct().parallelCatchingFlatMapBlocking(::extractVideos)
}
private val uqloadExtractor by lazy { UqloadExtractor(client) }
@ -216,15 +211,6 @@ class Anime4Up : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
// ============================= Utilities ==============================
private inline fun <A, B> Iterable<A>.parallelCatchingFlatMap(crossinline f: suspend (A) -> Iterable<B>): List<B> =
runBlocking {
map {
async(Dispatchers.Default) {
runCatching { f(it) }.getOrElse { emptyList() }
}
}.awaitAll().flatten()
}
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!

View File

@ -8,7 +8,6 @@ ext {
pkgNameSuffix = 'ar.animeblkom'
extClass = '.AnimeBlkom'
extVersionCode = 16
libVersion = '13'
}
dependencies {

View File

@ -32,8 +32,6 @@ class AnimeBlkom : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = false
override val client = network.cloudflareClient
override fun headersBuilder() = super.headersBuilder()
.add("referer", baseUrl)

View File

@ -7,7 +7,6 @@ ext {
pkgNameSuffix = 'ar.animeiat'
extClass = '.Animeiat'
extVersionCode = 1
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -8,7 +8,6 @@ ext {
pkgNameSuffix = 'ar.animelek'
extClass = '.AnimeLek'
extVersionCode = 27
libVersion = '13'
}
dependencies {

View File

@ -17,7 +17,6 @@ import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.lib.vidbomextractor.VidBomExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -36,8 +35,6 @@ class AnimeLek : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}

View File

@ -8,7 +8,6 @@ ext {
pkgNameSuffix = 'ar.animerco'
extClass = '.Animerco'
extVersionCode = 34
libVersion = '13'
}
dependencies {

View File

@ -23,12 +23,8 @@ import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -47,8 +43,6 @@ class Animerco : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = false
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
@ -160,9 +154,7 @@ class Animerco : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoListParse(response: Response): List<Video> {
val document = response.use { it.asJsoup() }
val players = document.select(videoListSelector())
return players.parallelMap {
runCatching { getPlayerVideos(it) }.getOrElse { emptyList() }
}.flatten()
return players.parallelCatchingFlatMapBlocking(::getPlayerVideos)
}
override fun videoListSelector() = "li.dooplay_player_option" // ul#playeroptionsul
@ -250,11 +242,6 @@ class Animerco : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
// ============================= Utilities ==============================
private inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
companion object {
private const val PREF_QUALITY_KEY = "preferred_quality"
private const val PREF_QUALITY_TITLE = "Preferred quality"

View File

@ -9,7 +9,6 @@ ext {
pkgNameSuffix = 'ar.arabanime'
extClass = '.ArabAnime'
extVersionCode = 2
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -38,8 +38,6 @@ class ArabAnime : ConfigurableAnimeSource, AnimeHttpSource() {
override val supportsLatest = true
override val client = network.cloudflareClient
private val json: Json by injectLazy()
private val preferences by lazy {

View File

@ -8,7 +8,6 @@ ext {
pkgNameSuffix = 'ar.arabseed'
extClass = '.ArabSeed'
extVersionCode = 9
libVersion = '13'
}
dependencies {

View File

@ -18,10 +18,7 @@ import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -42,8 +39,6 @@ class ArabSeed : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = false
override val client = network.cloudflareClient
override fun headersBuilder() = super.headersBuilder().add("Referer", baseUrl)
private val preferences by lazy {
@ -97,11 +92,11 @@ class ArabSeed : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoListSelector() = "div.containerServers ul li"
private fun videosFromElement(document: Document): List<Video> {
return document.select(videoListSelector()).parallelMap { element ->
return document.select(videoListSelector()).parallelCatchingFlatMapBlocking { element ->
val quality = element.text()
val embedUrl = element.attr("data-link")
runCatching { getVideosFromUrl(embedUrl, quality) }.getOrElse { emptyList() }
}.flatten()
getVideosFromUrl(embedUrl, quality)
}
}
private val doodExtractor by lazy { DoodExtractor(client) }
@ -251,11 +246,6 @@ class ArabSeed : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
// ============================= Utilities ==============================
private inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
companion object {
// From egydead(ar)
private const val PREF_DOMAIN_KEY = "default_domain_v${BuildConfig.VERSION_NAME}"

View File

@ -8,7 +8,6 @@ ext {
pkgNameSuffix = 'ar.asia2tv'
extClass = '.Asia2TV'
extVersionCode = 15
libVersion = '13'
}
dependencies {

View File

@ -19,12 +19,8 @@ import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
import eu.kanade.tachiyomi.lib.vidbomextractor.VidBomExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -43,8 +39,6 @@ class Asia2TV : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = false
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
@ -90,7 +84,7 @@ class Asia2TV : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoListParse(response: Response): List<Video> {
val document = response.use { it.asJsoup() }
return document.select(videoListSelector()).parallelCatchingFlatMap {
return document.select(videoListSelector()).parallelCatchingFlatMapBlocking {
val url = it.attr("data-server")
getVideosFromUrl(url)
}
@ -265,15 +259,6 @@ class Asia2TV : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
// ============================= Utilities ==============================
private inline fun <A, B> Iterable<A>.parallelCatchingFlatMap(crossinline f: suspend (A) -> Iterable<B>): List<B> =
runBlocking {
map {
async(Dispatchers.Default) {
runCatching { f(it) }.getOrElse { emptyList() }
}
}.awaitAll().flatten()
}
companion object {
private val STREAM_WISH_DOMAINS by lazy { listOf("wishfast", "fviplions", "filelions", "streamwish", "dwish") }
private val VID_BOM_DOMAINS by lazy { listOf("vidbam", "vadbam", "vidbom", "vidbm") }

View File

@ -6,7 +6,6 @@ ext {
pkgNameSuffix = 'ar.egydead'
extClass = '.EgyDead'
extVersionCode = 10
libVersion = '13'
}
dependencies {

View File

@ -19,13 +19,10 @@ import eu.kanade.tachiyomi.lib.mixdropextractor.MixDropExtractor
import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMap
import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -46,8 +43,6 @@ class EgyDead : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
@ -132,19 +127,18 @@ class EgyDead : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
// ================================== video urls ==================================
private val streamWishExtractor by lazy { StreamWishExtractor(client, headers) }
override fun videoListParse(response: Response): List<Video> {
override suspend fun getVideoList(episode: SEpisode): List<Video> {
val requestBody = FormBody.Builder().add("View", "1").build()
val document = client.newCall(POST(response.request.url.toString(), body = requestBody)).execute().asJsoup()
return document.select(videoListSelector()).parallelMap {
val document = client.newCall(POST(baseUrl + episode.url, body = requestBody))
.await()
.use { it.asJsoup() }
return document.select(videoListSelector()).parallelCatchingFlatMap {
val url = it.attr("data-link")
runCatching { extractVideos(url) }.getOrElse { emptyList() }
}.flatten()
extractVideos(url)
}
}
private inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
private fun extractVideos(url: String): List<Video> {
return when {
DOOD_REGEX.containsMatchIn(url) -> {

View File

@ -6,7 +6,6 @@ ext {
pkgNameSuffix = 'ar.faselhd'
extClass = '.FASELHD'
extVersionCode = 14
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -34,8 +33,6 @@ class FASELHD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}

View File

@ -6,7 +6,6 @@ ext {
pkgNameSuffix = 'ar.movies4u'
extClass = '.Movies4U'
extVersionCode = 4
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -14,7 +14,6 @@ import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -34,8 +33,6 @@ class Movies4U : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = false
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}

View File

@ -6,7 +6,6 @@ ext {
pkgNameSuffix = 'ar.mycima'
extClass = '.MyCima'
extVersionCode = 20
libVersion = '13'
}
dependencies {

View File

@ -16,11 +16,7 @@ import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -39,8 +35,6 @@ class MyCima : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
@ -124,9 +118,8 @@ class MyCima : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
return document.select("ul.WatchServersList li btn").parallelMap {
return document.select("ul.WatchServersList li btn").parallelCatchingFlatMapBlocking {
val frameURL = it.attr("data-url")
runCatching {
if (it.parent()?.hasClass("MyCimaServer") == true) {
val referer = response.request.url.encodedPath
val newHeader = headers.newBuilder().add("referer", baseUrl + referer).build()
@ -135,8 +128,7 @@ class MyCima : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
} else {
extractVideos(frameURL)
}
}.getOrElse { emptyList() }
}.flatten()
}
}
private fun extractVideos(url: String): List<Video> {
@ -367,10 +359,6 @@ class MyCima : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
private fun getPrefBaseUrl(): String = preferences.getString(PREF_BASE_URL_KEY, PREF_BASE_URL_DEFAULT)!!
// ============================= Utilities ===================================
private inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
companion object {
private const val PREF_QUALITY_KEY = "preferred_quality"
private const val PREF_QUALITY_TITLE = "Preferred quality"

View File

@ -8,7 +8,6 @@ ext {
pkgNameSuffix = 'ar.okanime'
extClass = '.Okanime'
extVersionCode = 5
libVersion = '13'
}
dependencies {

View File

@ -17,16 +17,12 @@ import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
import eu.kanade.tachiyomi.lib.vidbomextractor.VidBomExtractor
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -69,14 +65,14 @@ class Okanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun latestUpdatesNextPageSelector() = "ul.pagination > li:last-child:not(.disabled)"
// =============================== Search ===============================
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage {
return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
val id = query.removePrefix(PREFIX_SEARCH)
client.newCall(GET("$baseUrl/anime/$id"))
.asObservableSuccess()
.map(::searchAnimeByIdParse)
.awaitSuccess()
.use(::searchAnimeByIdParse)
} else {
super.fetchSearchAnime(page, query, filters)
super.getSearchAnime(page, query, filters)
}
}
@ -141,7 +137,7 @@ class Okanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val hosterSelection = preferences.getStringSet(PREF_HOSTER_SELECTION_KEY, PREF_HOSTER_SELECTION_DEFAULT)!!
return response.use { it.asJsoup() }
.select("a.ep-link")
.parallelMap { element ->
.parallelCatchingFlatMapBlocking { element ->
val quality = element.selectFirst("span")?.text().orEmpty().let {
when (it) {
"HD" -> "720p"
@ -152,7 +148,7 @@ class Okanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
val url = element.attr("data-src")
extractVideosFromUrl(url, quality, hosterSelection)
}.flatten()
}
}
// Inspirated by JavGuru(all)
@ -163,8 +159,7 @@ class Okanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
private val vidBomExtractor by lazy { VidBomExtractor(client) }
private fun extractVideosFromUrl(url: String, quality: String, selection: Set<String>): List<Video> {
return runCatching {
when {
return when {
"https://doo" in url && "/e/" in url && selection.contains("Dood") -> {
doodExtractor.videoFromUrl(url, "DoodStream - $quality")
?.let(::listOf)
@ -183,8 +178,7 @@ class Okanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
vidBomExtractor.videosFromUrl(url)
}
else -> null
}
}.getOrNull() ?: emptyList()
}.orEmpty()
}
override fun videoListSelector(): String {
@ -238,11 +232,6 @@ class Okanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
// ============================= Utilities ==============================
private inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
companion object {
const val PREFIX_SEARCH = "id:"

View File

@ -6,7 +6,6 @@ ext {
pkgNameSuffix = 'ar.tuktukcinema'
extClass = '.Tuktukcinema'
extVersionCode = 15
libVersion = '13'
}
dependencies {

View File

@ -23,11 +23,7 @@ import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
import eu.kanade.tachiyomi.lib.vidbomextractor.VidBomExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -48,8 +44,6 @@ class Tuktukcinema : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
@ -149,13 +143,8 @@ class Tuktukcinema : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
return document.select(videoListSelector()).parallelMap {
runCatching { extractVideos(it) }.getOrElse { emptyList() }
}.flatten()
}
private inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
return document.select(videoListSelector())
.parallelCatchingFlatMapBlocking(::extractVideos)
}
private fun extractVideos(element: Element): List<Video> {

View File

@ -8,7 +8,6 @@ ext {
pkgNameSuffix = 'ar.witanime'
extClass = '.WitAnime'
extVersionCode = 47
libVersion = '13'
}
dependencies {

View File

@ -19,10 +19,7 @@ import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
import eu.kanade.tachiyomi.lib.vidbomextractor.VidBomExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
@ -40,8 +37,6 @@ class WitAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = true
override val client = network.cloudflareClient
override fun headersBuilder() = super.headersBuilder().add("Referer", baseUrl)
private val preferences by lazy {
@ -130,7 +125,7 @@ class WitAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val document = response.asJsoup()
return document.select("ul#episode-servers li a")
.distinctBy { it.text().substringBefore(" -") } // remove duplicates by server name
.parallelCatchingFlatMap {
.parallelCatchingFlatMapBlocking {
val url = it.attr("data-url")
.takeUnless(String::isBlank)
?.let { String(Base64.decode(it, Base64.DEFAULT)) }
@ -237,15 +232,6 @@ class WitAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
// ============================= Utilities ==============================
private inline fun <A, B> Iterable<A>.parallelCatchingFlatMap(crossinline f: suspend (A) -> Iterable<B>): List<B> =
runBlocking {
map {
async(Dispatchers.Default) {
runCatching { f(it) }.getOrElse { emptyList() }
}
}.awaitAll().flatten()
}
private fun getRealDoc(document: Document): Document {
return document.selectFirst("div.anime-page-link a")?.let {
client.newCall(GET(it.attr("href"), headers)).execute().asJsoup()

View File

@ -6,7 +6,6 @@ ext {
pkgNameSuffix = 'ar.xsanime'
extClass = '.XsAnime'
extVersionCode = 10
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -34,8 +33,6 @@ class XsAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = false
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}

View File

@ -6,7 +6,6 @@ ext {
pkgNameSuffix = 'ar.xsmovie'
extClass = '.XsMovie'
extVersionCode = 5
libVersion = '13'
}
apply from: "$rootDir/common.gradle"

View File

@ -13,7 +13,6 @@ import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
@ -32,8 +31,6 @@ class XsMovie : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = false
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}

View File

@ -7,7 +7,6 @@ ext {
pkgNameSuffix = 'de.aniflix'
extClass = '.Aniflix'
extVersionCode = 25
libVersion = '13'
}
dependencies {

View File

@ -23,16 +23,13 @@ import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservableSuccess
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.Json
import okhttp3.Headers
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -46,8 +43,6 @@ class Aniflix : ConfigurableAnimeSource, AnimeHttpSource() {
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
@ -59,16 +54,8 @@ class Aniflix : ConfigurableAnimeSource, AnimeHttpSource() {
private val refererHeader = Headers.headersOf("Referer", baseUrl)
override fun fetchAnimeDetails(anime: SAnime): Observable<SAnime> {
return client.newCall(GET(baseUrl + anime.url))
.asObservableSuccess()
.map { response ->
animeDetailsParse(response).apply { initialized = true }
}
}
override fun animeDetailsRequest(anime: SAnime): Request {
return GET(baseUrl + anime.url.replace("api/", ""))
override fun getAnimeUrl(anime: SAnime): String {
return baseUrl + anime.url.replace("api/", "")
}
override fun animeDetailsParse(response: Response): SAnime {

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