diff --git a/src/pt/animesotaku/AndroidManifest.xml b/src/pt/animesotaku/AndroidManifest.xml
deleted file mode 100644
index 344af03c..00000000
--- a/src/pt/animesotaku/AndroidManifest.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/pt/animesotaku/build.gradle b/src/pt/animesotaku/build.gradle
deleted file mode 100644
index 4031a00f..00000000
--- a/src/pt/animesotaku/build.gradle
+++ /dev/null
@@ -1,11 +0,0 @@
-ext {
- extName = 'AnimesOtaku'
- extClass = '.AnimesOtaku'
- extVersionCode = 1
-}
-
-apply from: "$rootDir/common.gradle"
-
-dependencies {
- implementation(project(":lib:blogger-extractor"))
-}
diff --git a/src/pt/animesotaku/res/mipmap-hdpi/ic_launcher.png b/src/pt/animesotaku/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index 13f236fb..00000000
Binary files a/src/pt/animesotaku/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/animesotaku/res/mipmap-mdpi/ic_launcher.png b/src/pt/animesotaku/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 7ba8b02c..00000000
Binary files a/src/pt/animesotaku/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/animesotaku/res/mipmap-xhdpi/ic_launcher.png b/src/pt/animesotaku/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index 71bed724..00000000
Binary files a/src/pt/animesotaku/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/animesotaku/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/animesotaku/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index acadcc41..00000000
Binary files a/src/pt/animesotaku/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/animesotaku/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/animesotaku/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index ef8f94e8..00000000
Binary files a/src/pt/animesotaku/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/animesotaku/src/eu/kanade/tachiyomi/animeextension/pt/animesotaku/AnimesOtaku.kt b/src/pt/animesotaku/src/eu/kanade/tachiyomi/animeextension/pt/animesotaku/AnimesOtaku.kt
deleted file mode 100644
index 91c07458..00000000
--- a/src/pt/animesotaku/src/eu/kanade/tachiyomi/animeextension/pt/animesotaku/AnimesOtaku.kt
+++ /dev/null
@@ -1,244 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.animesotaku
-
-import android.util.Base64
-import eu.kanade.tachiyomi.animeextension.pt.animesotaku.dto.SearchRequestDto
-import eu.kanade.tachiyomi.animeextension.pt.animesotaku.dto.SearchResponseDto
-import eu.kanade.tachiyomi.animeextension.pt.animesotaku.dto.SingleDto
-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.bloggerextractor.BloggerExtractor
-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.parallelCatchingFlatMapBlocking
-import eu.kanade.tachiyomi.util.parseAs
-import kotlinx.serialization.encodeToString
-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.injectLazy
-import java.util.concurrent.TimeUnit
-
-class AnimesOtaku : AnimeHttpSource() {
-
- override val name = "Animes Otaku"
-
- override val baseUrl = "https://www.animesotaku.cc"
-
- override val lang = "pt"
-
- override val supportsLatest = true
-
- private val json: Json by injectLazy()
-
- override val client = network.client.newBuilder()
- .connectTimeout(30, TimeUnit.SECONDS)
- .writeTimeout(30, TimeUnit.SECONDS)
- .readTimeout(30, TimeUnit.SECONDS)
- .build()
-
- override fun headersBuilder() = super.headersBuilder()
- .add("Referer", baseUrl)
-
- // ============================== Popular ===============================
- override fun popularAnimeRequest(page: Int) = searchOrderBy("total_kiranime_views", page)
-
- override fun popularAnimeParse(response: Response): AnimesPage {
- val results = response.parseAs()
- val doc = Jsoup.parseBodyFragment(results.data)
- val animes = doc.select("div.w-full:has(div.kira-anime)").map {
- SAnime.create().apply {
- thumbnail_url = it.selectFirst("img")?.attr("src")
- with(it.selectFirst("h3 > a")!!) {
- title = text().replace(" Assistir Online", "")
- setUrlWithoutDomain(attr("href"))
- }
- }
- }
-
- val page = response.request.url.queryParameter("page")?.toIntOrNull() ?: 1
- val hasNextPage = page < results.pages
- return AnimesPage(animes, hasNextPage)
- }
-
- // =============================== Latest ===============================
- override fun latestUpdatesRequest(page: Int) = searchOrderBy("kiranime_anime_updated", page)
-
- override fun latestUpdatesParse(response: Response) = popularAnimeParse(response)
-
- // =============================== Search ===============================
- override suspend fun getSearchAnime(
- page: Int,
- query: String,
- filters: AnimeFilterList,
- ): AnimesPage {
- return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
- val id = query.removePrefix(PREFIX_SEARCH)
- client.newCall(GET("$baseUrl/anime/$id"))
- .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 getFilterList() = AnimesOtakuFilters.FILTER_LIST
-
- override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
- val params = AnimesOtakuFilters.getSearchParameters(filters)
- val (meta, orderBy) = when (params.orderBy) {
- "date", "title" -> Pair(null, params.orderBy)
- else -> Pair(params.orderBy, "meta_value_num")
- }
-
- val single = SingleDto(
- paged = page,
- key = meta,
- order = params.order,
- orderBy = orderBy,
- season = params.season.ifEmpty { null },
- year = params.year.ifEmpty { null },
- )
-
- val taxonomies = with(params) {
- listOf(genres, status, producers, studios, types).filter {
- it.terms.isNotEmpty()
- }
- }
-
- val requestDto = SearchRequestDto(single, query, query, taxonomies)
- val requestData = json.encodeToString(requestDto)
- return searchRequest(requestData, page)
- }
-
- override fun searchAnimeParse(response: Response) = popularAnimeParse(response)
-
- private fun searchOrderBy(order: String, page: Int): Request {
- val body = """
- {
- "keyword": "",
- "query": "",
- "single": {
- "paged": $page,
- "orderby": "meta_value_num",
- "meta_key": "$order",
- "order": "desc"
- },
- "tax": []
- }
- """.trimIndent()
- return searchRequest(body, page)
- }
-
- private fun searchRequest(data: String, page: Int): Request {
- val body = data.toRequestBody("application/json".toMediaType())
- return POST(
- "$baseUrl/wp-json/kiranime/v1/anime/advancedsearch?_locale=user&page=$page",
- headers,
- body,
- )
- }
-
- // =========================== Anime Details ============================
- override fun animeDetailsParse(response: Response) = SAnime.create().apply {
- val document = response.asJsoup()
-
- setUrlWithoutDomain(document.location())
- thumbnail_url = document.selectFirst("div.anime-image img")?.attr("src")
- title =
- document.selectFirst("h1 span.show.anime")!!.text().replace(" Assistir Online", "")
- genre =
- document.select("span.leading-6 a[class~=border-opacity-30]").joinToString { it.text() }
- description = document.selectFirst("div[data-synopsis]")?.text()
- author = document.selectFirst("span.leading-6 a[href*=\"producer\"]:first-child")?.text()
- artist = document.selectFirst("span.leading-6 a[href*=\"studio\"]:first-child")?.text()
- }
-
- // ============================== Episodes ==============================
- override fun episodeListParse(response: Response): List {
- return getRealDoc(response.asJsoup())
- .select(episodeListSelector())
- .map(::episodeFromElement)
- }
-
- fun episodeListSelector(): String = "div[data-current-slider=\"episode-list\"] a"
-
- fun episodeFromElement(element: Element) = SEpisode.create().apply {
- setUrlWithoutDomain(element.attr("href"))
- name = element.selectFirst("span.font-semibold")!!.text().trim()
- episode_number = name.substringAfterLast(" ").toFloatOrNull() ?: 0F
- }
-
- // ============================ Video Links =============================
- private val bloggerExtractor by lazy { BloggerExtractor(client) }
-
- override fun videoListParse(response: Response): List