diff --git a/src/pt/animestc/AndroidManifest.xml b/src/pt/animestc/AndroidManifest.xml deleted file mode 100644 index e826c520..00000000 --- a/src/pt/animestc/AndroidManifest.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/src/pt/animestc/build.gradle b/src/pt/animestc/build.gradle deleted file mode 100644 index 50b73a68..00000000 --- a/src/pt/animestc/build.gradle +++ /dev/null @@ -1,11 +0,0 @@ -ext { - extName = 'AnimesTC' - extClass = '.AnimesTC' - extVersionCode = 7 -} - -apply from: "$rootDir/common.gradle" - -dependencies { - implementation(project(":lib:googledrive-extractor")) -} diff --git a/src/pt/animestc/res/mipmap-hdpi/ic_launcher.png b/src/pt/animestc/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 6d456791..00000000 Binary files a/src/pt/animestc/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/animestc/res/mipmap-mdpi/ic_launcher.png b/src/pt/animestc/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 384d412d..00000000 Binary files a/src/pt/animestc/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/animestc/res/mipmap-xhdpi/ic_launcher.png b/src/pt/animestc/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 5129c6e5..00000000 Binary files a/src/pt/animestc/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/animestc/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/animestc/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index bfbb5520..00000000 Binary files a/src/pt/animestc/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/animestc/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/animestc/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index f5229e6a..00000000 Binary files a/src/pt/animestc/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/pt/animestc/src/eu/kanade/tachiyomi/animeextension/pt/animestc/ATCFilters.kt b/src/pt/animestc/src/eu/kanade/tachiyomi/animeextension/pt/animestc/ATCFilters.kt deleted file mode 100644 index 2f830ed1..00000000 --- a/src/pt/animestc/src/eu/kanade/tachiyomi/animeextension/pt/animestc/ATCFilters.kt +++ /dev/null @@ -1,174 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.pt.animestc - -import eu.kanade.tachiyomi.animesource.model.AnimeFilter -import eu.kanade.tachiyomi.animesource.model.AnimeFilterList - -object ATCFilters { - open class QueryPartFilter( - displayName: String, - val vals: Array>, - ) : AnimeFilter.Select( - displayName, - vals.map { it.first }.toTypedArray(), - ) { - fun toQueryPart() = vals[state].second - } - - private inline fun AnimeFilterList.asQueryPart(): String { - return (first { it is R } as QueryPartFilter).toQueryPart() - } - - class TypeFilter : QueryPartFilter("Tipo", ATCFiltersData.TYPES) - class YearFilter : QueryPartFilter("Ano", ATCFiltersData.YEARS) - class GenreFilter : QueryPartFilter("Gênero", ATCFiltersData.GENRES) - class StatusFilter : QueryPartFilter("Status", ATCFiltersData.STATUS) - - val FILTER_LIST get() = AnimeFilterList( - TypeFilter(), - YearFilter(), - GenreFilter(), - StatusFilter(), - ) - - data class FilterSearchParams( - val type: String = "series", - val year: String = "", - val genre: String = "", - val status: String = "", - ) - - internal fun getSearchParameters(filters: AnimeFilterList): FilterSearchParams { - if (filters.isEmpty()) return FilterSearchParams() - - return FilterSearchParams( - filters.asQueryPart(), - filters.asQueryPart(), - filters.asQueryPart(), - filters.asQueryPart(), - ) - } - - private object ATCFiltersData { - val TYPES = arrayOf( - Pair("Anime", "series"), - Pair("Filme", "movie"), - Pair("OVA", "ova"), - ) - - val SELECT = Pair("Selecione", "") - - val STATUS = arrayOf( - SELECT, - Pair("Cancelado", "canceled"), - Pair("Completo", "complete"), - Pair("Em Lançamento", "airing"), - Pair("Pausado", "onhold"), - ) - - val YEARS = arrayOf(SELECT) + (1997..2024).map { - Pair(it.toString(), it.toString()) - }.toTypedArray() - - val GENRES = arrayOf( - SELECT, - Pair("Ação", "acao"), - Pair("Action", "action"), - Pair("Adventure", "adventure"), - Pair("Artes Marciais", "artes-marciais"), - Pair("Artes Marcial", "artes-marcial"), - Pair("Aventura", "aventura"), - Pair("Beisebol", "beisebol"), - Pair("Boys Love", "boys-love"), - Pair("Comédia", "comedia"), - Pair("Comédia Romântica", "comedia-romantica"), - Pair("Comedy", "comedy"), - Pair("Crianças", "criancas"), - Pair("Culinária", "culinaria"), - Pair("Cyberpunk", "cyberpunk"), - Pair("Demônios", "demonios"), - Pair("Distopia", "distopia"), - Pair("Documentário", "documentario"), - Pair("Drama", "drama"), - Pair("Ecchi", "ecchi"), - Pair("Escola", "escola"), - Pair("Escolar", "escolar"), - Pair("Espaço", "espaco"), - Pair("Esporte", "esporte"), - Pair("Esportes", "esportes"), - Pair("Fantasia", "fantasia"), - Pair("Ficção Científica", "ficcao-cientifica"), - Pair("Futebol", "futebol"), - Pair("Game", "game"), - Pair("Girl battleships", "girl-battleships"), - Pair("Gourmet", "gourmet"), - Pair("Gundam", "gundam"), - Pair("Harém", "harem"), - Pair("Hentai", "hentai"), - Pair("Historia", "historia"), - Pair("Historial", "historial"), - Pair("Historical", "historical"), - Pair("Histórico", "historico"), - Pair("Horror", "horror"), - Pair("Humor Negro", "humor-negro"), - Pair("Ídolo", "idolo"), - Pair("Infantis", "infantis"), - Pair("Investigação", "investigacao"), - Pair("Isekai", "isekai"), - Pair("Jogo", "jogo"), - Pair("Jogos", "jogos"), - Pair("Josei", "josei"), - Pair("Kids", "kids"), - Pair("Luta", "luta"), - Pair("Maduro", "maduro"), - Pair("Máfia", "mafia"), - Pair("Magia", "magia"), - Pair("Mágica", "magica"), - Pair("Mecha", "mecha"), - Pair("Militar", "militar"), - Pair("Militares", "militares"), - Pair("Mistério", "misterio"), - Pair("Música", "musica"), - Pair("Musical", "musical"), - Pair("Não Informado!", "nao-informado"), - Pair("Paródia", "parodia"), - Pair("Piratas", "piratas"), - Pair("Polícia", "policia"), - Pair("Policial", "policial"), - Pair("Político", "politico"), - Pair("Pós-Apocalíptico", "pos-apocaliptico"), - Pair("Psico", "psico"), - Pair("Psicológico", "psicologico"), - Pair("Romance", "romance"), - Pair("Samurai", "samurai"), - Pair("Samurais", "samurais"), - Pair("Sátiro", "satiro"), - Pair("School Life", "school-life"), - Pair("SciFi", "scifi"), - Pair("Sci-Fi", "sci-fi"), - Pair("Seinen", "seinen"), - Pair("Shotacon", "shotacon"), - Pair("Shoujo", "shoujo"), - Pair("Shoujo Ai", "shoujo-ai"), - Pair("Shounem", "shounem"), - Pair("Shounen", "shounen"), - Pair("Shounen-ai", "shounen-ai"), - Pair("Slice of Life", "slice-of-life"), - Pair("Sobrenatural", "sobrenatural"), - Pair("Space", "space"), - Pair("Supernatural", "supernatural"), - Pair("Super Poder", "super-poder"), - Pair("Super-Poderes", "super-poderes"), - Pair("Suspense", "suspense"), - Pair("tear-studio", "tear-studio"), - Pair("Terror", "terror"), - Pair("Thriller", "thriller"), - Pair("Tragédia", "tragedia"), - Pair("Vampiro", "vampiro"), - Pair("Vampiros", "vampiros"), - Pair("Vida Escolar", "vida-escolar"), - Pair("Yaoi", "yaoi"), - Pair("Yuri", "yuri"), - Pair("Zombie", "zombie"), - ) - } -} diff --git a/src/pt/animestc/src/eu/kanade/tachiyomi/animeextension/pt/animestc/AnimesTC.kt b/src/pt/animestc/src/eu/kanade/tachiyomi/animeextension/pt/animestc/AnimesTC.kt deleted file mode 100644 index 1f0330d7..00000000 --- a/src/pt/animestc/src/eu/kanade/tachiyomi/animeextension/pt/animestc/AnimesTC.kt +++ /dev/null @@ -1,294 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.pt.animestc - -import android.app.Application -import androidx.preference.ListPreference -import androidx.preference.PreferenceScreen -import eu.kanade.tachiyomi.animeextension.pt.animestc.dto.AnimeDto -import eu.kanade.tachiyomi.animeextension.pt.animestc.dto.EpisodeDto -import eu.kanade.tachiyomi.animeextension.pt.animestc.dto.ResponseDto -import eu.kanade.tachiyomi.animeextension.pt.animestc.dto.VideoDto -import eu.kanade.tachiyomi.animeextension.pt.animestc.extractors.LinkBypasser -import eu.kanade.tachiyomi.animeextension.pt.animestc.extractors.SendcmExtractor -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.AnimeHttpSource -import eu.kanade.tachiyomi.lib.googledriveextractor.GoogleDriveExtractor -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.awaitSuccess -import eu.kanade.tachiyomi.util.asJsoup -import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking -import eu.kanade.tachiyomi.util.parseAs -import kotlinx.serialization.json.Json -import okhttp3.HttpUrl.Companion.toHttpUrl -import okhttp3.Request -import okhttp3.Response -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get -import uy.kohesive.injekt.injectLazy -import java.text.SimpleDateFormat -import java.util.Locale - -class AnimesTC : ConfigurableAnimeSource, AnimeHttpSource() { - - override val name = "AnimesTC" - - override val baseUrl = "https://api2.animestc.com" - - override val lang = "pt-BR" - - override val supportsLatest = true - - override fun headersBuilder() = super.headersBuilder() - .add("Referer", "$HOST_URL/") - - private val preferences by lazy { - Injekt.get().getSharedPreferences("source_$id", 0x0000) - } - - private val json: Json by injectLazy() - - // ============================== Popular =============================== - override fun popularAnimeRequest(page: Int) = GET("$baseUrl/series?order=id&direction=asc&page=1&top=true", headers) - - override fun popularAnimeParse(response: Response): AnimesPage { - val data = response.parseAs>() - val animes = data.map(::searchAnimeFromObject) - return AnimesPage(animes, false) - } - - // =============================== Latest =============================== - override fun latestUpdatesRequest(page: Int) = GET(HOST_URL, headers) - - override fun latestUpdatesParse(response: Response): AnimesPage { - val doc = response.asJsoup() - val animes = doc.select("div > article.episode").map { - SAnime.create().apply { - val ahref = it.selectFirst("h3 > a.episode-info-title-orange")!! - title = ahref.text() - val slug = ahref.attr("href").substringAfterLast("/") - setUrlWithoutDomain("/series?slug=$slug") - thumbnail_url = it.selectFirst("img.episode-image")?.attr("abs:data-src") - } - } - .filter { it.thumbnail_url?.contains("/_nuxt/img/") == false } - .distinctBy { it.url } - - return AnimesPage(animes, false) - } - - // =============================== Search =============================== - override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { - val params = ATCFilters.getSearchParameters(filters) - val url = "$baseUrl/series?order=title&direction=asc&page=$page".toHttpUrl() - .newBuilder() - .addQueryParameter("type", params.type) - .addQueryParameter("search", query) - .addQueryParameter("year", params.year) - .addQueryParameter("releaseStatus", params.status) - .addQueryParameter("tag", params.genre) - .build() - - return GET(url, headers) - } - - override fun searchAnimeParse(response: Response): AnimesPage { - val data = response.parseAs>() - val animes = data.items.map(::searchAnimeFromObject) - val hasNextPage = data.lastPage > data.page - return AnimesPage(animes, hasNextPage) - } - - override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage { - return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler - val slug = query.removePrefix(PREFIX_SEARCH) - client.newCall(GET("$baseUrl/series?slug=$slug")) - .awaitSuccess() - .use(::searchAnimeBySlugParse) - } else { - return super.getSearchAnime(page, query, filters) - } - } - - override fun getFilterList(): AnimeFilterList = ATCFilters.FILTER_LIST - - private fun searchAnimeFromObject(anime: AnimeDto) = SAnime.create().apply { - thumbnail_url = anime.cover.url - title = anime.title - setUrlWithoutDomain("/series/${anime.id}") - } - - private fun searchAnimeBySlugParse(response: Response): AnimesPage { - val details = animeDetailsParse(response).apply { - setUrlWithoutDomain(response.request.url.toString()) - initialized = true - } - - return AnimesPage(listOf(details), false) - } - - // =========================== Anime Details ============================ - override fun animeDetailsParse(response: Response) = SAnime.create().apply { - val anime = response.getAnimeDto() - setUrlWithoutDomain("/series/${anime.id}") - title = anime.title - status = anime.status - thumbnail_url = anime.cover.url - artist = anime.producer - genre = anime.genres - description = buildString { - append(anime.synopsis + "\n") - - anime.classification?.also { append("\nClassificação: ", it, " anos") } - anime.year?.also { append("\nAno de lançamento: ", it) } - } - } - - // ============================== Episodes ============================== - override fun episodeListParse(response: Response): List { - val id = response.getAnimeDto().id - return getEpisodeList(id) - } - - private fun episodeListRequest(animeId: Int, page: Int) = - GET("$baseUrl/episodes?order=id&direction=desc&page=$page&seriesId=$animeId&specialOrder=true") - - private fun getEpisodeList(animeId: Int, page: Int = 1): List { - val response = client.newCall(episodeListRequest(animeId, page)).execute() - val parsed = response.parseAs>() - val episodes = parsed.items.map(::episodeFromObject) - - if (parsed.page < parsed.lastPage) { - return episodes + getEpisodeList(animeId, page + 1) - } else { - return episodes - } - } - - private fun episodeFromObject(episode: EpisodeDto) = SEpisode.create().apply { - name = episode.title - setUrlWithoutDomain("/episodes?slug=${episode.slug}") - episode_number = episode.number.toFloat() - date_upload = episode.created_at.toDate() - } - - // ============================ Video Links ============================= - private val sendcmExtractor by lazy { SendcmExtractor(client) } - private val gdriveExtractor by lazy { GoogleDriveExtractor(client, headers) } - private val linkBypasser by lazy { LinkBypasser(client, json) } - - private val supportedPlayers = listOf("send", "drive") - - override fun videoListParse(response: Response): List