[skip ci] Update dependencies (#1343)
* Bump harmless dependencies Note that bumping the android plugin will make compilation show lots of "hey bro use namespace instead of AndroidManifest.xml" warnings * Remove duktape dependency Zero extensions are using it, so its safe to remove. For executing js in extensions we can use quickjs instead of ducktape. * Upgrade gradle to 7.6 * Update kotlin * Update OkHttp * Update JSoup Jesus Christ this was boring asf * Update KtLint * [skip ci] refactor on some build.gradle.kts files * Expose coroutines to all extension by default
This commit is contained in:
@ -86,8 +86,8 @@ class Kuramanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
private fun parseShortInfo(element: Element): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(element.select("a").first().attr("href"))
|
||||
anime.thumbnail_url = element.select("a > div").first().attr("data-setbg")
|
||||
anime.setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
|
||||
anime.thumbnail_url = element.selectFirst("a > div")!!.attr("data-setbg")
|
||||
anime.title = element.select("div.product__item__text > h5").text()
|
||||
return anime
|
||||
}
|
||||
@ -124,7 +124,7 @@ class Kuramanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
document.select("select#changeServer > option").forEach {
|
||||
videoList.addAll(
|
||||
videosFromServer(response.request.url.toString(), it.attr("value"), it.text())
|
||||
videosFromServer(response.request.url.toString(), it.attr("value"), it.text()),
|
||||
)
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ class Kuramanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
private fun videosFromServer(episodeUrl: String, server: String, name: String): List<Video> {
|
||||
val document = client.newCall(
|
||||
GET("$episodeUrl?activate_stream=1&stream_server=$server", headers = headers)
|
||||
GET("$episodeUrl?activate_stream=1&stream_server=$server", headers = headers),
|
||||
).execute().asJsoup()
|
||||
return document.select(videoListSelector()).map { videoFromElement(it, name, episodeUrl) }
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ class Kuronime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
override fun episodeFromElement(element: Element): SEpisode {
|
||||
val episode = SEpisode.create()
|
||||
val epsNum = getNumberFromEpsString(element.select("span.lchx").text())
|
||||
episode.setUrlWithoutDomain(element.select("a").first().attr("href"))
|
||||
episode.setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
|
||||
episode.episode_number = when {
|
||||
(epsNum.isNotEmpty()) -> epsNum.toFloat()
|
||||
else -> 1F
|
||||
@ -84,9 +84,9 @@ class Kuronime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
private fun getAnimeFromAnimeElement(element: Element): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(element.select("div > a").first().attr("href"))
|
||||
anime.setUrlWithoutDomain(element.selectFirst("div > a")!!.attr("href"))
|
||||
|
||||
val thumbnailElement = element.selectFirst("div > a > div.limit > img")
|
||||
val thumbnailElement = element.selectFirst("div > a > div.limit > img")!!
|
||||
val thumbnail = thumbnailElement.attr("src")
|
||||
anime.thumbnail_url = if (thumbnail.startsWith("https:")) {
|
||||
thumbnail
|
||||
@ -132,7 +132,7 @@ class Kuronime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
document.select("select.mirror > option[value]").forEach { opt ->
|
||||
val decoded = if (opt.attr("value").isEmpty()) {
|
||||
document.selectFirst("iframe").attr("data-src")
|
||||
document.selectFirst("iframe")!!.attr("data-src")
|
||||
} else {
|
||||
Jsoup.parse(
|
||||
String(Base64.decode(opt.attr("value"), Base64.DEFAULT)),
|
||||
|
@ -13,7 +13,7 @@ import uy.kohesive.injekt.injectLazy
|
||||
@Serializable
|
||||
data class Source(
|
||||
val file: String,
|
||||
val label: String
|
||||
val label: String,
|
||||
)
|
||||
|
||||
class AnimekuExtractor(private val client: OkHttpClient) {
|
||||
@ -26,7 +26,7 @@ class AnimekuExtractor(private val client: OkHttpClient) {
|
||||
|
||||
val quickJs = QuickJs.create()
|
||||
val decryped = quickJs.evaluate(
|
||||
script.data().trim().split("\n")[0].replace("eval(function", "function a").replace("decodeURIComponent(escape(r))}(", "r};a(").substringBeforeLast(")")
|
||||
script.data().trim().split("\n")[0].replace("eval(function", "function a").replace("decodeURIComponent(escape(r))}(", "r};a(").substringBeforeLast(")"),
|
||||
).toString()
|
||||
quickJs.close()
|
||||
|
||||
@ -35,7 +35,7 @@ class AnimekuExtractor(private val client: OkHttpClient) {
|
||||
Video(
|
||||
src.file,
|
||||
"${src.label} - $name",
|
||||
src.file
|
||||
src.file,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,11 @@ import okhttp3.OkHttpClient
|
||||
class HxFileExtractor(private val client: OkHttpClient) {
|
||||
fun getVideoFromUrl(url: String, name: String): List<Video> {
|
||||
val document = client.newCall(GET(url)).execute().asJsoup()
|
||||
val packed = document.selectFirst("script:containsData(eval\\(function\\()").data()
|
||||
val packed = document.selectFirst("script:containsData(eval\\(function\\()")!!.data()
|
||||
val unpacked = JsUnpacker.unpackAndCombine(packed) ?: return emptyList()
|
||||
val videoUrl = unpacked.substringAfter("\"type\":\"video").substringAfter("\"file\":\"").substringBefore("\"")
|
||||
return listOf(
|
||||
Video(videoUrl, "Original - $name", videoUrl, headers = Headers.headersOf("Referer", "https://hxfile.co/"))
|
||||
Video(videoUrl, "Original - $name", videoUrl, headers = Headers.headersOf("Referer", "https://hxfile.co/")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,8 @@ class LinkBoxExtractor(private val client: OkHttpClient) {
|
||||
Video(
|
||||
it.jsonObject["url"].toString().replace("\"", ""),
|
||||
"${it.jsonObject["resolution"].toString().replace("\"", "")} - $name",
|
||||
it.jsonObject["url"].toString().replace("\"", "")
|
||||
)
|
||||
it.jsonObject["url"].toString().replace("\"", ""),
|
||||
),
|
||||
)
|
||||
}
|
||||
return videoList
|
||||
|
@ -8,14 +8,14 @@ import okhttp3.OkHttpClient
|
||||
|
||||
class Mp4uploadExtractor(private val client: OkHttpClient) {
|
||||
fun getVideoFromUrl(url: String, headers: Headers, name: String): List<Video> {
|
||||
val body = client.newCall(GET(url, headers = headers)).execute().body!!.string()
|
||||
val body = client.newCall(GET(url, headers = headers)).execute().body.string()
|
||||
|
||||
val packed = body.substringAfter("<script type='text/javascript'>eval(function(p,a,c,k,e,d)")
|
||||
.substringBefore("</script>")
|
||||
val unpacked = JsUnpacker.unpackAndCombine("eval(function(p,a,c,k,e,d)" + packed) ?: return emptyList()
|
||||
val videoUrl = unpacked.substringAfter("player.src(\"").substringBefore("\");")
|
||||
return listOf(
|
||||
Video(videoUrl, "Original - $name", videoUrl, headers = Headers.headersOf("Referer", "https://www.mp4upload.com/"))
|
||||
Video(videoUrl, "Original - $name", videoUrl, headers = Headers.headersOf("Referer", "https://www.mp4upload.com/")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,9 @@ class StreamlareExtractor(private val client: OkHttpClient) {
|
||||
POST(
|
||||
"https://slwatch.co/api/video/stream/get",
|
||||
body = "{\"id\":\"$id\"}"
|
||||
.toRequestBody("application/json".toMediaType())
|
||||
)
|
||||
).execute().body!!.string()
|
||||
.toRequestBody("application/json".toMediaType()),
|
||||
),
|
||||
).execute().body.string()
|
||||
|
||||
playlist.substringAfter("\"label\":\"").split("\"label\":\"").forEach {
|
||||
val quality = it.substringAfter("\"label\":\"").substringBefore("\",") + " - $name"
|
||||
|
@ -56,7 +56,7 @@ class MiniOppai : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
override fun episodeFromElement(element: Element): SEpisode {
|
||||
val episode = SEpisode.create()
|
||||
val epsNum = getNumberFromEpsString(element.select("span.lchx").text())
|
||||
episode.setUrlWithoutDomain(element.select("a").first().attr("href"))
|
||||
episode.setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
|
||||
episode.episode_number = when {
|
||||
(epsNum.isNotEmpty()) -> epsNum.toFloat()
|
||||
else -> 1F
|
||||
@ -76,8 +76,8 @@ class MiniOppai : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
private fun getAnimeFromAnimeElement(element: Element): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(element.select("div > a").first().attr("href"))
|
||||
anime.thumbnail_url = element.select("img").first().attr("data-src")
|
||||
anime.setUrlWithoutDomain(element.selectFirst("div > a")!!.attr("href"))
|
||||
anime.thumbnail_url = element.selectFirst("img")!!.attr("data-src")
|
||||
anime.title = element.select("div > a > div.tt").text()
|
||||
return anime
|
||||
}
|
||||
|
@ -61,28 +61,28 @@ class NeoNime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
private fun getAnimeFromAnimeElement(element: Element): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(element.select("a").first().attr("href"))
|
||||
anime.thumbnail_url = element.select("a > div.image > img").first().attr("data-src")
|
||||
anime.setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
|
||||
anime.thumbnail_url = element.selectFirst("a > div.image > img")!!.attr("data-src")
|
||||
anime.title = element.select("div.fixyear > div > h2").text()
|
||||
return anime
|
||||
}
|
||||
|
||||
private fun getAnimeFromEpisodeElement(element: Element): SAnime {
|
||||
val animepage = client.newCall(GET(element.select("td.bb > a").first().attr("href"))).execute().asJsoup()
|
||||
val animepage = client.newCall(GET(element.selectFirst("td.bb > a")!!.attr("href"))).execute().asJsoup()
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(animepage.select("#fixar > div.imagen > a").first().attr("href"))
|
||||
anime.thumbnail_url = animepage.select("#fixar > div.imagen > a > img").first().attr("data-src")
|
||||
anime.title = animepage.select("#fixar > div.imagen > a > img").first().attr("alt")
|
||||
anime.setUrlWithoutDomain(animepage.selectFirst("#fixar > div.imagen > a")!!.attr("href"))
|
||||
anime.thumbnail_url = animepage.selectFirst("#fixar > div.imagen > a > img")!!.attr("data-src")
|
||||
anime.title = animepage.selectFirst("#fixar > div.imagen > a > img")!!.attr("alt")
|
||||
return anime
|
||||
}
|
||||
|
||||
private fun getAnimeFromSearchElement(element: Element): SAnime {
|
||||
val url = element.select("a").first().attr("href")
|
||||
val url = element.selectFirst("a")!!.attr("href")
|
||||
val animepage = client.newCall(GET(url)).execute().asJsoup()
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(url)
|
||||
anime.title = animepage.select("#info > div:nth-child(2) > span").text()
|
||||
anime.thumbnail_url = animepage.select("div.imagen > img").first().attr("data-src")
|
||||
anime.thumbnail_url = animepage.selectFirst("div.imagen > img")!!.attr("data-src")
|
||||
anime.status = parseStatus(animepage.select("#info > div:nth-child(13) > span").text())
|
||||
anime.genre = animepage.select("#info > div:nth-child(3) > span > a").joinToString(", ") { it.text() }
|
||||
// this site didnt provide artist and author
|
||||
@ -169,7 +169,7 @@ class NeoNime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
override fun animeDetailsParse(document: Document): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.title = document.select("#info > div:nth-child(2) > span").text()
|
||||
anime.thumbnail_url = document.select("div.imagen > img").first().attr("data-src")
|
||||
anime.thumbnail_url = document.selectFirst("div.imagen > img")!!.attr("data-src")
|
||||
anime.status = parseStatus(document.select("#info > div:nth-child(13) > span").text())
|
||||
anime.genre = document.select("#info > div:nth-child(3) > span > a").joinToString(", ") { it.text() }
|
||||
// this site didnt provide artist and author
|
||||
@ -250,7 +250,7 @@ class NeoNime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
GET(link, headers = headers),
|
||||
).execute().asJsoup()
|
||||
|
||||
var iframeUrl = iframe.selectFirst("iframe").attr("src")
|
||||
var iframeUrl = iframe.selectFirst("iframe")!!.attr("src")
|
||||
|
||||
if (!iframeUrl.startsWith("http")) {
|
||||
iframeUrl = "https:$iframeUrl"
|
||||
|
@ -11,12 +11,12 @@ import uy.kohesive.injekt.injectLazy
|
||||
|
||||
@Serializable
|
||||
data class VideoConfig(
|
||||
val streams: List<Stream>
|
||||
val streams: List<Stream>,
|
||||
) {
|
||||
@Serializable
|
||||
data class Stream(
|
||||
val play_url: String,
|
||||
val format_id: Int
|
||||
val format_id: Int,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -20,14 +20,18 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
||||
|
||||
fun videosFromUrl(url: String, name: String): List<Video> {
|
||||
val headers = Headers.headersOf(
|
||||
"Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
||||
"Host", "gdriveplayer.to",
|
||||
"Referer", "https://neonime.fun/",
|
||||
"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0"
|
||||
"Accept",
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
||||
"Host",
|
||||
"gdriveplayer.to",
|
||||
"Referer",
|
||||
"https://neonime.fun/",
|
||||
"User-Agent",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0",
|
||||
)
|
||||
|
||||
val body = client.newCall(GET(url.replace(".me", ".to"), headers = headers)).execute()
|
||||
.body!!.string()
|
||||
.body.string()
|
||||
|
||||
val eval = JsUnpacker.unpackAndCombine(body)!!.replace("\\", "")
|
||||
val json = Json.decodeFromString<JsonObject>(REGEX_DATAJSON.getFirst(eval))
|
||||
@ -70,9 +74,8 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
||||
hashAlgorithm: String = "MD5",
|
||||
keyLength: Int = 32,
|
||||
ivLength: Int = 16,
|
||||
iterations: Int = 1
|
||||
iterations: Int = 1,
|
||||
): List<ByteArray>? {
|
||||
|
||||
val md = MessageDigest.getInstance(hashAlgorithm)
|
||||
val digestLength = md.getDigestLength()
|
||||
val targetKeySize = keyLength + ivLength
|
||||
@ -84,12 +87,13 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
||||
md.reset()
|
||||
|
||||
while (generatedLength < targetKeySize) {
|
||||
if (generatedLength > 0)
|
||||
if (generatedLength > 0) {
|
||||
md.update(
|
||||
generatedData,
|
||||
generatedLength - digestLength,
|
||||
digestLength
|
||||
digestLength,
|
||||
)
|
||||
}
|
||||
|
||||
md.update(password)
|
||||
md.update(salt, 0, 8)
|
||||
@ -104,7 +108,7 @@ class GdrivePlayerExtractor(private val client: OkHttpClient) {
|
||||
}
|
||||
val result = listOf(
|
||||
generatedData.copyOfRange(0, keyLength),
|
||||
generatedData.copyOfRange(keyLength, targetKeySize)
|
||||
generatedData.copyOfRange(keyLength, targetKeySize),
|
||||
)
|
||||
return result
|
||||
} catch (e: DigestException) {
|
||||
|
@ -27,8 +27,8 @@ class LinkBoxExtractor(private val client: OkHttpClient) {
|
||||
Video(
|
||||
it.jsonObject["url"].toString().replace("\"", ""),
|
||||
"${it.jsonObject["resolution"].toString().replace("\"", "")} - $name",
|
||||
it.jsonObject["url"].toString().replace("\"", "")
|
||||
)
|
||||
it.jsonObject["url"].toString().replace("\"", ""),
|
||||
),
|
||||
)
|
||||
}
|
||||
return videoList
|
||||
|
@ -93,8 +93,8 @@ class Oploverz : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
private fun getAnimeFromAnimeElement(element: Element): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(element.select("div > a").first().attr("href"))
|
||||
anime.thumbnail_url = element.select("div > a > div.limit > img").first().attr("src")
|
||||
anime.setUrlWithoutDomain(element.selectFirst("div > a")!!.attr("href"))
|
||||
anime.thumbnail_url = element.selectFirst("div > a > div.limit > img")!!.attr("src")
|
||||
anime.title = element.select("div > a > div.tt > h2").text()
|
||||
return anime
|
||||
}
|
||||
@ -132,9 +132,11 @@ class Oploverz : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
val zippy = document.select(patternZippy).mapNotNull {
|
||||
runCatching { zippyFromElement(it) }.getOrNull()
|
||||
}
|
||||
val google = if (iframe == null) { mutableListOf() } else try {
|
||||
googleLinkFromElement(iframe)
|
||||
} catch (e: Exception) { mutableListOf() }
|
||||
val google = if (iframe == null) { mutableListOf() } else {
|
||||
try {
|
||||
googleLinkFromElement(iframe)
|
||||
} catch (e: Exception) { mutableListOf() }
|
||||
}
|
||||
|
||||
return google + zippy
|
||||
}
|
||||
@ -143,7 +145,7 @@ class Oploverz : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
private fun googleLinkFromElement(iframe: Element): List<Video> {
|
||||
val iframeResponse = client.newCall(GET(iframe.attr("src"))).execute()
|
||||
val streams = iframeResponse.body!!.string().substringAfter("\"streams\":[").substringBefore("]")
|
||||
val streams = iframeResponse.body.string().substringAfter("\"streams\":[").substringBefore("]")
|
||||
val videoList = mutableListOf<Video>()
|
||||
streams.split("},").reversed().forEach {
|
||||
val url = unescape(it.substringAfter("{\"play_url\":\"").substringBefore("\""))
|
||||
@ -250,15 +252,24 @@ class Oploverz : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
val delimiter = input[i]
|
||||
i++ // consume letter or backslash
|
||||
if (delimiter == '\\' && i < input.length) {
|
||||
|
||||
// consume first after backslash
|
||||
val ch = input[i]
|
||||
i++
|
||||
if (ch == '\\' || ch == '/' || ch == '"' || ch == '\'') {
|
||||
builder.append(ch)
|
||||
} else if (ch == 'n') builder.append('\n') else if (ch == 'r') builder.append('\r') else if (ch == 't') builder.append(
|
||||
'\t'
|
||||
) else if (ch == 'b') builder.append('\b') else if (ch == 'f') builder.append('\u000C') else if (ch == 'u') {
|
||||
} else if (ch == 'n') {
|
||||
builder.append('\n')
|
||||
} else if (ch == 'r') {
|
||||
builder.append('\r')
|
||||
} else if (ch == 't') {
|
||||
builder.append(
|
||||
'\t',
|
||||
)
|
||||
} else if (ch == 'b') {
|
||||
builder.append('\b')
|
||||
} else if (ch == 'f') {
|
||||
builder.append('\u000C')
|
||||
} else if (ch == 'u') {
|
||||
val hex = StringBuilder()
|
||||
|
||||
// expect 4 digits
|
||||
|
@ -101,8 +101,8 @@ class OtakuDesu : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(element.select("div.thumb > a").first().attr("href"))
|
||||
anime.thumbnail_url = element.select("div.thumb > a > div.thumbz > img").first().attr("src")
|
||||
anime.setUrlWithoutDomain(element.selectFirst("div.thumb > a")!!.attr("href"))
|
||||
anime.thumbnail_url = element.selectFirst("div.thumb > a > div.thumbz > img")!!.attr("src")
|
||||
anime.title = element.select("div.thumb > a > div.thumbz > h2").text()
|
||||
return anime
|
||||
}
|
||||
@ -115,8 +115,8 @@ class OtakuDesu : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
override fun popularAnimeFromElement(element: Element): SAnime {
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(element.select("div.thumb > a").first().attr("href"))
|
||||
anime.thumbnail_url = element.select("div.thumb > a > div.thumbz > img").first().attr("src")
|
||||
anime.setUrlWithoutDomain(element.selectFirst("div.thumb > a")!!.attr("href"))
|
||||
anime.thumbnail_url = element.selectFirst("div.thumb > a > div.thumbz > img")!!.attr("src")
|
||||
anime.title = element.select("div.thumb > a > div.thumbz > h2").text()
|
||||
return anime
|
||||
}
|
||||
@ -133,16 +133,16 @@ class OtakuDesu : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
val anime = SAnime.create()
|
||||
anime.setUrlWithoutDomain(
|
||||
when (ui) {
|
||||
"search" -> element.select("h2 > a").first().attr("href")
|
||||
"search" -> element.selectFirst("h2 > a")!!.attr("href")
|
||||
"genres" -> element.select(".col-anime-title > a").attr("href")
|
||||
else -> element.select("div.thumb > a").first().attr("href")
|
||||
}
|
||||
else -> element.selectFirst("div.thumb > a")!!.attr("href")
|
||||
},
|
||||
)
|
||||
|
||||
anime.thumbnail_url = when (ui) {
|
||||
"search" -> element.select("img").first().attr("src")
|
||||
"search" -> element.selectFirst("img")!!.attr("src")
|
||||
"genres" -> element.select(".col-anime-cover > img").attr("src")
|
||||
else -> element.select("div.thumb > a > div.thumbz > img").first().attr("src")
|
||||
else -> element.selectFirst("div.thumb > a > div.thumbz > img")!!.attr("src")
|
||||
}
|
||||
anime.title = when (ui) {
|
||||
"search" -> element.select("h2 > a").text().replace(" Subtitle Indonesia", "")
|
||||
@ -255,7 +255,7 @@ class OtakuDesu : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
// filter
|
||||
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
|
||||
AnimeFilter.Header("Text search ignores filters"),
|
||||
GenreFilter()
|
||||
GenreFilter(),
|
||||
)
|
||||
|
||||
private class GenreFilter : UriPartFilter(
|
||||
@ -298,7 +298,7 @@ class OtakuDesu : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
Pair("Supernatural", "supernatural"),
|
||||
Pair("Thriller", "thriller"),
|
||||
Pair("Vampire", "vampire"),
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
||||
|
Reference in New Issue
Block a user