diff --git a/src/zh/nivod/build.gradle b/src/zh/nivod/build.gradle new file mode 100644 index 00000000..9e2a6e3b --- /dev/null +++ b/src/zh/nivod/build.gradle @@ -0,0 +1,7 @@ +ext { + extName = 'Nivod' + extClass = '.Nivod' + extVersionCode = 1 +} + +apply from: "$rootDir/common.gradle" diff --git a/src/zh/nivod/res/mipmap-hdpi/ic_launcher.png b/src/zh/nivod/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..0c6171bc Binary files /dev/null and b/src/zh/nivod/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/zh/nivod/res/mipmap-mdpi/ic_launcher.png b/src/zh/nivod/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..7de968da Binary files /dev/null and b/src/zh/nivod/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/zh/nivod/res/mipmap-xhdpi/ic_launcher.png b/src/zh/nivod/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..90699f12 Binary files /dev/null and b/src/zh/nivod/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/zh/nivod/res/mipmap-xxhdpi/ic_launcher.png b/src/zh/nivod/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..76bbfde1 Binary files /dev/null and b/src/zh/nivod/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/zh/nivod/res/mipmap-xxxhdpi/ic_launcher.png b/src/zh/nivod/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..b671a4d9 Binary files /dev/null and b/src/zh/nivod/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/zh/nivod/src/eu/kanade/tachiyomi/animeextension/zh/nivod/Filters.kt b/src/zh/nivod/src/eu/kanade/tachiyomi/animeextension/zh/nivod/Filters.kt new file mode 100644 index 00000000..d2a9bb4c --- /dev/null +++ b/src/zh/nivod/src/eu/kanade/tachiyomi/animeextension/zh/nivod/Filters.kt @@ -0,0 +1,38 @@ +package eu.kanade.tachiyomi.animeextension.zh.nivod + +import eu.kanade.tachiyomi.animesource.model.AnimeFilter +import kotlinx.serialization.Serializable + +open class QueryFilter( + name: String, + private val options: List>, + val key: String, +) : + AnimeFilter.Select(name, options.map { it.first }.toTypedArray()) { + val selected: String + get() = options[state].second +} + +class ChannelFilter : QueryFilter( + "分类", + listOf( + "动漫" to "anime", + "电影" to "movie", + "电视剧" to "tv", + "综艺" to "show", + ), + "channel", +) + +class YearFilter(options: List>) : QueryFilter("年份", options, "year") + +class TypeFilter(options: List>) : QueryFilter("类型", options, "showtype") + +class RegionFilter(options: List>) : QueryFilter("地区", options, "region") + +@Serializable +internal class FilterConfig( + val regions: Map, + val types: Map, + val years: Map, +) diff --git a/src/zh/nivod/src/eu/kanade/tachiyomi/animeextension/zh/nivod/Nivod.kt b/src/zh/nivod/src/eu/kanade/tachiyomi/animeextension/zh/nivod/Nivod.kt new file mode 100644 index 00000000..894cce2d --- /dev/null +++ b/src/zh/nivod/src/eu/kanade/tachiyomi/animeextension/zh/nivod/Nivod.kt @@ -0,0 +1,308 @@ +package eu.kanade.tachiyomi.animeextension.zh.nivod + +import android.app.Application +import android.content.SharedPreferences +import eu.kanade.tachiyomi.animesource.model.AnimeFilter +import eu.kanade.tachiyomi.animesource.model.AnimeFilterList +import eu.kanade.tachiyomi.animesource.model.AnimesPage +import eu.kanade.tachiyomi.animesource.model.SAnime +import eu.kanade.tachiyomi.animesource.model.SEpisode +import eu.kanade.tachiyomi.animesource.model.Video +import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource +import eu.kanade.tachiyomi.network.GET +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.Request +import okhttp3.Response +import org.jsoup.nodes.Element +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import uy.kohesive.injekt.injectLazy +import java.net.URLEncoder +import java.util.Calendar + +class Nivod : AnimeHttpSource() { + override val baseUrl: String + get() = "https://www.nivod.cc" + override val lang: String + get() = "zh" + override val name: String + get() = "泥视频" + override val supportsLatest: Boolean + get() = true + + private val json by injectLazy() + private val preferences: SharedPreferences by lazy { + Injekt.get().getSharedPreferences("source_$id", 0x0000) + } + + override fun animeDetailsParse(response: Response): SAnime { + val doc = response.asJsoup() + return SAnime.create().apply { + thumbnail_url = baseUrl + doc.select(".left-img-c img").attr("src") + title = doc.select(".right-title").text() + genre = + doc.select(".right-label-c .right-label").joinToString { it.text() } + author = doc.select(".right-type-c:nth-child(4) .right-label").text() + artist = doc.select(".right-type-c:nth-child(5) .right-label").text() + description = doc.select(".right-type-c:nth-child(6) .right-label").text() + } + } + + override fun episodeListParse(response: Response): List { + val doc = response.asJsoup() + return doc.select(".list-ruku a").map { + SEpisode.create().apply { + url = it.attr("href") + name = it.select(".item").text() + } + } + } + + override fun videoListRequest(episode: SEpisode): Request { + val doc = client.newCall(super.videoListRequest(episode)).execute().asJsoup() + val path = doc.selectFirst("script:containsData(xhr_playinfo)")!!.data() + .substringAfter("url = '").substringBefore("'") + return GET(baseUrl + path) + } + + override fun videoListParse(response: Response): List