feat(all/hikari): Replace streamwish with vidhide (#3208)

This commit is contained in:
Secozzi 2024-05-01 20:28:32 +00:00 committed by GitHub
parent 2d15f1e7aa
commit 218079d218
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 129 additions and 6 deletions

View File

@ -0,0 +1,7 @@
plugins {
id("lib-android")
}
dependencies {
implementation(project(":lib:playlist-utils"))
}

View File

@ -0,0 +1,64 @@
package eu.kanade.tachiyomi.lib.vidhideextractor
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 kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json
import okhttp3.Headers
import okhttp3.OkHttpClient
class VidHideExtractor(private val client: OkHttpClient, private val headers: Headers) {
private val playlistUtils by lazy { PlaylistUtils(client, headers) }
val json = Json {
isLenient = true
ignoreUnknownKeys = true
}
fun videosFromUrl(url: String, videoNameGen: (String) -> String = { quality -> "VidHide - $quality" }): List<Video> {
val doc = client.newCall(GET(url, headers)).execute()
.asJsoup()
val scriptBody = doc.selectFirst("script:containsData(m3u8)")
?.data()
?: return emptyList()
val masterUrl = scriptBody
.substringAfter("source", "")
.substringAfter("file:\"", "")
.substringBefore("\"", "")
.takeIf(String::isNotBlank)
?: return emptyList()
val subtitleList = try {
val subtitleStr = scriptBody
.substringAfter("tracks")
.substringAfter("[")
.substringBefore("]")
val parsed = json.decodeFromString<List<TrackDto>>("[$subtitleStr]")
parsed.filter { it.kind.equals("captions", true) }
.map { Track(it.file, it.label!!) }
} catch (e: SerializationException) {
emptyList()
}
return playlistUtils.extractFromHls(
masterUrl,
url,
videoNameGen = videoNameGen,
subtitleList = subtitleList,
)
}
@Serializable
class TrackDto(
val file: String,
val kind: String,
val label: String? = null,
)
}

View File

@ -1,12 +1,12 @@
ext { ext {
extName = 'Hikari' extName = 'Hikari'
extClass = '.Hikari' extClass = '.Hikari'
extVersionCode = 3 extVersionCode = 4
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"
dependencies { dependencies {
implementation(project(':lib:filemoon-extractor')) implementation(project(':lib:filemoon-extractor'))
implementation(project(':lib:streamwish-extractor')) implementation(project(':lib:vidhide-extractor'))
} }

View File

@ -1,5 +1,9 @@
package eu.kanade.tachiyomi.animeextension.all.hikari package eu.kanade.tachiyomi.animeextension.all.hikari
import android.app.Application
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.AnimesPage import eu.kanade.tachiyomi.animesource.model.AnimesPage
@ -8,7 +12,7 @@ import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor import eu.kanade.tachiyomi.lib.vidhideextractor.VidHideExtractor
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import eu.kanade.tachiyomi.util.parseAs import eu.kanade.tachiyomi.util.parseAs
@ -19,8 +23,10 @@ import okhttp3.Response
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class Hikari : ParsedAnimeHttpSource() { class Hikari : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
override val name = "Hikari" override val name = "Hikari"
@ -35,6 +41,10 @@ class Hikari : ParsedAnimeHttpSource() {
add("Referer", "$baseUrl/") add("Referer", "$baseUrl/")
} }
private val preferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
// ============================== Popular =============================== // ============================== Popular ===============================
override fun popularAnimeRequest(page: Int): Request { override fun popularAnimeRequest(page: Int): Request {
@ -206,7 +216,7 @@ class Hikari : ParsedAnimeHttpSource() {
// ============================ Video Links ============================= // ============================ Video Links =============================
private val filemoonExtractor by lazy { FilemoonExtractor(client) } private val filemoonExtractor by lazy { FilemoonExtractor(client) }
private val streamWishExtractor by lazy { StreamWishExtractor(client, headers) } private val vidHideExtractor by lazy { VidHideExtractor(client, headers) }
private val embedRegex = Regex("""getEmbed\(\s*(\d+)\s*,\s*(\d+)\s*,\s*'(\d+)'""") private val embedRegex = Regex("""getEmbed\(\s*(\d+)\s*,\s*(\d+)\s*,\s*'(\d+)'""")
override fun videoListRequest(episode: SEpisode): Request { override fun videoListRequest(episode: SEpisode): Request {
@ -248,7 +258,7 @@ class Hikari : ParsedAnimeHttpSource() {
} }
private fun getVideosFromEmbed(embedUrl: String, name: String): List<Video> = when { private fun getVideosFromEmbed(embedUrl: String, name: String): List<Video> = when {
name.contains("streamwish", true) -> streamWishExtractor.videosFromUrl(embedUrl, name) name.contains("vidhide", true) -> vidHideExtractor.videosFromUrl(embedUrl)
embedUrl.contains("filemoon", true) -> { embedUrl.contains("filemoon", true) -> {
filemoonExtractor.videosFromUrl(embedUrl, prefix = "$name - ", headers = headers) filemoonExtractor.videosFromUrl(embedUrl, prefix = "$name - ", headers = headers)
} }
@ -257,6 +267,17 @@ class Hikari : ParsedAnimeHttpSource() {
override fun videoListSelector() = ".server-item:has(a[onclick~=getEmbed])" override fun videoListSelector() = ".server-item:has(a[onclick~=getEmbed])"
override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!
return sortedWith(
compareBy(
{ it.quality.contains(quality) },
{ QUALITY_REGEX.find(it.quality)?.groupValues?.get(1)?.toIntOrNull() ?: 0 },
),
).reversed()
}
override fun videoFromElement(element: Element): Video = override fun videoFromElement(element: Element): Video =
throw UnsupportedOperationException() throw UnsupportedOperationException()
@ -277,4 +298,35 @@ class Hikari : ParsedAnimeHttpSource() {
val totalPages: Int, val totalPages: Int,
) )
} }
companion object {
private val QUALITY_REGEX = Regex("""(\d+)p""")
private const val PREF_QUALITY_KEY = "preferred_quality"
private const val PREF_QUALITY_DEFAULT = "1080"
private val PREF_QUALITY_VALUES = arrayOf("1080", "720", "480", "360")
private val PREF_QUALITY_ENTRIES = PREF_QUALITY_VALUES.map {
"${it}p"
}.toTypedArray()
}
// ============================== Settings ==============================
override fun setupPreferenceScreen(screen: PreferenceScreen) {
ListPreference(screen.context).apply {
key = PREF_QUALITY_KEY
title = "Preferred quality"
entries = PREF_QUALITY_ENTRIES
entryValues = PREF_QUALITY_VALUES
setDefaultValue(PREF_QUALITY_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()
}
}.also(screen::addPreference)
}
} }