Initial commit

This commit is contained in:
almightyhak 2024-06-20 11:54:12 +07:00
commit 98ed7e8839
2263 changed files with 108711 additions and 0 deletions

View 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"))
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

View file

@ -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",
)
}
}

View file

@ -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 },
)
}
}