feat(tr/anizm): Add host & fansub selection preferences + more extractors (#2184)
This commit is contained in:
@ -8,20 +8,23 @@ ext {
|
|||||||
extName = 'Anizm'
|
extName = 'Anizm'
|
||||||
pkgNameSuffix = 'tr.anizm'
|
pkgNameSuffix = 'tr.anizm'
|
||||||
extClass = '.Anizm'
|
extClass = '.Anizm'
|
||||||
extVersionCode = 2
|
extVersionCode = 3
|
||||||
libVersion = '13'
|
libVersion = '13'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(':lib-uqload-extractor'))
|
implementation(project(":lib-dood-extractor"))
|
||||||
|
implementation(project(":lib-filemoon-extractor"))
|
||||||
|
implementation(project(":lib-gdriveplayer-extractor"))
|
||||||
|
implementation(project(":lib-mp4upload-extractor"))
|
||||||
|
implementation(project(":lib-mytv-extractor"))
|
||||||
|
implementation(project(":lib-okru-extractor"))
|
||||||
implementation(project(":lib-sendvid-extractor"))
|
implementation(project(":lib-sendvid-extractor"))
|
||||||
implementation(project(":lib-sibnet-extractor"))
|
implementation(project(":lib-sibnet-extractor"))
|
||||||
implementation(project(":lib-dood-extractor"))
|
implementation(project(":lib-streamtape-extractor"))
|
||||||
implementation(project(":lib-mp4upload-extractor"))
|
implementation(project(':lib-uqload-extractor'))
|
||||||
implementation(project(":lib-voe-extractor"))
|
implementation(project(":lib-voe-extractor"))
|
||||||
implementation(project(":lib-filemoon-extractor"))
|
|
||||||
implementation(project(":lib-yourupload-extractor"))
|
implementation(project(":lib-yourupload-extractor"))
|
||||||
implementation(project(":lib-gdriveplayer-extractor"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package eu.kanade.tachiyomi.animeextension.tr.anizm
|
package eu.kanade.tachiyomi.animeextension.tr.anizm
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
|
import androidx.preference.MultiSelectListPreference
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import eu.kanade.tachiyomi.animeextension.tr.anizm.AnizmFilters.applyFilterParams
|
import eu.kanade.tachiyomi.animeextension.tr.anizm.AnizmFilters.applyFilterParams
|
||||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||||
@ -15,8 +18,11 @@ import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
|
|||||||
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
|
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
|
||||||
import eu.kanade.tachiyomi.lib.gdriveplayerextractor.GdrivePlayerExtractor
|
import eu.kanade.tachiyomi.lib.gdriveplayerextractor.GdrivePlayerExtractor
|
||||||
import eu.kanade.tachiyomi.lib.mp4uploadextractor.Mp4uploadExtractor
|
import eu.kanade.tachiyomi.lib.mp4uploadextractor.Mp4uploadExtractor
|
||||||
|
import eu.kanade.tachiyomi.lib.mytvextractor.MytvExtractor
|
||||||
|
import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
|
||||||
import eu.kanade.tachiyomi.lib.sendvidextractor.SendvidExtractor
|
import eu.kanade.tachiyomi.lib.sendvidextractor.SendvidExtractor
|
||||||
import eu.kanade.tachiyomi.lib.sibnetextractor.SibnetExtractor
|
import eu.kanade.tachiyomi.lib.sibnetextractor.SibnetExtractor
|
||||||
|
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
|
||||||
import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
|
import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
|
||||||
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
|
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
|
||||||
import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
|
import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
|
||||||
@ -35,6 +41,7 @@ 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 org.jsoup.select.Elements
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
@ -182,22 +189,47 @@ class Anizm : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
|
|||||||
|
|
||||||
override fun videoListParse(response: Response): List<Video> {
|
override fun videoListParse(response: Response): List<Video> {
|
||||||
val doc = response.use { it.asJsoup() }
|
val doc = response.use { it.asJsoup() }
|
||||||
val fansubUrls = doc.select("div#fansec > a").map { it.attr("translator") }
|
|
||||||
val playerUrls = fansubUrls.flatMap {
|
val fansubUrls = doc.select("div#fansec > a")
|
||||||
|
.filterSubs()
|
||||||
|
.map { it.text().fixedFansubName() to it.attr("translator") }
|
||||||
|
.ifEmpty {
|
||||||
|
throw Exception("No fansubs available! Have you filtered them out?")
|
||||||
|
}
|
||||||
|
|
||||||
|
val chosenHosts = preferences.getStringSet(PREF_HOSTS_SELECTION_KEY, PREF_HOSTS_SELECTION_DEFAULT)!!
|
||||||
|
|
||||||
|
val playerUrls = fansubUrls.flatMap { pair ->
|
||||||
|
val (fansub, url) = pair
|
||||||
runCatching {
|
runCatching {
|
||||||
client.newCall(GET(it, headers)).execute()
|
client.newCall(GET(url, headers)).execute()
|
||||||
.parseAs<ResponseDto>()
|
.parseAs<ResponseDto>()
|
||||||
.data
|
.data
|
||||||
.let(Jsoup::parse)
|
.let(Jsoup::parse)
|
||||||
.select("a.videoPlayerButtons")
|
.select("a.videoPlayerButtons")
|
||||||
.map { it.attr("video").replace("/video/", "/player/") }
|
.toList()
|
||||||
|
.filter { it.text().trim() in chosenHosts }
|
||||||
|
.map { fansub to it.attr("video").replace("/video/", "/player/") }
|
||||||
}.getOrElse { emptyList() }
|
}.getOrElse { emptyList() }
|
||||||
}
|
}
|
||||||
return playerUrls.parallelMap {
|
|
||||||
|
return playerUrls.parallelMap { pair ->
|
||||||
|
val (fansub, url) = pair
|
||||||
runCatching {
|
runCatching {
|
||||||
getVideosFromUrl(it)
|
getVideosFromUrl(url).map {
|
||||||
|
Video(
|
||||||
|
it.url,
|
||||||
|
"[$fansub] ${it.quality}",
|
||||||
|
it.videoUrl,
|
||||||
|
it.headers,
|
||||||
|
it.subtitleTracks,
|
||||||
|
it.audioTracks,
|
||||||
|
)
|
||||||
|
}
|
||||||
}.getOrElse { emptyList() }
|
}.getOrElse { emptyList() }
|
||||||
}.flatten()
|
}.flatten().ifEmpty {
|
||||||
|
throw Exception("No videos available, eat a yogurt and cry a bit.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val noRedirectClient by lazy {
|
private val noRedirectClient by lazy {
|
||||||
@ -205,14 +237,17 @@ class Anizm : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val doodExtractor by lazy { DoodExtractor(client) }
|
private val doodExtractor by lazy { DoodExtractor(client) }
|
||||||
private val gdrivePlayerExtractor by lazy { GdrivePlayerExtractor(client) }
|
|
||||||
private val uqloadExtractor by lazy { UqloadExtractor(client) }
|
|
||||||
private val mp4uploadExtractor by lazy { Mp4uploadExtractor(client) }
|
|
||||||
private val yourUploadExtractor by lazy { YourUploadExtractor(client) }
|
|
||||||
private val voeExtractor by lazy { VoeExtractor(client) }
|
|
||||||
private val filemoonExtractor by lazy { FilemoonExtractor(client) }
|
private val filemoonExtractor by lazy { FilemoonExtractor(client) }
|
||||||
|
private val gdrivePlayerExtractor by lazy { GdrivePlayerExtractor(client) }
|
||||||
|
private val mp4uploadExtractor by lazy { Mp4uploadExtractor(client) }
|
||||||
|
private val mytvExtractor by lazy { MytvExtractor(client) }
|
||||||
|
private val okruExtractor by lazy { OkruExtractor(client) }
|
||||||
private val sendvidExtractor by lazy { SendvidExtractor(client, headers) }
|
private val sendvidExtractor by lazy { SendvidExtractor(client, headers) }
|
||||||
private val sibnetExtractor by lazy { SibnetExtractor(client) }
|
private val sibnetExtractor by lazy { SibnetExtractor(client) }
|
||||||
|
private val streamtapeExtractor by lazy { StreamTapeExtractor(client) }
|
||||||
|
private val uqloadExtractor by lazy { UqloadExtractor(client) }
|
||||||
|
private val voeExtractor by lazy { VoeExtractor(client) }
|
||||||
|
private val yourUploadExtractor by lazy { YourUploadExtractor(client) }
|
||||||
|
|
||||||
private fun getVideosFromUrl(firstUrl: String): List<Video> {
|
private fun getVideosFromUrl(firstUrl: String): List<Video> {
|
||||||
val url = noRedirectClient.newCall(GET(firstUrl, headers)).execute()
|
val url = noRedirectClient.newCall(GET(firstUrl, headers)).execute()
|
||||||
@ -224,7 +259,10 @@ class Anizm : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
|
|||||||
"sendvid.com" in url -> sendvidExtractor.videosFromUrl(url)
|
"sendvid.com" in url -> sendvidExtractor.videosFromUrl(url)
|
||||||
"video.sibnet" in url -> sibnetExtractor.videosFromUrl(url)
|
"video.sibnet" in url -> sibnetExtractor.videosFromUrl(url)
|
||||||
"mp4upload" in url -> mp4uploadExtractor.videosFromUrl(url, headers)
|
"mp4upload" in url -> mp4uploadExtractor.videosFromUrl(url, headers)
|
||||||
|
"myvi." in url -> mytvExtractor.videosFromUrl(url)
|
||||||
|
"ok.ru" in url || "odnoklassniki.ru" in url -> okruExtractor.videosFromUrl(url)
|
||||||
"yourupload" in url -> yourUploadExtractor.videoFromUrl(url, headers)
|
"yourupload" in url -> yourUploadExtractor.videoFromUrl(url, headers)
|
||||||
|
"streamtape" in url -> streamtapeExtractor.videoFromUrl(url)?.let(::listOf)
|
||||||
"dood" in url -> doodExtractor.videoFromUrl(url)?.let(::listOf)
|
"dood" in url -> doodExtractor.videoFromUrl(url)?.let(::listOf)
|
||||||
"drive.google" in url -> {
|
"drive.google" in url -> {
|
||||||
val newUrl = "https://gdriveplayer.to/embed2.php?link=$url"
|
val newUrl = "https://gdriveplayer.to/embed2.php?link=$url"
|
||||||
@ -265,6 +303,51 @@ class Anizm : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
|
|||||||
preferences.edit().putString(key, entry).commit()
|
preferences.edit().putString(key, entry).commit()
|
||||||
}
|
}
|
||||||
}.also(screen::addPreference)
|
}.also(screen::addPreference)
|
||||||
|
|
||||||
|
MultiSelectListPreference(screen.context).apply {
|
||||||
|
key = PREF_FANSUB_SELECTION_KEY
|
||||||
|
title = PREF_FANSUB_SELECTION_TITLE
|
||||||
|
PREF_FANSUB_SELECTION_ENTRIES.let {
|
||||||
|
entries = it
|
||||||
|
entryValues = it
|
||||||
|
setDefaultValue(it.toSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
preferences.edit().putStringSet(key, newValue as Set<String>).commit()
|
||||||
|
}
|
||||||
|
}.also(screen::addPreference)
|
||||||
|
|
||||||
|
EditTextPreference(screen.context).apply {
|
||||||
|
key = PREF_ADDITIONAL_FANSUBS_KEY
|
||||||
|
title = PREF_ADDITIONAL_FANSUBS_TITLE
|
||||||
|
dialogTitle = PREF_ADDITIONAL_FANSUBS_DIALOG_TITLE
|
||||||
|
dialogMessage = PREF_ADDITIONAL_FANSUBS_DIALOG_MESSAGE
|
||||||
|
setDefaultValue(PREF_ADDITIONAL_FANSUBS_DEFAULT)
|
||||||
|
summary = PREF_ADDITIONAL_FANSUBS_SUMMARY
|
||||||
|
|
||||||
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
runCatching {
|
||||||
|
val value = newValue as String
|
||||||
|
Toast.makeText(screen.context, PREF_ADDITIONAL_FANSUBS_TOAST, Toast.LENGTH_LONG).show()
|
||||||
|
preferences.edit().putString(key, value).commit()
|
||||||
|
}.getOrDefault(false)
|
||||||
|
}
|
||||||
|
}.also(screen::addPreference)
|
||||||
|
|
||||||
|
MultiSelectListPreference(screen.context).apply {
|
||||||
|
key = PREF_HOSTS_SELECTION_KEY
|
||||||
|
title = PREF_HOSTS_SELECTION_TITLE
|
||||||
|
entries = PREF_HOSTS_SELECTION_ENTRIES
|
||||||
|
entryValues = PREF_HOSTS_SELECTION_ENTRIES
|
||||||
|
setDefaultValue(PREF_HOSTS_SELECTION_DEFAULT)
|
||||||
|
|
||||||
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
preferences.edit().putStringSet(key, newValue as Set<String>).commit()
|
||||||
|
}
|
||||||
|
}.also(screen::addPreference)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================= Utilities ==============================
|
// ============================= Utilities ==============================
|
||||||
@ -281,10 +364,41 @@ class Anizm : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
|
|||||||
val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!
|
val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!
|
||||||
|
|
||||||
return sortedWith(
|
return sortedWith(
|
||||||
compareBy { it.quality.contains(quality) },
|
compareBy(
|
||||||
|
{ it.quality.contains(quality) }, // preferred quality first
|
||||||
|
{ it.quality.substringBefore("]") }, // then group by fansub
|
||||||
|
// then group by quality
|
||||||
|
{ Regex("""(\d+)p""").find(it.quality)?.groupValues?.get(1)?.toIntOrNull() ?: 0 },
|
||||||
|
),
|
||||||
).reversed()
|
).reversed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun String.fixedFansubName(): String =
|
||||||
|
substringBefore("- BD")
|
||||||
|
.substringBefore("Fansub")
|
||||||
|
.substringBefore("Bağımsız")
|
||||||
|
.trim()
|
||||||
|
|
||||||
|
private fun Elements.filterSubs(): List<Element> {
|
||||||
|
val allFansubs = PREF_FANSUB_SELECTION_ENTRIES
|
||||||
|
val chosenFansubs = preferences.getStringSet(PREF_FANSUB_SELECTION_KEY, allFansubs.toSet())!!
|
||||||
|
|
||||||
|
return toList().filter {
|
||||||
|
val text = it.text().fixedFansubName()
|
||||||
|
text in chosenFansubs || text !in allFansubs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val PREF_FANSUB_SELECTION_ENTRIES: Array<String> get() {
|
||||||
|
val additional = preferences.getString(PREF_ADDITIONAL_FANSUBS_KEY, "")!!
|
||||||
|
.split(",")
|
||||||
|
.map { it.fixedFansubName() }
|
||||||
|
.filter(String::isNotBlank)
|
||||||
|
.toSet()
|
||||||
|
|
||||||
|
return (DEFAULT_FANSUBS + additional).sorted().toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val PREFIX_SEARCH = "id:"
|
const val PREFIX_SEARCH = "id:"
|
||||||
|
|
||||||
@ -293,5 +407,62 @@ class Anizm : ParsedAnimeHttpSource(), ConfigurableAnimeSource {
|
|||||||
private const val PREF_QUALITY_DEFAULT = "720p"
|
private const val PREF_QUALITY_DEFAULT = "720p"
|
||||||
private val PREF_QUALITY_ENTRIES = arrayOf("1080p", "720p", "480p", "360p")
|
private val PREF_QUALITY_ENTRIES = arrayOf("1080p", "720p", "480p", "360p")
|
||||||
private val PREF_QUALITY_VALUES = PREF_QUALITY_ENTRIES
|
private val PREF_QUALITY_VALUES = PREF_QUALITY_ENTRIES
|
||||||
|
|
||||||
|
private const val PREF_FANSUB_SELECTION_KEY = "pref_fansub_selection"
|
||||||
|
private const val PREF_FANSUB_SELECTION_TITLE = "Enable/Disable Fansubs"
|
||||||
|
private val DEFAULT_FANSUBS by lazy {
|
||||||
|
setOf(
|
||||||
|
"Adonis",
|
||||||
|
"Akatsuki",
|
||||||
|
"AnimeSeverler",
|
||||||
|
"AniSekai",
|
||||||
|
"Aoi",
|
||||||
|
"ARE-YOU-SURE",
|
||||||
|
"ÇeviriBükücüler",
|
||||||
|
"DeiraSubs",
|
||||||
|
"Güncellenecek",
|
||||||
|
"hitokirireaper",
|
||||||
|
"Holy",
|
||||||
|
"Lawsonia",
|
||||||
|
"LoliSubs",
|
||||||
|
"LowSubs",
|
||||||
|
"Magnum357",
|
||||||
|
"NaoSubs",
|
||||||
|
"Origami",
|
||||||
|
"PijamalıKoi",
|
||||||
|
"Tempest",
|
||||||
|
"UragiriSubs",
|
||||||
|
"whosgoodbadass",
|
||||||
|
"Yuki",
|
||||||
|
"YuushaSubs",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val PREF_ADDITIONAL_FANSUBS_KEY = "pref_additional_fansubs_key"
|
||||||
|
private const val PREF_ADDITIONAL_FANSUBS_TITLE = "Add custom fansubs to the selection preference"
|
||||||
|
private const val PREF_ADDITIONAL_FANSUBS_DEFAULT = ""
|
||||||
|
private const val PREF_ADDITIONAL_FANSUBS_DIALOG_TITLE = "Enter a list of additional fansubs, separated by a comma."
|
||||||
|
private const val PREF_ADDITIONAL_FANSUBS_DIALOG_MESSAGE = "Example: AntichristHaters Fansub, 2cm erect subs"
|
||||||
|
private const val PREF_ADDITIONAL_FANSUBS_SUMMARY = "You can add more fansubs to the previous preference from here."
|
||||||
|
private const val PREF_ADDITIONAL_FANSUBS_TOAST = "Reopen the extension's preferences for it to take effect."
|
||||||
|
|
||||||
|
private const val PREF_HOSTS_SELECTION_KEY = "pref_hosts_selection"
|
||||||
|
private const val PREF_HOSTS_SELECTION_TITLE = "Disable/enable video hosts"
|
||||||
|
private val PREF_HOSTS_SELECTION_ENTRIES = arrayOf(
|
||||||
|
"DoodStream",
|
||||||
|
"FileMoon",
|
||||||
|
"GDrive",
|
||||||
|
"MP4Upload",
|
||||||
|
"MyviRU",
|
||||||
|
"Myvi.TV",
|
||||||
|
"Odnoklassniki",
|
||||||
|
"SendVid",
|
||||||
|
"Sibnet",
|
||||||
|
"StreamTape",
|
||||||
|
"UQload",
|
||||||
|
"Voe",
|
||||||
|
"YourUpload",
|
||||||
|
)
|
||||||
|
private val PREF_HOSTS_SELECTION_DEFAULT by lazy { PREF_HOSTS_SELECTION_ENTRIES.toSet() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user