mirror of
https://github.com/yuzono/anime-extensions.git
synced 2026-06-13 13:39:44 +00:00
feat(src/es): VerPelisTop added & HLA fixed (Kohi-den/extensions-source#1073)
Closes Kohi-den/extensions-source#1066 Closes Kohi-den/extensions-source#1056 Co-authored-by: imper1aldev <23511335+imper1aldev@users.noreply.github.com> (cherry picked from commit 178e85bcd50940355d0d7032ad44779f8f8dcc50)
This commit is contained in:
@@ -196,16 +196,15 @@ class Hentaila : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
|
||||
override fun episodeListParse(response: Response): List<SEpisode> {
|
||||
val episodes = mutableListOf<SEpisode>()
|
||||
val animeId = Regex("""media/([^/?#]+)""")
|
||||
.find(response.request.url.toString())?.groupValues?.get(1)?.lowercase() ?: ""
|
||||
val jsoup = response.asJsoup()
|
||||
|
||||
jsoup.select("article.group\\/item").forEach {
|
||||
val href = it.select("a").attr("abs:href")
|
||||
val epNum = it.select("div.bg-line.text-subs span").text()
|
||||
val episode = SEpisode.create().apply {
|
||||
episode_number = epNum.toFloatOrNull() ?: return@forEach
|
||||
epNum.toFloatOrNull()?.let { num -> episode_number = num }
|
||||
name = "Episodio $epNum"
|
||||
url = "/media/$animeId/$epNum"
|
||||
setUrlWithoutDomain(href)
|
||||
}
|
||||
episodes.add(episode)
|
||||
}
|
||||
@@ -268,30 +267,44 @@ class Hentaila : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
}
|
||||
}
|
||||
|
||||
val allVideos = serverList.parallelCatchingFlatMapBlocking { each ->
|
||||
when (each.name.lowercase()) {
|
||||
"streamwish" -> streamWishExtractor.videosFromUrl(each.url, videoNameGen = { "StreamWish:$it" })
|
||||
"mp4upload" -> mp4uploadExtractor.videosFromUrl(each.url, headers = headers, prefix = "Mp4Upload")
|
||||
"voe" -> voeExtractor.videosFromUrl(each.url)
|
||||
"arc" -> listOf(Video(each.url.substringAfter("#"), "Arc", each.url.substringAfter("#")))
|
||||
"yupi", "yourupload" -> yourUploadExtractor.videoFromUrl(each.url, headers = headers)
|
||||
"burst" -> burstCloudExtractor.videoFromUrl(each.url, headers = headers)
|
||||
"sendvid" -> sendvidExtractor.videosFromUrl(each.url)
|
||||
"mediafire" -> mediaFireExtractor.getVideoFromUrl(each.url)
|
||||
"fireload" -> fireLoadExtractor.getVideoFromUrl(each.url)
|
||||
"vidhide" -> vidhideExtractor.videosFromUrl(each.url)
|
||||
"mega" -> megacloudExtractor.getVideosFromUrl(each.url, "Megacloud", "Megacloud")
|
||||
val allVideos = serverList.parallelCatchingFlatMapBlocking { server ->
|
||||
val serverName = serverDomainCatalog.firstOrNull { (_, names) -> names.any { it.lowercase() in server.url.lowercase() } }?.first
|
||||
?: server.name.lowercase()
|
||||
when (serverName) {
|
||||
"streamwish" -> streamWishExtractor.videosFromUrl(server.url, videoNameGen = { "StreamWish:$it" })
|
||||
"mp4upload" -> mp4uploadExtractor.videosFromUrl(server.url, headers = headers, prefix = "Mp4Upload")
|
||||
"voe" -> voeExtractor.videosFromUrl(server.url)
|
||||
"arc" -> listOf(Video(server.url.substringAfter("#"), "Arc", server.url.substringAfter("#")))
|
||||
"yupi", "yourupload" -> yourUploadExtractor.videoFromUrl(server.url, headers = headers)
|
||||
"burst", "burstcloud" -> burstCloudExtractor.videoFromUrl(server.url, headers = headers)
|
||||
"sendvid" -> sendvidExtractor.videosFromUrl(server.url)
|
||||
"mediafire" -> mediaFireExtractor.getVideoFromUrl(server.url)
|
||||
"fireload" -> fireLoadExtractor.getVideoFromUrl(server.url)
|
||||
"vidhide" -> vidhideExtractor.videosFromUrl(server.url) // streamHideVidExtractor
|
||||
"mega" -> megacloudExtractor.getVideosFromUrl(server.url, "Megacloud", "Megacloud")
|
||||
"vip" -> universalExtractor.videosFromUrl(
|
||||
each.url.replace("/play/", "/m3u8/"),
|
||||
server.url.replace("/play/", "/m3u8/"),
|
||||
origRequestHeader = headers,
|
||||
prefix = "VIP",
|
||||
)
|
||||
else -> emptyList()
|
||||
else -> universalExtractor.videosFromUrl(server.url, headers)
|
||||
}
|
||||
}
|
||||
return allVideos
|
||||
}
|
||||
|
||||
private val serverDomainCatalog = listOf(
|
||||
"streamwish" to listOf("wishembed", "streamwish", "strwish", "wish", "Kswplayer", "Swhoi", "Multimovies", "Uqloads", "neko-stream", "swdyu", "iplayerhls", "streamgg"),
|
||||
"voe" to listOf("voe", "tubelessceliolymph", "simpulumlamerop", "urochsunloath", "nathanfromsubject", "yip.", "metagnathtuggers", "donaldlineelse"),
|
||||
"arc" to listOf("arc"),
|
||||
"mp4upload" to listOf("mp4upload"),
|
||||
"yourupload" to listOf("yourupload", "yupi"),
|
||||
"burstcloud" to listOf("burstcloud", "burst"),
|
||||
"vidhide" to listOf("ahvsh", "streamhide", "guccihide", "streamvid", "vidhide", "kinoger", "smoothpre", "dhtpre", "peytonepre", "earnvids", "ryderjet"),
|
||||
"sendvid" to listOf("sendvid"),
|
||||
"mediafire" to listOf("mediafire"),
|
||||
)
|
||||
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT).orEmpty()
|
||||
val server = preferences.getString(PREF_SERVER_KEY, PREF_SERVER_DEFAULT).orEmpty()
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
package eu.kanade.tachiyomi.animeextension.es.hentaila
|
||||
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||
import java.util.Calendar
|
||||
|
||||
object HentailaFilters {
|
||||
open class QueryPartFilter(displayName: String, val vals: Array<Pair<String, String>>) : AnimeFilter.Select<String>(
|
||||
displayName,
|
||||
vals.map { it.first }.toTypedArray(),
|
||||
) {
|
||||
fun toQueryPart(name: String) = vals[state].second.takeIf { it.isNotEmpty() }?.let { "&$name=${vals[state].second}" } ?: run { "" }
|
||||
}
|
||||
|
||||
open class CheckBoxFilterList(name: String, values: List<CheckBox>) : AnimeFilter.Group<AnimeFilter.CheckBox>(name, values)
|
||||
open class CheckBoxFilter(name: String) : AnimeFilter.CheckBox(name) {
|
||||
fun toQueryPart(name: String): String {
|
||||
return this.state.takeIf { it }?.let { "&$name=true" } ?: run { "" }
|
||||
}
|
||||
}
|
||||
|
||||
private class CheckBoxVal(name: String, state: Boolean = false) : AnimeFilter.CheckBox(name, state)
|
||||
|
||||
private inline fun <reified R> AnimeFilterList.parseCheckbox(
|
||||
options: Array<Pair<String, String>>,
|
||||
name: String,
|
||||
): String {
|
||||
return (this.getFirst<R>() as CheckBoxFilterList).state
|
||||
.mapNotNull { checkbox ->
|
||||
if (checkbox.state) {
|
||||
options.find { it.first == checkbox.name }!!.second
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}.joinToString("&$name=").let {
|
||||
if (it.isBlank()) {
|
||||
""
|
||||
} else {
|
||||
"&$name=$it"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified R> AnimeFilterList.asQueryPart(name: String): String {
|
||||
return (this.getFirst<R>() as QueryPartFilter).toQueryPart(name)
|
||||
}
|
||||
|
||||
private inline fun <reified R> AnimeFilterList.checkAsQueryPart(name: String): String {
|
||||
return (this.getFirst<R>() as CheckBoxFilter).toQueryPart(name)
|
||||
}
|
||||
|
||||
private inline fun <reified R> AnimeFilterList.getFirst(): R {
|
||||
return this.filterIsInstance<R>().first()
|
||||
}
|
||||
|
||||
private fun String.changePrefix() = this.takeIf { it.startsWith("&") }?.let { this.replaceFirst("&", "?") } ?: run { this }
|
||||
|
||||
data class FilterSearchParams(val filter: String = "") { fun getQuery() = filter.changePrefix() }
|
||||
|
||||
internal fun getSearchParameters(filters: AnimeFilterList): FilterSearchParams {
|
||||
if (filters.isEmpty()) return FilterSearchParams()
|
||||
return FilterSearchParams(
|
||||
filters.parseCheckbox<GenresFilter>(HentailaFiltersData.GENRES, "genre") +
|
||||
filters.asQueryPart<YearMinFilter>("minYear") +
|
||||
filters.asQueryPart<YearMaxFilter>("maxYear") +
|
||||
filters.asQueryPart<StatusFilter>("status") +
|
||||
filters.asQueryPart<SortFilter>("order") +
|
||||
filters.checkAsQueryPart<CheckBoxFilter>("uncensored"),
|
||||
)
|
||||
}
|
||||
|
||||
val FILTER_LIST get() = AnimeFilterList(
|
||||
AnimeFilter.Header("La busqueda por texto ignora el filtro"),
|
||||
GenresFilter(),
|
||||
YearMinFilter(),
|
||||
YearMaxFilter(),
|
||||
StatusFilter(),
|
||||
AnimeFilter.Separator(),
|
||||
CensoredFilter(),
|
||||
AnimeFilter.Separator(),
|
||||
SortFilter(),
|
||||
)
|
||||
|
||||
class GenresFilter : CheckBoxFilterList("Género", HentailaFiltersData.GENRES.map { CheckBoxVal(it.first, false) })
|
||||
class YearMinFilter : QueryPartFilter("Min. Año", arrayOf(Pair("Todos", "")) + HentailaFiltersData.YEARS)
|
||||
class YearMaxFilter : QueryPartFilter("Max. Año", arrayOf(Pair("Todos", "")) + HentailaFiltersData.YEARS.reversed())
|
||||
class StatusFilter : QueryPartFilter("Estado", HentailaFiltersData.STATUS)
|
||||
class SortFilter : QueryPartFilter("Ordenar por", HentailaFiltersData.SORT)
|
||||
class CensoredFilter : CheckBoxFilter("Sin censura")
|
||||
|
||||
private object HentailaFiltersData {
|
||||
val GENRES = arrayOf(
|
||||
Pair("3D", "3d"),
|
||||
Pair("Ahegao", "ahegao"),
|
||||
Pair("Anal", "anal"),
|
||||
Pair("Casadas", "casadas"),
|
||||
Pair("Chikan", "chikan"),
|
||||
Pair("Ecchi", "ecchi"),
|
||||
Pair("Enfermeras", "enfermeras"),
|
||||
Pair("Escolares", "escolares"),
|
||||
Pair("Futanari", "futanari"),
|
||||
Pair("Gore", "gore"),
|
||||
Pair("Hardcore", "hardcore"),
|
||||
Pair("Harem", "harem"),
|
||||
Pair("Incesto", "incesto"),
|
||||
Pair("Juegos Sexuales", "juegos-sexuales"),
|
||||
Pair("Suspenso", "suspenso"),
|
||||
Pair("Milfs", "milfs"),
|
||||
Pair("Maids", "maids"),
|
||||
Pair("Netorare", "netorare"),
|
||||
Pair("Ninfomania", "ninfomania"),
|
||||
Pair("Ninjas", "ninjas"),
|
||||
Pair("Orgias", "orgias"),
|
||||
Pair("Romance", "romance"),
|
||||
Pair("Shota", "shota"),
|
||||
Pair("Softcore", "softcore"),
|
||||
Pair("Succubus", "succubus"),
|
||||
Pair("Teacher", "teacher"),
|
||||
Pair("Tentaculos", "tentaculos"),
|
||||
Pair("Tetonas", "tetonas"),
|
||||
Pair("Vanilla", "vanilla"),
|
||||
Pair("Violacion", "violacion"),
|
||||
Pair("Virgenes", "virgenes"),
|
||||
Pair("Yaoi", "yaoi"),
|
||||
Pair("Yuri", "yuri"),
|
||||
Pair("Bondage", "bondage"),
|
||||
Pair("Elfas", "elfas"),
|
||||
Pair("Petit", "petit"),
|
||||
Pair("Threesome", "threesome"),
|
||||
Pair("Paizuri", "paizuri"),
|
||||
Pair("Gal", "gal"),
|
||||
Pair("Oyakodon", "oyakodon"),
|
||||
)
|
||||
val YEARS = (1991..Calendar.getInstance().get(Calendar.YEAR)).map { Pair("$it", "$it") }.toTypedArray()
|
||||
val STATUS = arrayOf(
|
||||
Pair("Todos", ""),
|
||||
Pair("Finalizado", "finalizado"),
|
||||
Pair("Próximamente", "proximamente"),
|
||||
Pair("En emisión", "emision"),
|
||||
)
|
||||
val SORT = arrayOf(
|
||||
Pair("Predeterminado", ""),
|
||||
Pair("Puntuación", "score"),
|
||||
Pair("Populares", "popular"),
|
||||
Pair("Título", "title"),
|
||||
Pair("Últimos agregados", "latest_added"),
|
||||
Pair("Últimos estrenos", "latest_released"),
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user