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