diff --git a/src/pt/animeszone/AndroidManifest.xml b/src/pt/animeszone/AndroidManifest.xml deleted file mode 100644 index bc031e78..00000000 --- a/src/pt/animeszone/AndroidManifest.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android"> - - <application> - <activity - android:name=".pt.animeszone.AZUrlActivity" - android:excludeFromRecents="true" - android:exported="true" - android:theme="@android:style/Theme.NoDisplay"> - <intent-filter> - <action android:name="android.intent.action.VIEW" /> - - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> - - <data - android:host="animeszone.net" - android:pathPattern="/..*/..*" - android:scheme="https" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/src/pt/animeszone/build.gradle b/src/pt/animeszone/build.gradle deleted file mode 100644 index 6b089449..00000000 --- a/src/pt/animeszone/build.gradle +++ /dev/null @@ -1,12 +0,0 @@ -ext { - extName = 'AnimesZone' - extClass = '.AnimesZone' - extVersionCode = 8 - isNsfw = true -} - -apply from: "$rootDir/common.gradle" - -dependencies { - implementation(project(':lib:dood-extractor')) -} diff --git a/src/pt/animeszone/res/mipmap-hdpi/ic_launcher.png b/src/pt/animeszone/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 2d1732e1..00000000 Binary files a/src/pt/animeszone/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/animeszone/res/mipmap-mdpi/ic_launcher.png b/src/pt/animeszone/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 0fb7c62e..00000000 Binary files a/src/pt/animeszone/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/animeszone/res/mipmap-xhdpi/ic_launcher.png b/src/pt/animeszone/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index be1ee581..00000000 Binary files a/src/pt/animeszone/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/animeszone/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/animeszone/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 489695ae..00000000 Binary files a/src/pt/animeszone/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/animeszone/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/animeszone/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 39fb6769..00000000 Binary files a/src/pt/animeszone/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/animeszone/res/web_hi_res_512.png b/src/pt/animeszone/res/web_hi_res_512.png deleted file mode 100644 index 07d80ae4..00000000 Binary files a/src/pt/animeszone/res/web_hi_res_512.png and /dev/null differ diff --git a/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/AZUrlActivity.kt b/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/AZUrlActivity.kt deleted file mode 100644 index e701aadf..00000000 --- a/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/AZUrlActivity.kt +++ /dev/null @@ -1,42 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.pt.animeszone - -import android.app.Activity -import android.content.ActivityNotFoundException -import android.content.Intent -import android.os.Bundle -import android.util.Log -import kotlin.system.exitProcess - -/** - * Springboard that accepts https://animeszone.net/<type>/<slug> intents - * and redirects them to the main Aniyomi process. - */ -class AZUrlActivity : Activity() { - - private val tag = javaClass.simpleName - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val pathSegments = intent?.data?.pathSegments - if (pathSegments != null && pathSegments.size > 1) { - val searchQuery = "${pathSegments[0]}/${pathSegments[1]}" - - val mainIntent = Intent().apply { - action = "eu.kanade.tachiyomi.ANIMESEARCH" - putExtra("query", "${AnimesZone.PREFIX_SEARCH}$searchQuery") - putExtra("filter", packageName) - } - - try { - startActivity(mainIntent) - } catch (e: ActivityNotFoundException) { - Log.e(tag, e.toString()) - } - } else { - Log.e(tag, "could not parse uri from intent $intent") - } - - finish() - exitProcess(0) - } -} diff --git a/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/AnimesZone.kt b/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/AnimesZone.kt deleted file mode 100644 index 04f40496..00000000 --- a/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/AnimesZone.kt +++ /dev/null @@ -1,439 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.pt.animeszone - -import android.app.Application -import androidx.preference.ListPreference -import androidx.preference.PreferenceScreen -import app.cash.quickjs.QuickJs -import eu.kanade.tachiyomi.animeextension.pt.animeszone.extractors.BloggerJWPlayerExtractor -import eu.kanade.tachiyomi.animeextension.pt.animeszone.extractors.PlaylistExtractor -import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource -import eu.kanade.tachiyomi.animesource.model.AnimeFilterList -import eu.kanade.tachiyomi.animesource.model.AnimesPage -import eu.kanade.tachiyomi.animesource.model.SAnime -import eu.kanade.tachiyomi.animesource.model.SEpisode -import eu.kanade.tachiyomi.animesource.model.Video -import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource -import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.POST -import eu.kanade.tachiyomi.network.awaitSuccess -import eu.kanade.tachiyomi.util.asJsoup -import eu.kanade.tachiyomi.util.parseAs -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.Request -import okhttp3.RequestBody.Companion.toRequestBody -import okhttp3.Response -import org.jsoup.Jsoup -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get -import uy.kohesive.injekt.injectLazy - -class AnimesZone : ConfigurableAnimeSource, ParsedAnimeHttpSource() { - - override val name = "AnimesZone" - - override val baseUrl = "https://animeszone.net" - - override val lang = "pt-BR" - - override val supportsLatest = true - - override fun headersBuilder() = super.headersBuilder() - .add("Referer", "$baseUrl/") - .add("Origin", baseUrl) - - private val json: Json by injectLazy() - - private val preferences by lazy { - Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) - } - - // ============================== Popular =============================== - override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/tendencia/") - - override fun popularAnimeSelector(): String = "div.items > div.seriesList" - - override fun popularAnimeNextPageSelector(): String? = null - - override fun popularAnimeFromElement(element: Element) = SAnime.create().apply { - setUrlWithoutDomain(element.selectFirst("a[href]")!!.attr("abs:href")) - thumbnail_url = element.selectFirst("div.cover-image")?.run { - attr("style").substringAfter("url('").substringBefore("'") - } - title = element.selectFirst("span.series-title")!!.text() - } - - // =============================== Latest =============================== - override fun latestUpdatesRequest(page: Int): Request { - return if (page == 1) { - GET("$baseUrl/animes-legendados/") - } else { - GET("$baseUrl/animes-legendados/page/$page/") - } - } - - override fun latestUpdatesSelector(): String = "main#list-animes ul.post-lst > li" - - override fun latestUpdatesNextPageSelector(): String = "div.paginadorplay > a.active + a" - - override fun latestUpdatesFromElement(element: Element) = SAnime.create().apply { - setUrlWithoutDomain(element.selectFirst("div.aniItem > a[href]")!!.attr("abs:href")) - thumbnail_url = element.selectFirst("div.aniItemImg img[src]")?.attr("abs:src") - title = element.selectFirst("h2.aniTitulo")!!.text() - } - - // =============================== Search =============================== - override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage { - return if (query.startsWith(PREFIX_SEARCH)) { - val path = query.removePrefix(PREFIX_SEARCH) - client.newCall(GET("$baseUrl/$path")) - .awaitSuccess() - .use(::searchAnimeByIdParse) - } else { - super.getSearchAnime(page, query, filters) - } - } - - private fun searchAnimeByIdParse(response: Response): AnimesPage { - val details = animeDetailsParse(response).apply { - setUrlWithoutDomain(response.request.url.toString()) - initialized = true - } - - return AnimesPage(listOf(details), false) - } - - override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { - val params = AnimesZoneFilters.getSearchParameters(filters) - - val cleanQuery = query.replace(" ", "%20") - val queryQuery = if (query.isBlank()) { - "" - } else { - "&_pesquisa=$cleanQuery" - } - val url = "$baseUrl/?s=${params.genre}${params.year}${params.version}${params.studio}${params.type}${params.adult}$queryQuery" - - val httpParams = url.substringAfter("$baseUrl/?").split("&").joinToString(",") { - val (key, value) = it.split("=", limit = 2) - "\"$key\":\"$value\"" - } - val softRefresh = if (page == 1) 0 else 1 - val jsonBody = """ - { - "action":"facetwp_refresh", - "data":{ - "facets":{ - "generos":[ - ${queryToJsonList(params.genre)} - ], - "versao":[ - ${queryToJsonList(params.year)} - ], - "tipo":[ - ${queryToJsonList(params.version)} - ], - "estudio":[ - ${queryToJsonList(params.studio)} - ], - "tipototal":[ - ${queryToJsonList(params.type)} - ], - "adulto":[ - ${queryToJsonList(params.adult)} - ], - "pesquisa":"$query", - "paginar":[ - - ] - }, - "frozen_facets":{ - - }, - "http_params":{ - "get":{ - $httpParams - }, - "uri":"", - "url_vars":[ - - ] - }, - "template":"wp", - "extras":{ - "sort":"default" - }, - "soft_refresh":$softRefresh, - "is_bfcache":1, - "first_load":0, - "paged":$page - } - } - """.trimIndent().toRequestBody("application/json".toMediaType()) - - return POST(url, headers, jsonBody) - } - - override fun searchAnimeParse(response: Response): AnimesPage { - val parsed = response.parseAs<PostResponse>() - - val document = Jsoup.parse(parsed.template) - - val animes = document.select(searchAnimeSelector()).map(::searchAnimeFromElement) - - val hasNextPage = parsed.settings.pager.run { page < total_pages } - - return AnimesPage(animes, hasNextPage) - } - - override fun searchAnimeSelector(): String = "div.aniItem" - - override fun searchAnimeNextPageSelector(): String? = null - - override fun searchAnimeFromElement(element: Element) = SAnime.create().apply { - setUrlWithoutDomain(element.selectFirst("a[href]")!!.attr("href")) - thumbnail_url = element.selectFirst("img[src]")?.attr("abs:src") - title = element.selectFirst("div.aniInfos")?.text() ?: "Anime" - } - - // ============================== FILTERS =============================== - override fun getFilterList(): AnimeFilterList = AnimesZoneFilters.FILTER_LIST - - // =========================== Anime Details ============================ - override fun animeDetailsParse(document: Document) = SAnime.create().apply { - title = document.selectFirst("div.container > div div.bottom-div > h4")?.ownText() - ?: document.selectFirst("div#info > h1")?.text() - ?: "Anime" - thumbnail_url = document.selectFirst("div.container > div > img[src]")?.attr("abs:src") - description = document.selectFirst("section#sinopse p:matches(.)")?.text() - ?: document.selectFirst("div.content.right > dialog > p:matches(.)")?.text() - genre = document.select("div.card-body table > tbody > tr:has(>td:contains(Genres)) td > a").joinToString { it.text() } - } - - // ============================== Episodes ============================== - override fun episodeListParse(response: Response): List<SEpisode> { - val document = response.asJsoup() - - val singleVideo = document.selectFirst("div.anime__video__player") - - // First check if single episode - return if (singleVideo != null) { - SEpisode.create().apply { - name = document.selectFirst("div#info h1")?.text() ?: "Episódio" - episode_number = 1F - setUrlWithoutDomain(document.location()) - }.let(::listOf) - } else { - buildList { - document.select(episodeListSelector()).forEach { ep -> - val name = ep.selectFirst("h2.aniTitulo")?.text()?.trim() - // Check if it's multi-season - var nextPageUrl = when { - name != null && name.startsWith("temporada ", true) -> ep.selectFirst("a[href]")!!.attr("href") - else -> { - add(episodeFromElement(ep, size + 1)) - document.nextPageUrl() - } - } - - while (nextPageUrl != null) { - val seasonDocument = client.newCall(GET(nextPageUrl)).execute() - .asJsoup() - - seasonDocument.select(episodeListSelector()).forEach { seasonEp -> - add(episodeFromElement(seasonEp, size + 1, name)) - } - - nextPageUrl = seasonDocument.nextPageUrl() - } - } - - reverse() - } - } - } - - private fun Document.nextPageUrl() = selectFirst("div.paginadorplay > a:contains(Próxima Pagina)")?.absUrl("href") - - override fun episodeListSelector(): String = "main.site-main ul.post-lst > li" - - private fun episodeFromElement(element: Element, counter: Int, info: String? = null): SEpisode { - val epTitle = element.selectFirst("div.title")?.text() ?: element.text() - val epNumber = element.selectFirst("span.epiTipo") - - return SEpisode.create().apply { - name = "Ep. ${epNumber?.text()?.trim() ?: counter} - ${epTitle.replace(EPISODE_REGEX, "")}" - .replace(" - - ", " - ") - episode_number = epNumber?.run { - text().trim().toFloatOrNull() - } ?: counter.toFloat() - scanlator = info - setUrlWithoutDomain(element.selectFirst("article > a")!!.attr("href")) - } - } - - override fun episodeFromElement(element: Element): SEpisode = throw UnsupportedOperationException() - - // ============================ Video Links ============================= - override fun videoListParse(response: Response): List<Video> { - val document = response.asJsoup() - - val videoList = document.select("div#playeroptions li[data-post]").flatMap { vid -> - val jsonHeaders = headersBuilder() - .add("Accept", "application/json, text/javascript, */*; q=0.01") - .add("X-Requested-With", "XMLHttpRequest") - .build() - - val post = vid.attr("data-post") - val type = vid.attr("data-type") - val nume = vid.attr("data-nume") - - val apires = client.newCall( - GET("$baseUrl/wp-json/dooplayer/v2/$post/$type/$nume", jsonHeaders), - ).execute() - - val url = apires.parseAs<VideoResponse>().embed_url - - when { - url.startsWith("https://dood") -> DoodExtractor(client).videosFromUrl(url, vid.text().trim()) - "https://gojopoolt" in url -> { - client.newCall(GET(url, headers)).execute() - .asJsoup() - .selectFirst("script:containsData(sources:)") - ?.data() - ?.let(BloggerJWPlayerExtractor::videosFromScript) - .orEmpty() - } - url.startsWith(baseUrl) -> videosFromInternalUrl(url) - "blogger.com" in url -> extractBloggerVideos(url, vid.text().trim()) - else -> emptyList() - } - } - - return videoList - } - - private fun videosFromInternalUrl(url: String): List<Video> { - val videoDocument = client.newCall(GET(url, headers)).execute() - .asJsoup() - - val script = videoDocument.selectFirst("script:containsData(decodeURIComponent)")?.data() - ?.let(::getDecrypted) - ?: videoDocument.selectFirst("script:containsData(sources:)")?.data() - ?: return emptyList() - - return when { - "/bloggerjwplayer" in url || "jwplayer-2" in url || "/ctaplayer" in url -> { - BloggerJWPlayerExtractor.videosFromScript(script) - } - "/m3u8" in url -> PlaylistExtractor.videosFromScript(script) - else -> emptyList() - } - } - - private fun extractBloggerVideos(url: String, name: String): List<Video> { - return client.newCall(GET(url, headers)).execute() - .body.string() - .takeIf { !it.contains("errorContainer") } - .let { it ?: return emptyList() } - .substringAfter("\"streams\":[") - .substringBefore("]") - .split("},") - .map { - val videoUrl = it.substringAfter("{\"play_url\":\"").substringBefore('"') - val format = it.substringAfter("\"format_id\":").substringBefore("}") - val quality = when (format) { - "18" -> "360p" - "22" -> "720p" - else -> "Unknown" - } - Video(videoUrl, "$quality - $name", videoUrl, headers = headers) - } - } - - override fun videoFromElement(element: Element): Video = throw UnsupportedOperationException() - - override fun videoListSelector(): String = throw UnsupportedOperationException() - - override fun videoUrlParse(document: Document): String = throw UnsupportedOperationException() - - // ============================== Settings ============================== - override fun setupPreferenceScreen(screen: PreferenceScreen) { - ListPreference(screen.context).apply { - key = PREF_QUALITY_KEY - title = PREF_QUALITY_TITLE - 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) - } - - // ============================= Utilities ============================== - private fun getDecrypted(script: String): String? { - val patchedScript = script.trim().split("\n").first() - .replace("eval(function", "function a") - .replace("decodeURIComponent(escape(r))}(", "r};a(") - .substringBeforeLast(")") - - return QuickJs.create().use { - it.evaluate(patchedScript)?.toString() - } - } - - private fun queryToJsonList(input: String): String { - if (input.isEmpty()) return "" - return input.substringAfter("=").split("%2C").joinToString(",") { - "\"$it\"" - } - } - - @Serializable - data class VideoResponse(val embed_url: String) - - @Serializable - data class PostResponse( - val template: String, - val settings: Settings, - ) { - @Serializable - data class Settings(val pager: Pager) { - @Serializable - data class Pager( - val page: Int, - val total_pages: Int, - ) - } - } - - override fun List<Video>.sort(): List<Video> { - val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!! - - return sortedWith( - compareBy { it.quality.contains(quality) }, - ).reversed() - } - - companion object { - const val PREFIX_SEARCH = "id:" - - private val EPISODE_REGEX by lazy { Regex("""Episódio ?\d+\.?\d* ?""") } - - private const val PREF_QUALITY_KEY = "preferred_quality" - private const val PREF_QUALITY_TITLE = "Qualidade preferida" - private const val PREF_QUALITY_DEFAULT = "720" - private val PREF_QUALITY_ENTRIES = arrayOf("1080p", "720p", "480p", "360p") - private val PREF_QUALITY_VALUES = arrayOf("1080", "720", "480", "360") - } -} diff --git a/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/AnimesZoneFilters.kt b/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/AnimesZoneFilters.kt deleted file mode 100644 index 73e82ee7..00000000 --- a/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/AnimesZoneFilters.kt +++ /dev/null @@ -1,279 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.pt.animeszone - -import eu.kanade.tachiyomi.animesource.model.AnimeFilter -import eu.kanade.tachiyomi.animesource.model.AnimeFilterList - -object AnimesZoneFilters { - open class QueryPartFilter( - displayName: String, - val vals: Array<Pair<String, String>>, - ) : AnimeFilter.Select<String>( - displayName, - vals.map { it.first }.toTypedArray(), - ) { - fun toQueryPart() = vals[state].second - } - - open class CheckBoxFilterList(name: String, values: List<CheckBox>) : AnimeFilter.Group<AnimeFilter.CheckBox>(name, values) - private class CheckBoxVal(name: String, state: Boolean = false) : AnimeFilter.CheckBox(name, state) - - private inline fun <reified R> AnimeFilterList.asQueryPart(name: String): String { - return (first { it is R } as QueryPartFilter).toQueryPart() - .takeUnless(String::isEmpty) - ?.let { "&$name=$it" } - .orEmpty() - } - - private inline fun <reified R> AnimeFilterList.parseCheckbox( - options: Array<Pair<String, String>>, - name: String, - ): String { - return (first { it is R } as CheckBoxFilterList).state - .asSequence() - .filter { it.state } - .map { checkbox -> options.find { it.first == checkbox.name }!!.second } - .filter(String::isNotBlank) - .joinToString("%2C") { "&$name=$it" } - } - - class GenreFilter : CheckBoxFilterList( - "Selecionar Gêneros", - AnimesZoneFiltersData.GENRE.map { CheckBoxVal(it.first, false) }, - ) - - class YearFilter : QueryPartFilter("Ano", AnimesZoneFiltersData.YEAR) - - class VersionFilter : QueryPartFilter("Versão", AnimesZoneFiltersData.VERSION) - - class StudioFilter : CheckBoxFilterList( - "Estudio", - AnimesZoneFiltersData.STUDIO.map { CheckBoxVal(it.first, false) }, - ) - - class TypeFilter : QueryPartFilter("Tipo", AnimesZoneFiltersData.TYPE) - - class AdultFilter : QueryPartFilter("Adulto", AnimesZoneFiltersData.ADULT) - - val FILTER_LIST get() = AnimeFilterList( - GenreFilter(), - StudioFilter(), - YearFilter(), - VersionFilter(), - TypeFilter(), - AdultFilter(), - ) - - data class FilterSearchParams( - val genre: String = "", - val year: String = "", - val version: String = "", - val studio: String = "", - val type: String = "", - val adult: String = "", - ) - - internal fun getSearchParameters(filters: AnimeFilterList): FilterSearchParams { - if (filters.isEmpty()) return FilterSearchParams() - - return FilterSearchParams( - filters.parseCheckbox<GenreFilter>(AnimesZoneFiltersData.GENRE, "_generos"), - filters.asQueryPart<YearFilter>("_versao"), - filters.asQueryPart<VersionFilter>("_tipo"), - filters.parseCheckbox<StudioFilter>(AnimesZoneFiltersData.STUDIO, "_estudio"), - filters.asQueryPart<TypeFilter>("_tipototal"), - filters.asQueryPart<AdultFilter>("_adulto"), - ) - } - - private object AnimesZoneFiltersData { - val ANY = Pair("Selecione", "") - - val GENRE = arrayOf( - Pair("Comédia", "comedia"), - Pair("Ação", "acao"), - Pair("Fantasia", "fantasia"), - Pair("Romance", "romance"), - Pair("Drama", "drama"), - Pair("Escolar", "escolar"), - Pair("Aventura", "aventura"), - Pair("Shounen", "shounen"), - Pair("Sobrenatural", "sobrenatural"), - Pair("Slice-of-life", "slice-of-life"), - Pair("Sci-Fi", "sci-fi"), - Pair("Ecchi", "ecchi"), - Pair("Mistério", "misterio"), - Pair("Seinen", "seinen"), - Pair("Magia", "magia"), - Pair("Animação", "animacao"), - Pair("Harem", "harem"), - Pair("Psicológico", "psicologico"), - Pair("Super Poder", "super-poder"), - Pair("Violência", "violencia"), - Pair("Sci-Fi & Fantasy", "sci-fi-fantasy"), - Pair("Histórico", "historico"), - Pair("Isekai", "isekai"), - Pair("Mecha", "mecha"), - Pair("Demónio", "demonio"), - Pair("Terror", "terror"), - Pair("Esportes", "esportes"), - Pair("Militar", "militar"), - Pair("Artes Marciais", "artes-marciais"), - Pair("Jogo", "jogo"), - Pair("Vampiro", "vampiro"), - Pair("Musical", "musical"), - Pair("Suspense", "suspense"), - Pair("Paródia", "parodia"), - Pair("Shoujo", "shoujo"), - Pair("Nudez", "nudez"), - Pair("Supernatural", "supernatural"), - Pair("Espacial", "espacial"), - Pair("Shoujo-ai", "shoujo-ai"), - Pair("Crime", "crime"), - Pair("Policial", "policial"), - Pair("Ficção Científica", "ficcao-cientifica"), - Pair("Samurai", "samurai"), - Pair("Josei", "josei"), - Pair("Action & Adventure", "action-adventure"), - Pair("Amizade", "amizade"), - Pair("Horror", "horror"), - Pair("Família", "familia"), - Pair("Música", "musica"), - Pair("Insanidade", "insanidade"), - Pair("Obsceno", "obsceno"), - Pair("Shounen-ai", "shounen-ai"), - Pair("Carros", "carros"), - Pair("Gore", "gore"), - Pair("War & Politics", "war-politics"), - Pair("Yaoi", "yaoi"), - Pair("Cinema TV", "cinema-tv"), - Pair("Gourmet", "gourmet"), - Pair("Infantil", "infantil"), - Pair("Vida Escolar", "vida-escolar"), - ) - - val YEAR = arrayOf(ANY) + (1986..2024).map { - Pair(it.toString(), it.toString()) - }.reversed().toTypedArray() - - val VERSION = arrayOf( - ANY, - Pair("Legendados", "legendada"), - Pair("Dublado", "series02"), - Pair("Seção de Hentais", "series03"), - ) - - val STUDIO = arrayOf( - Pair("J.C.Staff", "j-c-staff"), - Pair("Shueisha", "shueisha"), - Pair("Aniplex", "aniplex"), - Pair("BONES", "bones"), - Pair("Kadokawa", "kadokawa"), - Pair("TOHO Animation", "toho-animation"), - Pair("Pony Canyon", "pony-canyon"), - Pair("A-1 Pictures", "a-1-pictures"), - Pair("DENTSU", "dentsu"), - Pair("Kodansha", "kodansha"), - Pair("Production I.G", "production-i-g"), - Pair("CloverWorks", "cloverworks"), - Pair("Madhouse", "madhouse"), - Pair("Bit grooove promotion", "bit-grooove-promotion"), - Pair("MAPPA", "mappa"), - Pair("SILVER LINK.", "silver-link"), - Pair("Wit Studio", "wit-studio"), - Pair("Magic Capsule", "magic-capsule"), - Pair("OLM", "olm"), - Pair("Lantis", "lantis"), - Pair("Movic", "movic"), - Pair("SATELIGHT", "satelight"), - Pair("Shogakukan-Shueisha Productions", "shogakukan-shueisha-productions"), - Pair("Square Enix", "square-enix"), - Pair("STUDIO MAUSU", "studio-mausu"), - Pair("Yomiuri Telecasting Corporation", "yomiuri-telecasting-corporation"), - Pair("Bandai Namco Arts", "bandai-namco-arts"), - Pair("David Production", "david-production"), - Pair("EGG FIRM", "egg-firm"), - Pair("Lerche", "lerche"), - Pair("Liden Films", "liden-films"), - Pair("Sony Music Entertainment", "sony-music-entertainment-japan"), - Pair("Studio Deen", "studio-deen"), - Pair("TMS Entertainment", "tms-entertainment"), - Pair("Toho", "toho"), - Pair("Crunchyroll", "crunchyroll"), - Pair("dugout", "dugout"), - Pair("ENGI", "engi"), - Pair("MBS", "mbs"), - Pair("P.A.Works", "p-a-works"), - Pair("Tezuka Productions", "tezuka-productions"), - Pair("TV Tokyo", "tv-tokyo"), - Pair("Warner Bros. Japan", "warner-bros-japan"), - Pair("White Fox", "white-fox"), - Pair("avex pictures", "avex-pictures"), - Pair("Bibury Animation Studios", "bibury-animation-studios"), - Pair("Brain's Base", "brains-base"), - Pair("DMM music", "dmm-music"), - Pair("DMM pictures", "dmm-pictures"), - Pair("feel.", "feel"), - Pair("Hakuhodo DY Music & Pictures", "hakuhodo-dy-music-pictures"), - Pair("Lidenfilms", "lidenfilms"), - Pair("MAHO FILM", "maho-film"), - Pair("NHK Enterprises", "nhk-enterprises"), - Pair("Passione", "passione"), - Pair("Pierrot", "pierrot"), - Pair("Pine Jam", "pine-jam"), - Pair("Pink Pineapple", "pink-pineapple"), - Pair("project No.9", "project-no-9"), - Pair("Seven", "seven"), - Pair("SHAFT", "shaft"), - Pair("TNK", "tnk"), - Pair("Zero-G", "zero-g"), - Pair("Asahi Production", "asahi-production"), - Pair("asread", "asread"), - Pair("AT-X", "at-x"), - Pair("Bandai Namco Pictures", "bandai-namco-pictures"), - Pair("BS Fuji", "bs-fuji"), - Pair("C2C", "c2c"), - Pair("Children's Playground Entertainment", "childrens-playground-entertainment"), - Pair("diomedéa", "diomedea"), - Pair("Doga Kobo", "doga-kobo"), - Pair("Geno Studio", "geno-studio"), - Pair("Good Smile Company", "good-smile-company"), - Pair("Graphinica", "graphinica"), - Pair("Hakusensha", "hakusensha"), - Pair("HALF H·P STUDIO", "f279ee47217fbae84c07eb11181f4997"), - Pair("King Records", "king-records"), - Pair("Kyoto Animation", "kyoto-animation"), - Pair("Nippon BS Broadcasting", "nippon-bs-broadcasting"), - Pair("Nippon Columbia", "nippon-columbia"), - Pair("Nitroplus", "nitroplus"), - Pair("Shogakukan", "shogakukan"), - Pair("Sotsu", "sotsu"), - Pair("Sound Team・Don Juan", "45e6f4604baaebfbebf4f43139db8d68"), - Pair("Studio Gokumi", "studio-gokumi"), - Pair("Suiseisha", "suiseisha"), - Pair("SUNRISE", "sunrise"), - Pair("SynergySP", "synergysp"), - Pair("Techno Sound", "techno-sound"), - Pair("THE KLOCKWORX", "the-klockworx"), - Pair("Toei Animation", "toei-animation"), - Pair("TOY'S FACTORY", "toys-factory"), - Pair("Twin Engine", "twin-engine"), - Pair("ufotable", "ufotable"), - Pair("ABC Animation", "abc-animation"), - Pair("Ajiado", "ajiado"), - Pair("APDREAM", "apdream"), - Pair("Ashi Productions", "ashi-productions"), - ) - - val TYPE = arrayOf( - ANY, - Pair("TV Shows", "tvshows"), - Pair("Filmes", "movies"), - ) - - val ADULT = arrayOf( - ANY, - Pair("Hentais", "dublada"), - Pair("Seção de Hentais", "series03"), - ) - } -} diff --git a/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/extractors/BloggerJWPlayerExtractor.kt b/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/extractors/BloggerJWPlayerExtractor.kt deleted file mode 100644 index c655a3e8..00000000 --- a/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/extractors/BloggerJWPlayerExtractor.kt +++ /dev/null @@ -1,27 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.pt.animeszone.extractors - -import eu.kanade.tachiyomi.animesource.model.Video - -object BloggerJWPlayerExtractor { - fun videosFromScript(script: String): List<Video> { - val sources = script.substringAfter("sources: [").substringBefore("],") - - return sources.split("{").drop(1).mapNotNull { - val label = it.substringAfter("label") - .substringAfter(':') - .substringAfter('"') - .substringBefore('"') - - val videoUrl = it.substringAfter("file") - .substringAfter(':') - .substringAfter('"') - .substringBefore('"') - .replace("\\", "") - if (videoUrl.isEmpty()) { - null - } else { - Video(videoUrl, "BloggerJWPlayer - $label", videoUrl) - } - } - } -} diff --git a/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/extractors/PlaylistExtractor.kt b/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/extractors/PlaylistExtractor.kt deleted file mode 100644 index 69d0d58c..00000000 --- a/src/pt/animeszone/src/eu/kanade/tachiyomi/animeextension/pt/animeszone/extractors/PlaylistExtractor.kt +++ /dev/null @@ -1,18 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.pt.animeszone.extractors - -import eu.kanade.tachiyomi.animesource.model.Video - -object PlaylistExtractor { - fun videosFromScript(script: String): List<Video> { - val sources = script.substringAfter("sources: [").substringBefore("],") - - return sources.split("file:\"").drop(1).mapNotNull { source -> - val url = source.substringBefore("\"").ifEmpty { return@mapNotNull null } - val label = source.substringAfter("label:\"").substringBefore("\"") - .replace("FHD", "1080p") - .replace("HD", "720p") - .replace("SD", "480p") - Video(url, "Playlist - $label", url) - } - } -}