diff --git a/src/zh/hanime1/build.gradle b/src/zh/hanime1/build.gradle index f1b59699..85bc719b 100644 --- a/src/zh/hanime1/build.gradle +++ b/src/zh/hanime1/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Hanime1' extClass = '.Hanime1' - extVersionCode = 5 + extVersionCode = 4 isNsfw = true } diff --git a/src/zh/hanime1/src/eu/kanade/tachiyomi/animeextension/zh/hanime1/Hanime1.kt b/src/zh/hanime1/src/eu/kanade/tachiyomi/animeextension/zh/hanime1/Hanime1.kt index 311e7597..ab8e354b 100644 --- a/src/zh/hanime1/src/eu/kanade/tachiyomi/animeextension/zh/hanime1/Hanime1.kt +++ b/src/zh/hanime1/src/eu/kanade/tachiyomi/animeextension/zh/hanime1/Hanime1.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.animeextension.zh.hanime1 import android.app.Application import android.content.SharedPreferences -import android.util.Log import androidx.preference.ListPreference import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource @@ -17,15 +16,12 @@ import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.awaitSuccess import eu.kanade.tachiyomi.util.asJsoup import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonPrimitive import okhttp3.Cookie @@ -69,32 +65,14 @@ class Hanime1 : AnimeHttpSource(), ConfigurableAnimeSource { } override fun animeDetailsParse(response: Response): SAnime { - val doc = response.asJsoup() + val jsoup = response.asJsoup() return SAnime.create().apply { - genre = doc.select(".single-video-tag").not("[data-toggle]").eachText().joinToString() - author = doc.select("#video-artist-name").text() - doc.select("script[type=application/ld+json]").first()?.data()?.let { + genre = jsoup.select(".single-video-tag").not("[data-toggle]").eachText().joinToString() + author = jsoup.select("#video-artist-name").text() + jsoup.select("script[type=application/ld+json]").first()?.data()?.let { val info = json.decodeFromString(it).jsonObject title = info["name"]!!.jsonPrimitive.content description = info["description"]!!.jsonPrimitive.content - thumbnail_url = info["thumbnailUrl"]?.jsonArray?.get(0)?.jsonPrimitive?.content - } - val type = doc.select("a#video-artist-name + a").text().trim() - if (type == "裏番" || type == "泡麵番") { - // Use the series cover image for bangumi entries instead of the episode image. - runBlocking { - try { - val animesPage = - getSearchAnime( - 1, - title, - AnimeFilterList(GenreFilter(arrayOf("", type)).apply { state = 1 }), - ) - thumbnail_url = animesPage.animes.first().thumbnail_url - } catch (e: Exception) { - Log.e(name, "Failed to get bangumi cover image") - } - } } } } @@ -159,7 +137,7 @@ class Hanime1 : AnimeHttpSource(), ConfigurableAnimeSource { override fun searchAnimeParse(response: Response): AnimesPage { val jsoup = response.asJsoup() - val nodes = jsoup.select("div.search-doujin-videos.hidden-xs:not(:has(a[target=_blank]))") + val nodes = jsoup.select("div.search-doujin-videos.hidden-xs") val list = if (nodes.isNotEmpty()) { nodes.map { SAnime.create().apply { @@ -238,12 +216,11 @@ class Hanime1 : AnimeHttpSource(), ConfigurableAnimeSource { return chain.proceed(chain.request()) } - @OptIn(DelicateCoroutinesApi::class) private fun updateFilters() { filterUpdateState = FilterUpdateState.UPDATING val exceptionHandler = CoroutineExceptionHandler { _, _ -> filterUpdateState = FilterUpdateState.FAILED } - GlobalScope.launch(Dispatchers.IO + exceptionHandler) { + CoroutineScope(Dispatchers.IO + exceptionHandler).launch { val jsoup = client.newCall(GET("$baseUrl/search")).awaitSuccess().asJsoup() val genreList = jsoup.select("div.genre-option div.hentai-sort-options").eachText() val sortList = diff --git a/src/zh/xfani/build.gradle b/src/zh/xfani/build.gradle index 937a972a..89b38f74 100644 --- a/src/zh/xfani/build.gradle +++ b/src/zh/xfani/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Xfani' extClass = '.Xfani' - extVersionCode = 6 + extVersionCode = 5 } apply from: "$rootDir/common.gradle" diff --git a/src/zh/xfani/src/eu/kanade/tachiyomi/animeextension/zh/xfani/Xfani.kt b/src/zh/xfani/src/eu/kanade/tachiyomi/animeextension/zh/xfani/Xfani.kt index add3a049..92583f32 100644 --- a/src/zh/xfani/src/eu/kanade/tachiyomi/animeextension/zh/xfani/Xfani.kt +++ b/src/zh/xfani/src/eu/kanade/tachiyomi/animeextension/zh/xfani/Xfani.kt @@ -20,9 +20,8 @@ import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.awaitSuccess import eu.kanade.tachiyomi.util.asJsoup import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.serialization.json.Json import kotlinx.serialization.json.jsonObject @@ -54,7 +53,7 @@ enum class FilterUpdateState { class Xfani : AnimeHttpSource(), ConfigurableAnimeSource { override val baseUrl: String - get() = "https://dm.xifanacg.com" + get() = "https://dick.xfani.com" override val lang: String get() = "zh" override val name: String @@ -118,16 +117,10 @@ class Xfani : AnimeHttpSource(), ConfigurableAnimeSource { } override fun animeDetailsParse(response: Response): SAnime { - val doc = response.asJsoup() + val jsoup = response.asJsoup() return SAnime.create().apply { - description = doc.select("#height_limit.text").text() - title = doc.select(".slide-info-title").text() - author = doc.select(".slide-info:contains(导演 :)").text().removePrefix("导演 :") - .removeSuffix(",") - artist = doc.select(".slide-info:contains(演员 :)").text().removePrefix("演员 :") - .removeSuffix(",") - genre = doc.select(".slide-info:contains(类型 :)").text().removePrefix("类型 :") - .removeSuffix(",").replace(",", ", ") + description = jsoup.select("#height_limit.text").text() + title = jsoup.select(".slide-info-title").text() } } @@ -241,13 +234,19 @@ class Xfani : AnimeHttpSource(), ConfigurableAnimeSource { return vodListToAnimePageList(response) } val jsoup = response.asJsoup() - val items = jsoup.select("div.search-list") + val items = jsoup.select("div.public-list-box.search-box.flex.rel") val animeList = items.map { item -> SAnime.create().apply { - title = item.select("div.detail-info > a").text() - url = item.select("div.detail-info > a").attr("href") + title = item.select(".thumb-txt").text() + url = item.select("div.left.public-list-bj a.public-list-exp").attr("href") thumbnail_url = - item.select("div.detail-pic img[data-src]").attr("data-src") + item.select("div.left.public-list-bj img[data-src]").attr("data-src") + author = item.select("div.thumb-actor").text().removeSuffix("/") + artist = item.select("div.thumb-director").text().removeSuffix("/") + description = item.select(".thumb-blurb").text() + genre = item.select("div.thumb-else").text() + val statusString = item.select("div.left.public-list-bj .public-list-prb").text() + status = STATUS_STR_MAPPING.getOrElse(statusString) { SAnime.ONGOING } } } val tip = jsoup.select("div.pages div.page-tip").text() @@ -260,13 +259,12 @@ class Xfani : AnimeHttpSource(), ConfigurableAnimeSource { return numbers.size == 2 && numbers[0] != numbers[1] } - @OptIn(DelicateCoroutinesApi::class) private fun updateFilter() { filterState = FilterUpdateState.UPDATING val handler = CoroutineExceptionHandler { _, _ -> filterState = FilterUpdateState.FAILED } - GlobalScope.launch(Dispatchers.IO + handler) { + CoroutineScope(Dispatchers.IO + handler).launch { val jsoup = client.newCall(GET("$baseUrl/show/1/html")).awaitSuccess().asJsoup() // update class and year filter type val classList = jsoup.select("li[data-type=class]").eachAttr("data-val") @@ -395,5 +393,9 @@ class Xfani : AnimeHttpSource(), ConfigurableAnimeSource { const val PREF_KEY_FILTER_YEAR = "PREF_KEY_FILTER_YEAR" const val DEFAULT_VIDEO_SOURCE = "0" + + val STATUS_STR_MAPPING = mapOf( + "已完结" to SAnime.COMPLETED, + ) } }