forked from AlmightyHak/extensions-source
Initial commit
This commit is contained in:
commit
98ed7e8839
2263 changed files with 108711 additions and 0 deletions
16
src/all/chineseanime/build.gradle
Normal file
16
src/all/chineseanime/build.gradle
Normal file
|
@ -0,0 +1,16 @@
|
|||
ext {
|
||||
extName = 'ChineseAnime'
|
||||
extClass = '.ChineseAnime'
|
||||
themePkg = 'animestream'
|
||||
baseUrl = 'https://www.chineseanime.vip'
|
||||
overrideVersionCode = 8
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
||||
dependencies {
|
||||
implementation(project(":lib:dailymotion-extractor"))
|
||||
implementation(project(":lib:streamwish-extractor"))
|
||||
implementation(project(":lib:streamvid-extractor"))
|
||||
implementation(project(":lib:playlist-utils"))
|
||||
}
|
BIN
src/all/chineseanime/res/mipmap-hdpi/ic_launcher.png
Normal file
BIN
src/all/chineseanime/res/mipmap-hdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
BIN
src/all/chineseanime/res/mipmap-mdpi/ic_launcher.png
Normal file
BIN
src/all/chineseanime/res/mipmap-mdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
BIN
src/all/chineseanime/res/mipmap-xhdpi/ic_launcher.png
Normal file
BIN
src/all/chineseanime/res/mipmap-xhdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
BIN
src/all/chineseanime/res/mipmap-xxhdpi/ic_launcher.png
Normal file
BIN
src/all/chineseanime/res/mipmap-xxhdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
src/all/chineseanime/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
BIN
src/all/chineseanime/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
BIN
src/all/chineseanime/res/web_hi_res_512.png
Normal file
BIN
src/all/chineseanime/res/web_hi_res_512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 207 KiB |
|
@ -0,0 +1,88 @@
|
|||
package eu.kanade.tachiyomi.animeextension.all.chineseanime
|
||||
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.animeextension.all.chineseanime.extractors.VatchusExtractor
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.lib.dailymotionextractor.DailymotionExtractor
|
||||
import eu.kanade.tachiyomi.lib.streamvidextractor.StreamVidExtractor
|
||||
import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
|
||||
import eu.kanade.tachiyomi.multisrc.animestream.AnimeStream
|
||||
|
||||
class ChineseAnime : AnimeStream(
|
||||
"all",
|
||||
"ChineseAnime",
|
||||
"https://www.chineseanime.vip",
|
||||
) {
|
||||
|
||||
// =============================== Search ===============================
|
||||
override fun searchAnimeNextPageSelector() = "div.mrgn > a.r"
|
||||
|
||||
// =========================== Anime Details ============================
|
||||
override val animeDescriptionSelector = ".entry-content"
|
||||
|
||||
// ============================== Filters ===============================
|
||||
override val filtersSelector = "div.filter > ul"
|
||||
|
||||
// ============================ Video Links =============================
|
||||
private val dailymotionExtractor by lazy { DailymotionExtractor(client, headers) }
|
||||
private val streamwishExtractor by lazy { StreamWishExtractor(client, headers) }
|
||||
private val streamvidExtractor by lazy { StreamVidExtractor(client) }
|
||||
private val vatchusExtractor by lazy { VatchusExtractor(client, headers) }
|
||||
|
||||
override fun getVideoList(url: String, name: String): List<Video> {
|
||||
val prefix = "$name - "
|
||||
return when {
|
||||
url.contains("dailymotion") -> dailymotionExtractor.videosFromUrl(url, prefix)
|
||||
url.contains("embedwish") -> streamwishExtractor.videosFromUrl(url, prefix)
|
||||
url.contains("vatchus") -> vatchusExtractor.videosFromUrl(url, prefix)
|
||||
url.contains("donghua.xyz/v/") -> streamvidExtractor.videosFromUrl(url, prefix, true)
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
// ============================== Settings ==============================
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
super.setupPreferenceScreen(screen) // Quality preferences
|
||||
val videoLangPref = ListPreference(screen.context).apply {
|
||||
key = PREF_LANG_KEY
|
||||
title = PREF_LANG_TITLE
|
||||
entries = PREF_LANG_VALUES
|
||||
entryValues = PREF_LANG_VALUES
|
||||
setDefaultValue(PREF_LANG_DEFAULT)
|
||||
summary = "%s"
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val selected = newValue as String
|
||||
val index = findIndexOfValue(selected)
|
||||
val entry = entryValues[index] as String
|
||||
preferences.edit().putString(key, entry).commit()
|
||||
}
|
||||
}
|
||||
|
||||
screen.addPreference(videoLangPref)
|
||||
}
|
||||
|
||||
// ============================= Utilities ==============================
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
val quality = preferences.getString(prefQualityKey, prefQualityDefault)!!
|
||||
val language = preferences.getString(PREF_LANG_KEY, PREF_LANG_DEFAULT)!!
|
||||
|
||||
return sortedWith(
|
||||
compareBy(
|
||||
{ it.quality.contains(quality) },
|
||||
{ it.quality.contains(language, true) },
|
||||
),
|
||||
).reversed()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PREF_LANG_KEY = "preferred_language"
|
||||
private const val PREF_LANG_TITLE = "Preferred Video Language"
|
||||
private const val PREF_LANG_DEFAULT = "All Sub"
|
||||
private val PREF_LANG_VALUES = arrayOf(
|
||||
"All Sub", "Arabic", "English", "Indonesia", "Persian", "Malay",
|
||||
"Polish", "Portuguese", "Spanish", "Thai", "Vietnamese",
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package eu.kanade.tachiyomi.animeextension.all.chineseanime.extractors
|
||||
|
||||
import android.util.Base64
|
||||
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 okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
|
||||
class VatchusExtractor(private val client: OkHttpClient, private val headers: Headers) {
|
||||
private val playlistUtils by lazy { PlaylistUtils(client, headers) }
|
||||
|
||||
fun videosFromUrl(url: String, prefix: String): List<Video> {
|
||||
val doc = client.newCall(GET(url, headers)).execute()
|
||||
.asJsoup()
|
||||
|
||||
val script = doc.selectFirst("script:containsData(document.write)")
|
||||
?.data()
|
||||
?: return emptyList()
|
||||
|
||||
val numberList = script.substringAfter(" = [").substringBefore("];")
|
||||
.replace("\"", "")
|
||||
.split(",")
|
||||
.map(String::trim)
|
||||
.filter(String::isNotBlank)
|
||||
.map { String(Base64.decode(it, Base64.DEFAULT)) }
|
||||
.mapNotNull { it.filter(Char::isDigit).toIntOrNull() }
|
||||
|
||||
val offset = numberList.first() - 60
|
||||
val decodedData = numberList.joinToString("") {
|
||||
Char(it - offset).toString()
|
||||
}.trim()
|
||||
|
||||
val playlistUrl = decodedData.substringAfter("file:'").substringBefore("'")
|
||||
val subs = decodedData.substringAfter("tracks:[").substringBefore("]")
|
||||
.split("{")
|
||||
.drop(1)
|
||||
.filter { it.contains(""""kind":"captions"""") }
|
||||
.mapNotNull {
|
||||
val trackUrl = it.substringAfter("file\":\"").substringBefore('"')
|
||||
.takeIf { link -> link.startsWith("http") }
|
||||
?: return@mapNotNull null
|
||||
val language = it.substringAfter("label\":\"").substringBefore('"')
|
||||
Track(trackUrl, language)
|
||||
}
|
||||
|
||||
return playlistUtils.extractFromHls(
|
||||
playlistUrl,
|
||||
url,
|
||||
subtitleList = subs,
|
||||
videoNameGen = { prefix + it },
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue