fix(pt/animeszone): Removed dead source Animes Zone (#606)

This commit is contained in:
WebDitto 2025-02-01 13:57:45 -03:00 committed by GitHub
parent 41e37c016f
commit a0ec79cd9d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 0 additions and 840 deletions

View file

@ -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>

View file

@ -1,12 +0,0 @@
ext {
extName = 'AnimesZone'
extClass = '.AnimesZone'
extVersionCode = 8
isNsfw = true
}
apply from: "$rootDir/common.gradle"
dependencies {
implementation(project(':lib:dood-extractor'))
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

View file

@ -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)
}
}

View file

@ -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")
}
}

View file

@ -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"),
)
}
}

View file

@ -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)
}
}
}
}

View file

@ -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)
}
}
}