refactor(it): refactoring of some italian extensions (#1776)
This commit is contained in:
@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
|
||||
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
@ -46,15 +45,13 @@ class AnimeLove : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
override fun popularAnimeSelector(): String = "div.containerlista > div.row > div.col-6"
|
||||
|
||||
override fun popularAnimeNextPageSelector(): String = "div > ul.page-nav > li:last-child:not(:has(a.disabled))"
|
||||
|
||||
override fun popularAnimeFromElement(element: Element): SAnime {
|
||||
return SAnime.create().apply {
|
||||
setUrlWithoutDomain(element.selectFirst("a")!!.attr("href").toHttpUrl().encodedPath)
|
||||
override fun popularAnimeFromElement(element: Element): SAnime = SAnime.create().apply {
|
||||
setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
|
||||
thumbnail_url = element.selectFirst("img")?.attr("src")
|
||||
title = element.selectFirst("div.default-text")!!.text()
|
||||
}
|
||||
}
|
||||
|
||||
override fun popularAnimeNextPageSelector(): String = "div > ul.page-nav > li:last-child:not(:has(a.disabled))"
|
||||
|
||||
// =============================== Latest ===============================
|
||||
|
||||
@ -62,10 +59,10 @@ class AnimeLove : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
override fun latestUpdatesSelector(): String = popularAnimeSelector()
|
||||
|
||||
override fun latestUpdatesNextPageSelector(): String = popularAnimeNextPageSelector()
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element): SAnime = popularAnimeFromElement(element)
|
||||
|
||||
override fun latestUpdatesNextPageSelector(): String = popularAnimeNextPageSelector()
|
||||
|
||||
// =============================== Search ===============================
|
||||
|
||||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
|
||||
@ -89,30 +86,26 @@ class AnimeLove : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
return super.searchAnimeParse(response)
|
||||
}
|
||||
|
||||
val document = response.asJsoup()
|
||||
val animeList = response.asJsoup()
|
||||
.select(searchAnimeSelectorSearch())
|
||||
.map(::searchAnimeFromElementSearch)
|
||||
|
||||
val animes = document.select(searchAnimeSelectorSearch()).map { element ->
|
||||
searchAnimeFromElementSearch(element)
|
||||
}
|
||||
|
||||
return AnimesPage(animes, false)
|
||||
return AnimesPage(animeList, false)
|
||||
}
|
||||
|
||||
override fun searchAnimeSelector(): String = popularAnimeSelector()
|
||||
|
||||
private fun searchAnimeSelectorSearch(): String = "div.col-md-8 > div.card > div.card-body > div.row > div.col-6"
|
||||
|
||||
override fun searchAnimeNextPageSelector(): String = popularAnimeNextPageSelector()
|
||||
override fun searchAnimeFromElement(element: Element): SAnime = popularAnimeFromElement(element)
|
||||
|
||||
private fun searchAnimeFromElementSearch(element: Element): SAnime {
|
||||
return SAnime.create().apply {
|
||||
setUrlWithoutDomain(element.selectFirst("a")!!.attr("href").toHttpUrl().encodedPath)
|
||||
private fun searchAnimeFromElementSearch(element: Element): SAnime = SAnime.create().apply {
|
||||
setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
|
||||
thumbnail_url = element.selectFirst("img")?.attr("src")
|
||||
title = element.selectFirst("p.card-text")!!.text()
|
||||
}
|
||||
}
|
||||
|
||||
override fun searchAnimeFromElement(element: Element): SAnime = popularAnimeFromElement(element)
|
||||
override fun searchAnimeNextPageSelector(): String = popularAnimeNextPageSelector()
|
||||
|
||||
// ============================== Filters ===============================
|
||||
|
||||
@ -238,37 +231,33 @@ class AnimeLove : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
// =========================== Anime Details ============================
|
||||
|
||||
override fun animeDetailsParse(document: Document): SAnime {
|
||||
val moreInfo = (document.selectFirst("div.card-body > p:contains(TIPO:)")?.text() ?: "") +
|
||||
"\n" +
|
||||
(document.selectFirst("div.card-body > p:contains(ANNO)")?.text() ?: "")
|
||||
|
||||
return SAnime.create().apply {
|
||||
override fun animeDetailsParse(document: Document): SAnime = SAnime.create().apply {
|
||||
title = document.selectFirst("div.card-body > p:contains(TITOLO:)")?.ownText() ?: ""
|
||||
thumbnail_url = document.selectFirst("div.card-body > div > img")?.attr("src") ?: ""
|
||||
author = document.selectFirst("div.card-body > p:contains(STUDIO:)")?.ownText() ?: ""
|
||||
status = document.selectFirst("div.card-body > p:contains(STATO:)")?.let {
|
||||
parseStatus(it.ownText())
|
||||
} ?: SAnime.UNKNOWN
|
||||
description = (document.selectFirst("div.card-body > p:contains(TRAMA:) ~ p")?.text() ?: "") + "\n\n$moreInfo"
|
||||
genre = document.selectFirst("div.card-body > p:contains(GENERI:)")?.ownText() ?: ""
|
||||
description = buildString {
|
||||
append(document.selectFirst("div.card-body > p:contains(TRAMA:) ~ p")?.text() ?: "")
|
||||
append("\n\n")
|
||||
append(document.selectFirst("div.card-body > p:contains(TIPO:)")?.text() ?: "")
|
||||
append("\n")
|
||||
append(document.selectFirst("div.card-body > p:contains(ANNO)")?.text() ?: "")
|
||||
}
|
||||
}
|
||||
|
||||
// ============================== Episodes ==============================
|
||||
|
||||
override fun episodeListParse(response: Response): List<SEpisode> {
|
||||
return super.episodeListParse(response).reversed()
|
||||
}
|
||||
override fun episodeListParse(response: Response): List<SEpisode> = super.episodeListParse(response).reversed()
|
||||
|
||||
override fun episodeListSelector(): String = "div.card ul.page-nav-list-episodi > li"
|
||||
|
||||
override fun episodeFromElement(element: Element): SEpisode {
|
||||
return SEpisode.create().apply {
|
||||
override fun episodeFromElement(element: Element): SEpisode = SEpisode.create().apply {
|
||||
name = "Episodi ${element.text()}"
|
||||
episode_number = element.selectFirst("span")?.text()?.toFloatOrNull() ?: 0F
|
||||
setUrlWithoutDomain(element.selectFirst("a[href]")!!.attr("href").toHttpUrl().encodedPath)
|
||||
}
|
||||
setUrlWithoutDomain(element.selectFirst("a[href]")!!.attr("href"))
|
||||
}
|
||||
|
||||
// ============================ Video Links =============================
|
||||
@ -301,13 +290,15 @@ class AnimeLove : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
}
|
||||
}
|
||||
|
||||
require(videoList.isNotEmpty()) { "Failed to fetch videos" }
|
||||
|
||||
return videoList
|
||||
}
|
||||
|
||||
override fun videoFromElement(element: Element): Video = throw Exception("Not Used")
|
||||
|
||||
override fun videoListSelector(): String = throw Exception("Not Used")
|
||||
|
||||
override fun videoFromElement(element: Element): Video = throw Exception("Not Used")
|
||||
|
||||
override fun videoUrlParse(document: Document): String = throw Exception("Not Used")
|
||||
|
||||
// ============================= Utilities ==============================
|
||||
@ -328,7 +319,7 @@ class AnimeLove : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
}
|
||||
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
val server = preferences.getString("preferred_server", "AnimeLove")!!
|
||||
val server = preferences.getString(PREF_SERVER_KEY, PREF_SERVER_DEFAULT)!!
|
||||
|
||||
return this.sortedWith(
|
||||
compareBy { it.quality.contains(server, true) },
|
||||
@ -343,13 +334,20 @@ class AnimeLove : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PREF_SERVER_KEY = "preferred_server"
|
||||
private const val PREF_SERVER_DEFAULT = "AnimeLove"
|
||||
}
|
||||
|
||||
// ============================== Settings ==============================
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
val videoServerPref = ListPreference(screen.context).apply {
|
||||
key = "preferred_server"
|
||||
ListPreference(screen.context).apply {
|
||||
key = PREF_SERVER_KEY
|
||||
title = "Preferred server"
|
||||
entries = arrayOf("AnimeLove", "StreamTape")
|
||||
entryValues = arrayOf("AnimeLove", "StreamTape")
|
||||
setDefaultValue("AnimeLove")
|
||||
setDefaultValue(PREF_SERVER_DEFAULT)
|
||||
summary = "%s"
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
@ -358,7 +356,6 @@ class AnimeLove : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
val entry = entryValues[index] as String
|
||||
preferences.edit().putString(key, entry).commit()
|
||||
}
|
||||
}
|
||||
screen.addPreference(videoServerPref)
|
||||
}.also(screen::addPreference)
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package eu.kanade.tachiyomi.animeextension.it.animeunity
|
||||
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.put
|
||||
|
||||
object AnimeUnityFilters {
|
||||
|
||||
@ -28,7 +30,7 @@ object AnimeUnityFilters {
|
||||
|
||||
class GenreFilter : CheckBoxFilterList(
|
||||
"Genere",
|
||||
AnimeUnityFiltersData.GENERE.map { CheckBoxVal(it.first, false) },
|
||||
AnimeUnityFiltersData.GENRE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class YearFilter : QueryPartFilter("Anno", AnimeUnityFiltersData.YEAR)
|
||||
@ -73,15 +75,12 @@ object AnimeUnityFilters {
|
||||
|
||||
val genre: String = filters.filterIsInstance<GenreFilter>()
|
||||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (format.state) {
|
||||
"{\"id\":" +
|
||||
AnimeUnityFiltersData.GENERE.find { it.first == format.name }!!.second +
|
||||
",\"name\":\"" +
|
||||
AnimeUnityFiltersData.GENERE.find { it.first == format.name }!!.first +
|
||||
"\"}"
|
||||
} else { null }
|
||||
}.joinToString(",")
|
||||
.state.filter { it.state }.joinToString(",") { format ->
|
||||
buildJsonObject {
|
||||
put("id", AnimeUnityFiltersData.GENRE.find { it.first == format.name }!!.second.toInt())
|
||||
put("name", AnimeUnityFiltersData.GENRE.find { it.first == format.name }!!.first)
|
||||
}.toString()
|
||||
}
|
||||
|
||||
return FilterSearchParams(
|
||||
filters.asQueryPart<TopFilter>(),
|
||||
@ -113,7 +112,7 @@ object AnimeUnityFilters {
|
||||
Pair("Più visti", "top-anime?order=most_viewed"),
|
||||
)
|
||||
|
||||
val GENERE = arrayOf(
|
||||
val GENRE = arrayOf(
|
||||
Pair("Action", "51"),
|
||||
Pair("Adventure", "21"),
|
||||
Pair("Cars", "29"),
|
||||
|
@ -76,33 +76,33 @@ class AniPlay : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request = throw Exception("Not used")
|
||||
|
||||
private fun searchAnimeRequest(page: Int, query: String, filters: AniPlayFilters.FilterSearchParams): Request {
|
||||
if ((filters.anni.isNotEmpty() && filters.stagione.isEmpty()) ||
|
||||
(filters.anni.isEmpty() && filters.stagione.isNotEmpty())
|
||||
if ((filters.year.isNotEmpty() && filters.season.isEmpty()) ||
|
||||
(filters.year.isEmpty() && filters.season.isNotEmpty())
|
||||
) {
|
||||
throw Exception("Per gli anime stagionali, seleziona sia l'anno che la stagione")
|
||||
error("Per gli anime stagionali, seleziona sia l'anno che la stagione")
|
||||
}
|
||||
|
||||
val url = if (filters.anni.isNotEmpty()) {
|
||||
val url = if (filters.year.isNotEmpty()) {
|
||||
"$baseUrl/api/seasonal-view".toHttpUrlOrNull()!!.newBuilder()
|
||||
.addPathSegment("${filters.stagione}-${filters.anni}")
|
||||
.addPathSegment("${filters.season}-${filters.year}")
|
||||
.addQueryParameter("page", (page - 1).toString())
|
||||
.addQueryParameter("size", "36")
|
||||
.addQueryParameter("sort", filters.ordina)
|
||||
.addQueryParameter("sort", filters.order)
|
||||
.addQueryParameter("sort", "id")
|
||||
} else {
|
||||
"$baseUrl/api/anime/advanced-similar-search".toHttpUrlOrNull()!!.newBuilder()
|
||||
.addQueryParameter("page", (page - 1).toString())
|
||||
.addQueryParameter("size", "36")
|
||||
.addQueryParameter("sort", filters.ordina)
|
||||
.addQueryParameter("sort", filters.order)
|
||||
.addQueryParameter("sort", "id")
|
||||
.addIfNotBlank("query", query)
|
||||
.addIfNotBlank("genreIds", filters.genere)
|
||||
.addIfNotBlank("typeIds", filters.tipologia)
|
||||
.addIfNotBlank("statusIds", filters.stato)
|
||||
.addIfNotBlank("originIds", filters.origine)
|
||||
.addIfNotBlank("genreIds", filters.genre)
|
||||
.addIfNotBlank("typeIds", filters.type)
|
||||
.addIfNotBlank("statusIds", filters.status)
|
||||
.addIfNotBlank("originIds", filters.origin)
|
||||
.addIfNotBlank("studioIds", filters.studio)
|
||||
.addIfNotBlank("startYear", filters.inizio)
|
||||
.addIfNotBlank("endYear", filters.fine)
|
||||
.addIfNotBlank("startYear", filters.start)
|
||||
.addIfNotBlank("endYear", filters.end)
|
||||
}
|
||||
|
||||
return GET(url.build().toString())
|
||||
|
@ -24,24 +24,24 @@ object AniPlayFilters {
|
||||
}
|
||||
}
|
||||
|
||||
class GenereFilter : CheckBoxFilterList(
|
||||
class GenreFilter : CheckBoxFilterList(
|
||||
"Genere",
|
||||
AniPlayFiltersData.GENERE.map { CheckBoxVal(it.first, false) },
|
||||
AniPlayFiltersData.GENRE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class TipologiaFilter : CheckBoxFilterList(
|
||||
class TypeFilter : CheckBoxFilterList(
|
||||
"Tipologia anime",
|
||||
AniPlayFiltersData.TIPOLOGIA.map { CheckBoxVal(it.first, false) },
|
||||
AniPlayFiltersData.TYPE.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class StatoFilter : CheckBoxFilterList(
|
||||
class StatusFilter : CheckBoxFilterList(
|
||||
"Stato",
|
||||
AniPlayFiltersData.STATO.map { CheckBoxVal(it.first, false) },
|
||||
AniPlayFiltersData.STATUS.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class OrigineFilter : CheckBoxFilterList(
|
||||
class OriginFilter : CheckBoxFilterList(
|
||||
"Origine",
|
||||
AniPlayFiltersData.ORIGINE.map { CheckBoxVal(it.first, false) },
|
||||
AniPlayFiltersData.ORIGIN.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class StudioFilter : CheckBoxFilterList(
|
||||
@ -49,110 +49,105 @@ object AniPlayFilters {
|
||||
AniPlayFiltersData.STUDIO.map { CheckBoxVal(it.first, false) },
|
||||
)
|
||||
|
||||
class InizioFilter : QueryPartFilter("Inizio", AniPlayFiltersData.ANNI)
|
||||
class FineFilter : QueryPartFilter("Fine", AniPlayFiltersData.ANNI)
|
||||
class OrdinaFilter : QueryPartFilter("Ordina per", AniPlayFiltersData.ORDINA)
|
||||
class StartFilter : QueryPartFilter("Inizio", AniPlayFiltersData.YEAR)
|
||||
class EndFilter : QueryPartFilter("Fine", AniPlayFiltersData.YEAR)
|
||||
class OrderFilter : QueryPartFilter("Ordina per", AniPlayFiltersData.ORDER)
|
||||
|
||||
class AnniFilter : QueryPartFilter("Anni", AniPlayFiltersData.ANNI)
|
||||
class StagioneFilter : QueryPartFilter("Stagione", AniPlayFiltersData.STAGIONE)
|
||||
class YearFilter : QueryPartFilter("Anni", AniPlayFiltersData.YEAR)
|
||||
class SeasonFilter : QueryPartFilter("Stagione", AniPlayFiltersData.SEASON)
|
||||
|
||||
val FILTER_LIST get() = AnimeFilterList(
|
||||
OrdinaFilter(),
|
||||
OrderFilter(),
|
||||
AnimeFilter.Separator(),
|
||||
|
||||
GenereFilter(),
|
||||
TipologiaFilter(),
|
||||
StatoFilter(),
|
||||
OrigineFilter(),
|
||||
GenreFilter(),
|
||||
TypeFilter(),
|
||||
StatusFilter(),
|
||||
OriginFilter(),
|
||||
StudioFilter(),
|
||||
|
||||
AnimeFilter.Separator(),
|
||||
AnimeFilter.Header("Anni"),
|
||||
InizioFilter(),
|
||||
FineFilter(),
|
||||
StartFilter(),
|
||||
EndFilter(),
|
||||
|
||||
AnimeFilter.Separator(),
|
||||
AnimeFilter.Header("Anime stagionali"),
|
||||
AnimeFilter.Header("(ignora altri filtri tranne l'ordinamento per)"),
|
||||
AnniFilter(),
|
||||
StagioneFilter(),
|
||||
YearFilter(),
|
||||
SeasonFilter(),
|
||||
|
||||
)
|
||||
|
||||
data class FilterSearchParams(
|
||||
val ordina: String = "views,desc",
|
||||
val genere: String = "",
|
||||
val tipologia: String = "",
|
||||
val stato: String = "",
|
||||
val origine: String = "",
|
||||
val order: String = "views,desc",
|
||||
val genre: String = "",
|
||||
val type: String = "",
|
||||
val status: String = "",
|
||||
val origin: String = "",
|
||||
val studio: String = "",
|
||||
val inizio: String = "",
|
||||
val fine: String = "",
|
||||
val anni: String = "",
|
||||
val stagione: String = "",
|
||||
val start: String = "",
|
||||
val end: String = "",
|
||||
val year: String = "",
|
||||
val season: String = "",
|
||||
)
|
||||
|
||||
internal fun getSearchParameters(filters: AnimeFilterList): FilterSearchParams {
|
||||
if (filters.isEmpty()) return FilterSearchParams()
|
||||
|
||||
val genere: String = filters.filterIsInstance<GenereFilter>()
|
||||
val genre: String = filters.filterIsInstance<GenreFilter>()
|
||||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (format.state) {
|
||||
AniPlayFiltersData.GENERE.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
}.joinToString(",")
|
||||
.state.filter { it.state }
|
||||
.joinToString(",") { format ->
|
||||
AniPlayFiltersData.GENRE.find { it.first == format.name }!!.second
|
||||
}
|
||||
|
||||
val tipologia: String = filters.filterIsInstance<TipologiaFilter>()
|
||||
val type: String = filters.filterIsInstance<TypeFilter>()
|
||||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (format.state) {
|
||||
AniPlayFiltersData.TIPOLOGIA.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
}.joinToString(",")
|
||||
.state.filter { it.state }
|
||||
.joinToString(",") { format ->
|
||||
AniPlayFiltersData.TYPE.find { it.first == format.name }!!.second
|
||||
}
|
||||
|
||||
val stato: String = filters.filterIsInstance<StatoFilter>()
|
||||
val status: String = filters.filterIsInstance<StatusFilter>()
|
||||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (format.state) {
|
||||
AniPlayFiltersData.STATO.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
}.joinToString(",")
|
||||
.state.filter { it.state }
|
||||
.joinToString(",") { format ->
|
||||
AniPlayFiltersData.STATUS.find { it.first == format.name }!!.second
|
||||
}
|
||||
|
||||
val origine: String = filters.filterIsInstance<OrigineFilter>()
|
||||
val origin: String = filters.filterIsInstance<OriginFilter>()
|
||||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (format.state) {
|
||||
AniPlayFiltersData.ORIGINE.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
}.joinToString(",")
|
||||
.state.filter { it.state }
|
||||
.joinToString(",") { format ->
|
||||
AniPlayFiltersData.ORIGIN.find { it.first == format.name }!!.second
|
||||
}
|
||||
|
||||
val studio: String = filters.filterIsInstance<StudioFilter>()
|
||||
.first()
|
||||
.state.mapNotNull { format ->
|
||||
if (format.state) {
|
||||
.state.filter { it.state }
|
||||
.joinToString(",") { format ->
|
||||
AniPlayFiltersData.STUDIO.find { it.first == format.name }!!.second
|
||||
} else { null }
|
||||
}.joinToString(",")
|
||||
}
|
||||
|
||||
return FilterSearchParams(
|
||||
filters.asQueryPart<OrdinaFilter>(),
|
||||
genere,
|
||||
tipologia,
|
||||
stato,
|
||||
origine,
|
||||
filters.asQueryPart<OrderFilter>(),
|
||||
genre,
|
||||
type,
|
||||
status,
|
||||
origin,
|
||||
studio,
|
||||
filters.asQueryPart<InizioFilter>(),
|
||||
filters.asQueryPart<FineFilter>(),
|
||||
filters.asQueryPart<AnniFilter>(),
|
||||
filters.asQueryPart<StagioneFilter>(),
|
||||
filters.asQueryPart<StartFilter>(),
|
||||
filters.asQueryPart<EndFilter>(),
|
||||
filters.asQueryPart<YearFilter>(),
|
||||
filters.asQueryPart<SeasonFilter>(),
|
||||
)
|
||||
}
|
||||
|
||||
private object AniPlayFiltersData {
|
||||
val ALL = Pair("All", "")
|
||||
|
||||
val ORDINA = arrayOf(
|
||||
val ORDER = arrayOf(
|
||||
Pair("Popolarità decrescente", "views,desc"),
|
||||
Pair("Popolarità crescente", "views,asc"),
|
||||
Pair("Titolo decrescente", "title,desc"),
|
||||
@ -167,7 +162,7 @@ object AniPlayFilters {
|
||||
Pair("Data di fine aggiunta", "createdDate,asc"),
|
||||
)
|
||||
|
||||
val GENERE = arrayOf(
|
||||
val GENRE = arrayOf(
|
||||
Pair("Arti marziali", "68"),
|
||||
Pair("Automobilismo", "90"),
|
||||
Pair("Avventura", "25"),
|
||||
@ -222,7 +217,7 @@ object AniPlayFilters {
|
||||
Pair("Yuri", "50"),
|
||||
)
|
||||
|
||||
val TIPOLOGIA = arrayOf(
|
||||
val TYPE = arrayOf(
|
||||
Pair("Movie", "2"),
|
||||
Pair("ONA", "4"),
|
||||
Pair("OVA", "3"),
|
||||
@ -230,7 +225,7 @@ object AniPlayFilters {
|
||||
Pair("Special", "5"),
|
||||
)
|
||||
|
||||
val STATO = arrayOf(
|
||||
val STATUS = arrayOf(
|
||||
Pair("Annunciato", "4"),
|
||||
Pair("Completato", "1"),
|
||||
Pair("In corso", "2"),
|
||||
@ -238,7 +233,7 @@ object AniPlayFilters {
|
||||
Pair("Sospeso", "3"),
|
||||
)
|
||||
|
||||
val ORIGINE = arrayOf(
|
||||
val ORIGIN = arrayOf(
|
||||
Pair("Gioco di carte", "1"),
|
||||
Pair("Light novel", "2"),
|
||||
Pair("Mange", "3"),
|
||||
@ -568,7 +563,7 @@ object AniPlayFilters {
|
||||
Pair("Zexcs", "259"),
|
||||
)
|
||||
|
||||
val STAGIONE = arrayOf(
|
||||
val SEASON = arrayOf(
|
||||
ALL,
|
||||
Pair("Inverno", "winter"),
|
||||
Pair("Primavera", "spring"),
|
||||
@ -576,7 +571,7 @@ object AniPlayFilters {
|
||||
Pair("Autunno", "fall"),
|
||||
)
|
||||
|
||||
val ANNI = arrayOf(ALL) + (1984..2023).map {
|
||||
val YEAR = arrayOf(ALL) + (1984..2023).map {
|
||||
Pair(it.toString(), it.toString())
|
||||
}.reversed().toTypedArray()
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
@ -58,15 +57,14 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
}
|
||||
|
||||
private fun getConnId() {
|
||||
val headers = Headers.headersOf(
|
||||
"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0",
|
||||
"Accept", "application/json, text/javascript, */*; q=0.01",
|
||||
"Accept-Language", "en-US,en;q=0.5",
|
||||
"Content-Type", "application/json",
|
||||
"Origin", "https://www.vvvvid.it",
|
||||
"Referer", "https://www.vvvvid.it/channel/0/you",
|
||||
"X-Requested-With", "XMLHttpRequest",
|
||||
)
|
||||
val headers = headers.newBuilder()
|
||||
.add("Accept", "application/json, text/javascript, */*; q=0.01")
|
||||
.add("Accept-Language", "en-US,en;q=0.5")
|
||||
.add("Content-Type", "application/json")
|
||||
.add("Origin", baseUrl)
|
||||
.add("Referer", "$baseUrl/channel/0/you")
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
val body = """
|
||||
{
|
||||
@ -92,7 +90,7 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
val response = client.newCall(
|
||||
POST("$baseUrl/user/login", body = body, headers = headers),
|
||||
).execute()
|
||||
if (response.code != 200) throw Exception("Failed to log in")
|
||||
if (response.code != 200) error("Failed to log in")
|
||||
val parsed = json.decodeFromString<LoginResponse>(response.body.string())
|
||||
|
||||
connId = parsed.data.conn_id
|
||||
@ -106,14 +104,13 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
getConnId()
|
||||
}
|
||||
|
||||
val headers = Headers.headersOf(
|
||||
"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0",
|
||||
"Accept", "application/json, text/javascript, */*; q=0.01",
|
||||
"Accept-Language", "en-US,en;q=0.5",
|
||||
"Cookie", "JSESSIONID=$sessionId",
|
||||
"Referer", "https://www.vvvvid.it/",
|
||||
"X-Requested-With", "XMLHttpRequest",
|
||||
)
|
||||
val headers = headers.newBuilder()
|
||||
.add("Accept", "application/json, text/javascript, */*; q=0.01")
|
||||
.add("Accept-Language", "en-US,en;q=0.5")
|
||||
.add("Cookie", "JSESSIONID=$sessionId")
|
||||
.add("Referer", "$baseUrl/")
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
if (page == 1) {
|
||||
updateFilters("anime", "Popolari")
|
||||
@ -143,14 +140,13 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
getConnId()
|
||||
}
|
||||
|
||||
val headers = Headers.headersOf(
|
||||
"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0",
|
||||
"Accept", "application/json, text/javascript, */*; q=0.01",
|
||||
"Accept-Language", "en-US,en;q=0.5",
|
||||
"Cookie", "JSESSIONID=$sessionId",
|
||||
"Referer", "https://www.vvvvid.it/",
|
||||
"X-Requested-With", "XMLHttpRequest",
|
||||
)
|
||||
val headers = headers.newBuilder()
|
||||
.add("Accept", "application/json, text/javascript, */*; q=0.01")
|
||||
.add("Accept-Language", "en-US,en;q=0.5")
|
||||
.add("Cookie", "JSESSIONID=$sessionId")
|
||||
.add("Referer", "$baseUrl/")
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
if (page == 1) {
|
||||
updateFilters("anime", "Nuove")
|
||||
@ -169,17 +165,16 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
}
|
||||
|
||||
if (query.isNotEmpty()) {
|
||||
throw Exception("Ricerca non disponibile")
|
||||
error("Ricerca non disponibile")
|
||||
}
|
||||
|
||||
val headers = Headers.headersOf(
|
||||
"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0",
|
||||
"Accept", "application/json, text/javascript, */*; q=0.01",
|
||||
"Accept-Language", "en-US,en;q=0.5",
|
||||
"Cookie", "JSESSIONID=$sessionId",
|
||||
"Referer", "https://www.vvvvid.it/",
|
||||
"X-Requested-With", "XMLHttpRequest",
|
||||
)
|
||||
val headers = headers.newBuilder()
|
||||
.add("Accept", "application/json, text/javascript, */*; q=0.01")
|
||||
.add("Accept-Language", "en-US,en;q=0.5")
|
||||
.add("Cookie", "JSESSIONID=$sessionId")
|
||||
.add("Referer", "$baseUrl/")
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
var filterStringFinal = ""
|
||||
var filterCounter = 0
|
||||
@ -329,33 +324,30 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
getConnId()
|
||||
}
|
||||
|
||||
val headers = Headers.headersOf(
|
||||
"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0",
|
||||
"Accept", "application/json, text/javascript, */*; q=0.01",
|
||||
"Accept-Language", "en-US,en;q=0.5",
|
||||
"Cookie", "JSESSIONID=$sessionId",
|
||||
"Referer", "https://www.vvvvid.it/",
|
||||
"X-Requested-With", "XMLHttpRequest",
|
||||
)
|
||||
val headers = headers.newBuilder()
|
||||
.add("Accept", "application/json, text/javascript, */*; q=0.01")
|
||||
.add("Accept-Language", "en-US,en;q=0.5")
|
||||
.add("Cookie", "JSESSIONID=$sessionId")
|
||||
.add("Referer", "$baseUrl/")
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
return GET("$baseUrl/vvvvid/ondemand/${anime.url}/info/?conn_id=$connId", headers = headers)
|
||||
}
|
||||
|
||||
override fun animeDetailsParse(response: Response): SAnime {
|
||||
val detailsJson = json.decodeFromString<InfoResponse>(response.body.string()).data
|
||||
val anime = SAnime.create()
|
||||
|
||||
anime.title = detailsJson.title
|
||||
anime.status = SAnime.UNKNOWN
|
||||
|
||||
var description = detailsJson.description + "\n"
|
||||
description += "\nAnno pubblicato: ${detailsJson.date_published}"
|
||||
description += "\n${detailsJson.additional_info.split(" | ").joinToString("\n")}"
|
||||
anime.description = description
|
||||
|
||||
anime.genre = detailsJson.show_genres?.let { it.joinToString(", ") } ?: ""
|
||||
|
||||
return anime
|
||||
return SAnime.create().apply {
|
||||
title = detailsJson.title
|
||||
status = SAnime.UNKNOWN
|
||||
genre = detailsJson.show_genres?.joinToString(", ") ?: ""
|
||||
description = buildString {
|
||||
append(detailsJson.description)
|
||||
append("\n\nAnno pubblicato: ${detailsJson.date_published}")
|
||||
append("\n${detailsJson.additional_info.split(" | ").joinToString("\n")}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================== Episodes ==============================
|
||||
@ -365,14 +357,13 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
getConnId()
|
||||
}
|
||||
|
||||
val headers = Headers.headersOf(
|
||||
"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0",
|
||||
"Accept", "application/json, text/javascript, */*; q=0.01",
|
||||
"Accept-Language", "en-US,en;q=0.5",
|
||||
"Cookie", "JSESSIONID=$sessionId",
|
||||
"Referer", "https://www.vvvvid.it/",
|
||||
"X-Requested-With", "XMLHttpRequest",
|
||||
)
|
||||
val headers = headers.newBuilder()
|
||||
.add("Accept", "application/json, text/javascript, */*; q=0.01")
|
||||
.add("Accept-Language", "en-US,en;q=0.5")
|
||||
.add("Cookie", "JSESSIONID=$sessionId")
|
||||
.add("Referer", "$baseUrl/")
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
return GET("$baseUrl/vvvvid/ondemand/${anime.url}/seasons/?conn_id=$connId", headers = headers)
|
||||
}
|
||||
@ -380,7 +371,7 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
override fun episodeListParse(response: Response): List<SEpisode> {
|
||||
val animeJson = json.decodeFromString<SeasonsResponse>(response.body.string())
|
||||
val episodeList = mutableListOf<SEpisode>()
|
||||
val subDub = preferences.getString("preferred_sub", "none")!!
|
||||
val subDub = preferences.getString(PREF_SUB_KEY, PREF_SUB_DEFAULT)!!
|
||||
|
||||
var counter = 1
|
||||
animeJson.data.forEach {
|
||||
@ -395,11 +386,13 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
}
|
||||
|
||||
it.episodes.forEach { ep ->
|
||||
val episode = SEpisode.create()
|
||||
episode.name = "$prefix${ep.number} ${ep.title}"
|
||||
episode.episode_number = counter.toFloat()
|
||||
episode.url = LinkData(it.show_id, ep.season_id, ep.video_id).toJsonString()
|
||||
episodeList.add(episode)
|
||||
episodeList.add(
|
||||
SEpisode.create().apply {
|
||||
name = "$prefix${ep.number} ${ep.title}"
|
||||
episode_number = counter.toFloat()
|
||||
url = LinkData(it.show_id, ep.season_id, ep.video_id).toJsonString()
|
||||
},
|
||||
)
|
||||
counter++
|
||||
}
|
||||
}
|
||||
@ -429,14 +422,13 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
|
||||
val mediaId = json.decodeFromString<LinkData>(episode.url)
|
||||
|
||||
val headers = Headers.headersOf(
|
||||
"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0",
|
||||
"Accept", "application/json, text/javascript, */*; q=0.01",
|
||||
"Accept-Language", "en-US,en;q=0.5",
|
||||
"Cookie", "JSESSIONID=$sessionId",
|
||||
"Referer", "https://www.vvvvid.it/",
|
||||
"X-Requested-With", "XMLHttpRequest",
|
||||
)
|
||||
val headers = headers.newBuilder()
|
||||
.add("Accept", "application/json, text/javascript, */*; q=0.01")
|
||||
.add("Accept-Language", "en-US,en;q=0.5")
|
||||
.add("Cookie", "JSESSIONID=$sessionId")
|
||||
.add("Referer", "$baseUrl/")
|
||||
.add("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
return Pair(
|
||||
GET(
|
||||
@ -528,13 +520,12 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
}
|
||||
|
||||
private fun videoFromDash(url: String, name: String): Video {
|
||||
val dashHeaders = Headers.headersOf(
|
||||
"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0",
|
||||
"Accept", "*/*",
|
||||
"Accept-Language", "en-US,en;q=0.5",
|
||||
"Origin", "https://www.vvvvid.it",
|
||||
"Referer", "https://www.vvvvid.it/",
|
||||
)
|
||||
val dashHeaders = headers.newBuilder()
|
||||
.add("Accept", "*/*")
|
||||
.add("Accept-Language", "en-US,en;q=0.5")
|
||||
.add("Origin", baseUrl)
|
||||
.add("Referer", "$baseUrl/")
|
||||
.build()
|
||||
|
||||
val dashContents = client.newCall(
|
||||
GET(url, headers = dashHeaders),
|
||||
@ -545,24 +536,14 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
val audioUrl = dashContents.substringAfter("mimeType=\"audio").substringBefore("</BaseURL>").substringAfter("<BaseURL>")
|
||||
|
||||
val audioTracks = mutableListOf<Track>()
|
||||
try {
|
||||
audioTracks.add(Track("$baseVideoUrl/$audioUrl", "Audio"))
|
||||
} catch (_: Error) { }
|
||||
|
||||
return try {
|
||||
Video(
|
||||
return Video(
|
||||
baseVideoUrl,
|
||||
name,
|
||||
"$baseVideoUrl/$videoUrl",
|
||||
audioTracks = audioTracks,
|
||||
)
|
||||
} catch (_: Error) {
|
||||
Video(
|
||||
baseVideoUrl,
|
||||
name,
|
||||
"$baseVideoUrl/$videoUrl",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRandomIntString(): String {
|
||||
@ -577,7 +558,7 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
}
|
||||
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
val quality = preferences.getString("preferred_quality", "HD")!!
|
||||
val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!
|
||||
|
||||
return this.sortedWith(
|
||||
compareBy { it.quality.contains(quality) },
|
||||
@ -656,13 +637,23 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
return d
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PREF_SUB_KEY = "preferred_sub"
|
||||
private const val PREF_SUB_DEFAULT = "none"
|
||||
|
||||
private const val PREF_QUALITY_KEY = "preferred_quality"
|
||||
private const val PREF_QUALITY_DEFAULT = "HD"
|
||||
}
|
||||
|
||||
// ============================== Settings ==============================
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
val subDubPref = ListPreference(screen.context).apply {
|
||||
key = "preferred_sub"
|
||||
ListPreference(screen.context).apply {
|
||||
key = PREF_SUB_KEY
|
||||
title = "Preferenza sub/dub"
|
||||
entries = arrayOf("Nessuno", "Sub", "Dub")
|
||||
entryValues = arrayOf("none", "sub", "dub")
|
||||
setDefaultValue("none")
|
||||
setDefaultValue(PREF_SUB_DEFAULT)
|
||||
summary = "%s"
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
@ -671,14 +662,14 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
val entry = entryValues[index] as String
|
||||
preferences.edit().putString(key, entry).commit()
|
||||
}
|
||||
}
|
||||
}.also(screen::addPreference)
|
||||
|
||||
val videoQualityPref = ListPreference(screen.context).apply {
|
||||
key = "preferred_quality"
|
||||
ListPreference(screen.context).apply {
|
||||
key = PREF_QUALITY_KEY
|
||||
title = "Qualità preferita"
|
||||
entries = arrayOf("HD", "SD")
|
||||
entryValues = arrayOf("HD", "SD")
|
||||
setDefaultValue("HD")
|
||||
setDefaultValue(PREF_QUALITY_DEFAULT)
|
||||
summary = "%s"
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
@ -687,9 +678,6 @@ class VVVVID : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
val entry = entryValues[index] as String
|
||||
preferences.edit().putString(key, entry).commit()
|
||||
}
|
||||
}
|
||||
|
||||
screen.addPreference(subDubPref)
|
||||
screen.addPreference(videoQualityPref)
|
||||
}.also(screen::addPreference)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user