diff --git a/.github/workflows/build_push.yml b/.github/workflows/build_push.yml
index 346eb44e..43101393 100644
--- a/.github/workflows/build_push.yml
+++ b/.github/workflows/build_push.yml
@@ -31,14 +31,15 @@ jobs:
           ref: main
           token: ${{ secrets.BOT_PAT }}
 
-      - name: Find lib changes
-        id: modified-libs
-        uses: tj-actions/changed-files@90a06d6ba9543371ab4df8eeca0be07ca6054959 #v42
-        with:
-          files: lib/
-          files_ignore: lib/**.md
-          files_separator: " "
-          safe_output: false
+      # Temporary pause because of leak of tj-actions/changed-files
+      # - name: Find lib changes
+      #   id: modified-libs
+      #   uses: tj-actions/changed-files@90a06d6ba9543371ab4df8eeca0be07ca6054959 #v42
+      #   with:
+      #     files: lib/
+      #     files_ignore: lib/**.md
+      #     files_separator: " "
+      #     safe_output: false
 
       - name: Import GPG key
         uses: crazy-max/ghaction-import-gpg@v6  # v6.1.0
@@ -48,12 +49,12 @@ jobs:
           git_user_signingkey: true
           git_commit_gpgsign: true
 
-        # This step is going to commit, but this will not trigger another workflow.
-      - name: Bump extensions that uses a modified lib
-        if: steps.modified-libs.outputs.any_changed == 'true'
-        run: |
-          chmod +x ./.github/scripts/bump-versions.py
-          ./.github/scripts/bump-versions.py ${{ steps.modified-libs.outputs.all_changed_files }}
+      #   # This step is going to commit, but this will not trigger another workflow.
+      # - name: Bump extensions that uses a modified lib
+      #   if: steps.modified-libs.outputs.any_changed == 'true'
+      #   run: |
+      #     chmod +x ./.github/scripts/bump-versions.py
+      #     ./.github/scripts/bump-versions.py ${{ steps.modified-libs.outputs.all_changed_files }}
 
       - name: Validate Gradle Wrapper
         uses: gradle/wrapper-validation-action@a494d935f4b56874c4a5a87d19af7afcf3a163d0 # v2
diff --git a/lib/amazon-extractor/build.gradle.kts b/lib/amazon-extractor/build.gradle.kts
new file mode 100644
index 00000000..a503203d
--- /dev/null
+++ b/lib/amazon-extractor/build.gradle.kts
@@ -0,0 +1,7 @@
+plugins {
+    id("lib-android")
+}
+
+dependencies {
+    implementation(project(":lib:playlist-utils"))
+}
\ No newline at end of file
diff --git a/lib/amazon-extractor/src/main/java/eu/kanade/tachiyomi/lib/amazonextractor/AmazonExtractor.kt b/lib/amazon-extractor/src/main/java/eu/kanade/tachiyomi/lib/amazonextractor/AmazonExtractor.kt
new file mode 100644
index 00000000..3402cb9e
--- /dev/null
+++ b/lib/amazon-extractor/src/main/java/eu/kanade/tachiyomi/lib/amazonextractor/AmazonExtractor.kt
@@ -0,0 +1,41 @@
+package eu.kanade.tachiyomi.lib.amazonextractor
+
+import eu.kanade.tachiyomi.animesource.model.Video
+import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.util.asJsoup
+import okhttp3.OkHttpClient
+
+class AmazonExtractor(private val client: OkHttpClient) {
+
+    private val playlistUtils by lazy { PlaylistUtils(client) }
+
+    fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
+        if (url.contains("disable", true)) return emptyList()
+
+        val document = client.newCall(GET(url)).execute().asJsoup()
+
+        val shareIdScript = document.select("script:containsData(var shareId)").firstOrNull()?.data()
+        if (shareIdScript.isNullOrBlank()) return emptyList()
+
+        val shareId = shareIdScript.substringAfter("shareId = \"").substringBefore("\"")
+        val amazonApiJsonUrl = "https://www.amazon.com/drive/v1/shares/$shareId?resourceVersion=V2&ContentType=JSON&asset=ALL"
+
+        val amazonApiJson = client.newCall(GET(amazonApiJsonUrl)).execute().asJsoup()
+
+        val epId = amazonApiJson.toString().substringAfter("\"id\":\"").substringBefore("\"")
+        val amazonApiUrl = "https://www.amazon.com/drive/v1/nodes/$epId/children?resourceVersion=V2&ContentType=JSON&limit=200&sort=%5B%22kind+DESC%22%2C+%22modifiedDate+DESC%22%5D&asset=ALL&tempLink=true&shareId=$shareId"
+
+        val amazonApi = client.newCall(GET(amazonApiUrl)).execute().asJsoup()
+
+        val videoUrl = amazonApi.toString().substringAfter("\"FOLDER\":").substringAfter("tempLink\":\"").substringBefore("\"")
+
+        val serverName = if (videoUrl.contains("&ext=es")) "AmazonES" else "Amazon"
+
+        return if (videoUrl.contains(".m3u8")) {
+            playlistUtils.extractFromHls(videoUrl, videoNameGen = { "${prefix}$serverName:$it" })
+        } else {
+            listOf(Video(videoUrl, "${prefix}$serverName", videoUrl))
+        }
+    }
+}
diff --git a/src/all/animeonsen/res/web_hi_res_512.png b/src/all/animeonsen/res/web_hi_res_512.png
deleted file mode 100644
index 2ca8cc98..00000000
Binary files a/src/all/animeonsen/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/all/animeworldindia/build.gradle b/src/all/animeworldindia/build.gradle
index 2e6be89d..0c887191 100644
--- a/src/all/animeworldindia/build.gradle
+++ b/src/all/animeworldindia/build.gradle
@@ -1,11 +1,11 @@
 ext {
     extName = 'AnimeWorld India'
     extClass = '.AnimeWorldIndiaFactory'
-    extVersionCode = 14
+    extVersionCode = 15
 }
 
 apply from: "$rootDir/common.gradle"
 
 dependencies {
     implementation(project(":lib:playlist-utils"))
-}
\ No newline at end of file
+}
diff --git a/src/all/animeworldindia/src/eu/kanade/tachiyomi/animeextension/all/animeworldindia/AnimeWorldIndia.kt b/src/all/animeworldindia/src/eu/kanade/tachiyomi/animeextension/all/animeworldindia/AnimeWorldIndia.kt
index 4ab6cd81..5fbe3c37 100644
--- a/src/all/animeworldindia/src/eu/kanade/tachiyomi/animeextension/all/animeworldindia/AnimeWorldIndia.kt
+++ b/src/all/animeworldindia/src/eu/kanade/tachiyomi/animeextension/all/animeworldindia/AnimeWorldIndia.kt
@@ -29,7 +29,7 @@ class AnimeWorldIndia(
 
     override val name = "AnimeWorld India"
 
-    override val baseUrl = "https://anime-world.in"
+    override val baseUrl = "https://anime-world.co"
 
     override val supportsLatest = true
 
diff --git a/src/all/animeworldindia/src/eu/kanade/tachiyomi/animeextension/all/animeworldindia/AnimeWorldIndiaFilters.kt b/src/all/animeworldindia/src/eu/kanade/tachiyomi/animeextension/all/animeworldindia/AnimeWorldIndiaFilters.kt
index 5baf4062..a55518bd 100644
--- a/src/all/animeworldindia/src/eu/kanade/tachiyomi/animeextension/all/animeworldindia/AnimeWorldIndiaFilters.kt
+++ b/src/all/animeworldindia/src/eu/kanade/tachiyomi/animeextension/all/animeworldindia/AnimeWorldIndiaFilters.kt
@@ -47,6 +47,7 @@ class AnimeWorldIndiaFilters {
 
     private fun getYearList() = listOf(
         StringQuery("Any", "all"),
+        StringQuery("2025", "2025"),
         StringQuery("2024", "2024"),
         StringQuery("2023", "2023"),
         StringQuery("2022", "2022"),
diff --git a/src/all/chineseanime/res/web_hi_res_512.png b/src/all/chineseanime/res/web_hi_res_512.png
deleted file mode 100644
index d8572ff1..00000000
Binary files a/src/all/chineseanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/all/javguru/res/web_hi_res_512.png b/src/all/javguru/res/web_hi_res_512.png
deleted file mode 100644
index 1e1e735b..00000000
Binary files a/src/all/javguru/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/all/missav/res/web_hi_res_512.png b/src/all/missav/res/web_hi_res_512.png
deleted file mode 100644
index 2b9568fd..00000000
Binary files a/src/all/missav/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ar/akwam/res/play_store_512.png b/src/ar/akwam/res/play_store_512.png
deleted file mode 100644
index 17a4ebb9..00000000
Binary files a/src/ar/akwam/res/play_store_512.png and /dev/null differ
diff --git a/src/ar/anime4up/res/play_store_512.png b/src/ar/anime4up/res/play_store_512.png
deleted file mode 100644
index 9bfe8e48..00000000
Binary files a/src/ar/anime4up/res/play_store_512.png and /dev/null differ
diff --git a/src/ar/animeblkom/res/web_hi_res_512.png b/src/ar/animeblkom/res/web_hi_res_512.png
deleted file mode 100644
index b47c05e9..00000000
Binary files a/src/ar/animeblkom/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ar/animeiat/res/web_hi_res_512.png b/src/ar/animeiat/res/web_hi_res_512.png
deleted file mode 100644
index 06a6eece..00000000
Binary files a/src/ar/animeiat/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ar/animelek/res/play_store_512.png b/src/ar/animelek/res/play_store_512.png
deleted file mode 100644
index 13283b86..00000000
Binary files a/src/ar/animelek/res/play_store_512.png and /dev/null differ
diff --git a/src/ar/animerco/res/play_store_512.png b/src/ar/animerco/res/play_store_512.png
deleted file mode 100644
index fbf8380e..00000000
Binary files a/src/ar/animerco/res/play_store_512.png and /dev/null differ
diff --git a/src/ar/arabanime/res/web_hi_res_512.png b/src/ar/arabanime/res/web_hi_res_512.png
deleted file mode 100644
index 684ce74b..00000000
Binary files a/src/ar/arabanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ar/arabseed/res/web_hi_res_512.png b/src/ar/arabseed/res/web_hi_res_512.png
deleted file mode 100644
index 42b8ffbf..00000000
Binary files a/src/ar/arabseed/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ar/asia2tv/res/play_store_512.png b/src/ar/asia2tv/res/play_store_512.png
deleted file mode 100644
index 644679a6..00000000
Binary files a/src/ar/asia2tv/res/play_store_512.png and /dev/null differ
diff --git a/src/ar/egydead/res/web_hi_res_512.png b/src/ar/egydead/res/web_hi_res_512.png
deleted file mode 100644
index bcff8301..00000000
Binary files a/src/ar/egydead/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ar/faselhd/res/web_hi_res_512.png b/src/ar/faselhd/res/web_hi_res_512.png
deleted file mode 100644
index bbe17f6d..00000000
Binary files a/src/ar/faselhd/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ar/mycima/res/web_hi_res_512.png b/src/ar/mycima/res/web_hi_res_512.png
deleted file mode 100644
index b3d75682..00000000
Binary files a/src/ar/mycima/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ar/tuktukcinema/res/web_hi_res_512.png b/src/ar/tuktukcinema/res/web_hi_res_512.png
deleted file mode 100644
index 55c57feb..00000000
Binary files a/src/ar/tuktukcinema/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ar/witanime/res/web_hi_res_512.png b/src/ar/witanime/res/web_hi_res_512.png
deleted file mode 100644
index e9de882c..00000000
Binary files a/src/ar/witanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ar/xsanime/res/web_hi_res_512.png b/src/ar/xsanime/res/web_hi_res_512.png
deleted file mode 100644
index b7ecb5f2..00000000
Binary files a/src/ar/xsanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ar/xsmovie/res/web_hi_res_512.png b/src/ar/xsmovie/res/web_hi_res_512.png
deleted file mode 100644
index 4ac97393..00000000
Binary files a/src/ar/xsmovie/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/de/animeloads/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/src/de/animeloads/res/mipmap-hdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 8dc560dd..00000000
Binary files a/src/de/animeloads/res/mipmap-hdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/animeloads/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/src/de/animeloads/res/mipmap-hdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 03d51624..00000000
Binary files a/src/de/animeloads/res/mipmap-hdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/animeloads/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/src/de/animeloads/res/mipmap-mdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index f8feb6e5..00000000
Binary files a/src/de/animeloads/res/mipmap-mdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/animeloads/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/src/de/animeloads/res/mipmap-mdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 3eaed0fb..00000000
Binary files a/src/de/animeloads/res/mipmap-mdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/animeloads/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/src/de/animeloads/res/mipmap-xhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 1b560124..00000000
Binary files a/src/de/animeloads/res/mipmap-xhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/animeloads/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/src/de/animeloads/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index da274ed6..00000000
Binary files a/src/de/animeloads/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/animeloads/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/src/de/animeloads/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 369383ac..00000000
Binary files a/src/de/animeloads/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/animeloads/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/src/de/animeloads/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index ec6a2ff3..00000000
Binary files a/src/de/animeloads/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/animeloads/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/src/de/animeloads/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index de26e98f..00000000
Binary files a/src/de/animeloads/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/animeloads/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/src/de/animeloads/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 050b46e2..00000000
Binary files a/src/de/animeloads/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/aniworld/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/src/de/aniworld/res/mipmap-hdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 8dc560dd..00000000
Binary files a/src/de/aniworld/res/mipmap-hdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/aniworld/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/src/de/aniworld/res/mipmap-hdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 9ec03535..00000000
Binary files a/src/de/aniworld/res/mipmap-hdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/aniworld/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/src/de/aniworld/res/mipmap-mdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index f8feb6e5..00000000
Binary files a/src/de/aniworld/res/mipmap-mdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/aniworld/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/src/de/aniworld/res/mipmap-mdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 86df8abd..00000000
Binary files a/src/de/aniworld/res/mipmap-mdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/aniworld/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/src/de/aniworld/res/mipmap-xhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 1b560124..00000000
Binary files a/src/de/aniworld/res/mipmap-xhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/aniworld/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/src/de/aniworld/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 3cb79f27..00000000
Binary files a/src/de/aniworld/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/aniworld/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/src/de/aniworld/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 369383ac..00000000
Binary files a/src/de/aniworld/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/aniworld/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/src/de/aniworld/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 366f1f42..00000000
Binary files a/src/de/aniworld/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/aniworld/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/src/de/aniworld/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index de26e98f..00000000
Binary files a/src/de/aniworld/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/aniworld/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/src/de/aniworld/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index aaad5a4c..00000000
Binary files a/src/de/aniworld/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-hdpi/ic_launcher_background.png b/src/de/cineclix/res/mipmap-hdpi/ic_launcher_background.png
deleted file mode 100644
index 2d07511b..00000000
Binary files a/src/de/cineclix/res/mipmap-hdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-hdpi/ic_launcher_foreground.png b/src/de/cineclix/res/mipmap-hdpi/ic_launcher_foreground.png
deleted file mode 100644
index bde37154..00000000
Binary files a/src/de/cineclix/res/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-hdpi/ic_launcher_monochrome.png b/src/de/cineclix/res/mipmap-hdpi/ic_launcher_monochrome.png
deleted file mode 100644
index bde37154..00000000
Binary files a/src/de/cineclix/res/mipmap-hdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-mdpi/ic_launcher_background.png b/src/de/cineclix/res/mipmap-mdpi/ic_launcher_background.png
deleted file mode 100644
index 09b41700..00000000
Binary files a/src/de/cineclix/res/mipmap-mdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-mdpi/ic_launcher_foreground.png b/src/de/cineclix/res/mipmap-mdpi/ic_launcher_foreground.png
deleted file mode 100644
index 017b0039..00000000
Binary files a/src/de/cineclix/res/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-mdpi/ic_launcher_monochrome.png b/src/de/cineclix/res/mipmap-mdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 017b0039..00000000
Binary files a/src/de/cineclix/res/mipmap-mdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-xhdpi/ic_launcher_background.png b/src/de/cineclix/res/mipmap-xhdpi/ic_launcher_background.png
deleted file mode 100644
index ea00baaf..00000000
Binary files a/src/de/cineclix/res/mipmap-xhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-xhdpi/ic_launcher_foreground.png b/src/de/cineclix/res/mipmap-xhdpi/ic_launcher_foreground.png
deleted file mode 100644
index cc83ed87..00000000
Binary files a/src/de/cineclix/res/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-xhdpi/ic_launcher_monochrome.png b/src/de/cineclix/res/mipmap-xhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index cc83ed87..00000000
Binary files a/src/de/cineclix/res/mipmap-xhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-xxhdpi/ic_launcher_background.png b/src/de/cineclix/res/mipmap-xxhdpi/ic_launcher_background.png
deleted file mode 100644
index adcd3c25..00000000
Binary files a/src/de/cineclix/res/mipmap-xxhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-xxhdpi/ic_launcher_foreground.png b/src/de/cineclix/res/mipmap-xxhdpi/ic_launcher_foreground.png
deleted file mode 100644
index bb12091e..00000000
Binary files a/src/de/cineclix/res/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/src/de/cineclix/res/mipmap-xxhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index bb12091e..00000000
Binary files a/src/de/cineclix/res/mipmap-xxhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-xxxhdpi/ic_launcher_background.png b/src/de/cineclix/res/mipmap-xxxhdpi/ic_launcher_background.png
deleted file mode 100644
index 08eb24e0..00000000
Binary files a/src/de/cineclix/res/mipmap-xxxhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/src/de/cineclix/res/mipmap-xxxhdpi/ic_launcher_foreground.png
deleted file mode 100644
index e82ff961..00000000
Binary files a/src/de/cineclix/res/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/cineclix/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/src/de/cineclix/res/mipmap-xxxhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index e82ff961..00000000
Binary files a/src/de/cineclix/res/mipmap-xxxhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/cinemathek/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/src/de/cinemathek/res/mipmap-hdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 8dc560dd..00000000
Binary files a/src/de/cinemathek/res/mipmap-hdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/cinemathek/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/src/de/cinemathek/res/mipmap-hdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index fe053c9f..00000000
Binary files a/src/de/cinemathek/res/mipmap-hdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/cinemathek/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/src/de/cinemathek/res/mipmap-mdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index f8feb6e5..00000000
Binary files a/src/de/cinemathek/res/mipmap-mdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/cinemathek/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/src/de/cinemathek/res/mipmap-mdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index bde9fb29..00000000
Binary files a/src/de/cinemathek/res/mipmap-mdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/cinemathek/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/src/de/cinemathek/res/mipmap-xhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 1b560124..00000000
Binary files a/src/de/cinemathek/res/mipmap-xhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/cinemathek/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/src/de/cinemathek/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index a3747f4b..00000000
Binary files a/src/de/cinemathek/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/cinemathek/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/src/de/cinemathek/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 369383ac..00000000
Binary files a/src/de/cinemathek/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/cinemathek/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/src/de/cinemathek/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index e26743f1..00000000
Binary files a/src/de/cinemathek/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/cinemathek/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/src/de/cinemathek/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index de26e98f..00000000
Binary files a/src/de/cinemathek/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/cinemathek/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/src/de/cinemathek/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 6b899ae7..00000000
Binary files a/src/de/cinemathek/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/filmpalast/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/src/de/filmpalast/res/mipmap-hdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 8dc560dd..00000000
Binary files a/src/de/filmpalast/res/mipmap-hdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/filmpalast/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/src/de/filmpalast/res/mipmap-hdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 4c5d378f..00000000
Binary files a/src/de/filmpalast/res/mipmap-hdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/filmpalast/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/src/de/filmpalast/res/mipmap-mdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index f8feb6e5..00000000
Binary files a/src/de/filmpalast/res/mipmap-mdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/filmpalast/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/src/de/filmpalast/res/mipmap-mdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 095e31f4..00000000
Binary files a/src/de/filmpalast/res/mipmap-mdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/filmpalast/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/src/de/filmpalast/res/mipmap-xhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 1b560124..00000000
Binary files a/src/de/filmpalast/res/mipmap-xhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/filmpalast/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/src/de/filmpalast/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 8787a0af..00000000
Binary files a/src/de/filmpalast/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/filmpalast/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/src/de/filmpalast/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 369383ac..00000000
Binary files a/src/de/filmpalast/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/filmpalast/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/src/de/filmpalast/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 6da85ba0..00000000
Binary files a/src/de/filmpalast/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/filmpalast/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/src/de/filmpalast/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index de26e98f..00000000
Binary files a/src/de/filmpalast/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/filmpalast/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/src/de/filmpalast/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 36f49fd3..00000000
Binary files a/src/de/filmpalast/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/kinoking/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/src/de/kinoking/res/mipmap-hdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 8dc560dd..00000000
Binary files a/src/de/kinoking/res/mipmap-hdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/kinoking/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/src/de/kinoking/res/mipmap-hdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 5acc8ad2..00000000
Binary files a/src/de/kinoking/res/mipmap-hdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/kinoking/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/src/de/kinoking/res/mipmap-mdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index f8feb6e5..00000000
Binary files a/src/de/kinoking/res/mipmap-mdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/kinoking/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/src/de/kinoking/res/mipmap-mdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 32a719b7..00000000
Binary files a/src/de/kinoking/res/mipmap-mdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/kinoking/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/src/de/kinoking/res/mipmap-xhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 1b560124..00000000
Binary files a/src/de/kinoking/res/mipmap-xhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/kinoking/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/src/de/kinoking/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index c303b600..00000000
Binary files a/src/de/kinoking/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/kinoking/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/src/de/kinoking/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 369383ac..00000000
Binary files a/src/de/kinoking/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/kinoking/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/src/de/kinoking/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 53bb9806..00000000
Binary files a/src/de/kinoking/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/kinoking/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/src/de/kinoking/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index de26e98f..00000000
Binary files a/src/de/kinoking/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/kinoking/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/src/de/kinoking/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 8e72d520..00000000
Binary files a/src/de/kinoking/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-hdpi/ic_launcher_background.png b/src/de/kool/res/mipmap-hdpi/ic_launcher_background.png
deleted file mode 100644
index 2d07511b..00000000
Binary files a/src/de/kool/res/mipmap-hdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-hdpi/ic_launcher_foreground.png b/src/de/kool/res/mipmap-hdpi/ic_launcher_foreground.png
deleted file mode 100644
index 259233d7..00000000
Binary files a/src/de/kool/res/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-hdpi/ic_launcher_monochrome.png b/src/de/kool/res/mipmap-hdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 259233d7..00000000
Binary files a/src/de/kool/res/mipmap-hdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-mdpi/ic_launcher_background.png b/src/de/kool/res/mipmap-mdpi/ic_launcher_background.png
deleted file mode 100644
index 09b41700..00000000
Binary files a/src/de/kool/res/mipmap-mdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-mdpi/ic_launcher_foreground.png b/src/de/kool/res/mipmap-mdpi/ic_launcher_foreground.png
deleted file mode 100644
index 360f5be2..00000000
Binary files a/src/de/kool/res/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-mdpi/ic_launcher_monochrome.png b/src/de/kool/res/mipmap-mdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 360f5be2..00000000
Binary files a/src/de/kool/res/mipmap-mdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-xhdpi/ic_launcher_background.png b/src/de/kool/res/mipmap-xhdpi/ic_launcher_background.png
deleted file mode 100644
index ea00baaf..00000000
Binary files a/src/de/kool/res/mipmap-xhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-xhdpi/ic_launcher_foreground.png b/src/de/kool/res/mipmap-xhdpi/ic_launcher_foreground.png
deleted file mode 100644
index de15043d..00000000
Binary files a/src/de/kool/res/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-xhdpi/ic_launcher_monochrome.png b/src/de/kool/res/mipmap-xhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index de15043d..00000000
Binary files a/src/de/kool/res/mipmap-xhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-xxhdpi/ic_launcher_background.png b/src/de/kool/res/mipmap-xxhdpi/ic_launcher_background.png
deleted file mode 100644
index adcd3c25..00000000
Binary files a/src/de/kool/res/mipmap-xxhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-xxhdpi/ic_launcher_foreground.png b/src/de/kool/res/mipmap-xxhdpi/ic_launcher_foreground.png
deleted file mode 100644
index 902dd5b9..00000000
Binary files a/src/de/kool/res/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/src/de/kool/res/mipmap-xxhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 902dd5b9..00000000
Binary files a/src/de/kool/res/mipmap-xxhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-xxxhdpi/ic_launcher_background.png b/src/de/kool/res/mipmap-xxxhdpi/ic_launcher_background.png
deleted file mode 100644
index 08eb24e0..00000000
Binary files a/src/de/kool/res/mipmap-xxxhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/src/de/kool/res/mipmap-xxxhdpi/ic_launcher_foreground.png
deleted file mode 100644
index 7046d799..00000000
Binary files a/src/de/kool/res/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/kool/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/src/de/kool/res/mipmap-xxxhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 7046d799..00000000
Binary files a/src/de/kool/res/mipmap-xxxhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-hdpi/ic_launcher_background.png b/src/de/movie2k/res/mipmap-hdpi/ic_launcher_background.png
deleted file mode 100644
index 2d07511b..00000000
Binary files a/src/de/movie2k/res/mipmap-hdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-hdpi/ic_launcher_foreground.png b/src/de/movie2k/res/mipmap-hdpi/ic_launcher_foreground.png
deleted file mode 100644
index cf49c890..00000000
Binary files a/src/de/movie2k/res/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-hdpi/ic_launcher_monochrome.png b/src/de/movie2k/res/mipmap-hdpi/ic_launcher_monochrome.png
deleted file mode 100644
index cf49c890..00000000
Binary files a/src/de/movie2k/res/mipmap-hdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-mdpi/ic_launcher_background.png b/src/de/movie2k/res/mipmap-mdpi/ic_launcher_background.png
deleted file mode 100644
index 09b41700..00000000
Binary files a/src/de/movie2k/res/mipmap-mdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-mdpi/ic_launcher_foreground.png b/src/de/movie2k/res/mipmap-mdpi/ic_launcher_foreground.png
deleted file mode 100644
index d4276e61..00000000
Binary files a/src/de/movie2k/res/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-mdpi/ic_launcher_monochrome.png b/src/de/movie2k/res/mipmap-mdpi/ic_launcher_monochrome.png
deleted file mode 100644
index d4276e61..00000000
Binary files a/src/de/movie2k/res/mipmap-mdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-xhdpi/ic_launcher_background.png b/src/de/movie2k/res/mipmap-xhdpi/ic_launcher_background.png
deleted file mode 100644
index ea00baaf..00000000
Binary files a/src/de/movie2k/res/mipmap-xhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-xhdpi/ic_launcher_foreground.png b/src/de/movie2k/res/mipmap-xhdpi/ic_launcher_foreground.png
deleted file mode 100644
index 6474e13c..00000000
Binary files a/src/de/movie2k/res/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-xhdpi/ic_launcher_monochrome.png b/src/de/movie2k/res/mipmap-xhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 6474e13c..00000000
Binary files a/src/de/movie2k/res/mipmap-xhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-xxhdpi/ic_launcher_background.png b/src/de/movie2k/res/mipmap-xxhdpi/ic_launcher_background.png
deleted file mode 100644
index adcd3c25..00000000
Binary files a/src/de/movie2k/res/mipmap-xxhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-xxhdpi/ic_launcher_foreground.png b/src/de/movie2k/res/mipmap-xxhdpi/ic_launcher_foreground.png
deleted file mode 100644
index 3777ec91..00000000
Binary files a/src/de/movie2k/res/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/src/de/movie2k/res/mipmap-xxhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 3777ec91..00000000
Binary files a/src/de/movie2k/res/mipmap-xxhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-xxxhdpi/ic_launcher_background.png b/src/de/movie2k/res/mipmap-xxxhdpi/ic_launcher_background.png
deleted file mode 100644
index 08eb24e0..00000000
Binary files a/src/de/movie2k/res/mipmap-xxxhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/src/de/movie2k/res/mipmap-xxxhdpi/ic_launcher_foreground.png
deleted file mode 100644
index bbeb49b6..00000000
Binary files a/src/de/movie2k/res/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/de/movie2k/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/src/de/movie2k/res/mipmap-xxxhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index bbeb49b6..00000000
Binary files a/src/de/movie2k/res/mipmap-xxxhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/de/movie4k/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/src/de/movie4k/res/mipmap-hdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 8dc560dd..00000000
Binary files a/src/de/movie4k/res/mipmap-hdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/movie4k/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/src/de/movie4k/res/mipmap-hdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 55c43ca1..00000000
Binary files a/src/de/movie4k/res/mipmap-hdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/movie4k/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/src/de/movie4k/res/mipmap-mdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index f8feb6e5..00000000
Binary files a/src/de/movie4k/res/mipmap-mdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/movie4k/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/src/de/movie4k/res/mipmap-mdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 44113ef3..00000000
Binary files a/src/de/movie4k/res/mipmap-mdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/movie4k/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/src/de/movie4k/res/mipmap-xhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 1b560124..00000000
Binary files a/src/de/movie4k/res/mipmap-xhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/movie4k/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/src/de/movie4k/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 61101bff..00000000
Binary files a/src/de/movie4k/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/movie4k/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/src/de/movie4k/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 369383ac..00000000
Binary files a/src/de/movie4k/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/movie4k/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/src/de/movie4k/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index ee622825..00000000
Binary files a/src/de/movie4k/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/movie4k/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/src/de/movie4k/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index de26e98f..00000000
Binary files a/src/de/movie4k/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/movie4k/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/src/de/movie4k/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 3e20bba5..00000000
Binary files a/src/de/movie4k/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/serienstream/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/src/de/serienstream/res/mipmap-hdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 8c5bf007..00000000
Binary files a/src/de/serienstream/res/mipmap-hdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/serienstream/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/src/de/serienstream/res/mipmap-hdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 8dd53660..00000000
Binary files a/src/de/serienstream/res/mipmap-hdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/serienstream/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/src/de/serienstream/res/mipmap-mdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 11c72b22..00000000
Binary files a/src/de/serienstream/res/mipmap-mdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/serienstream/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/src/de/serienstream/res/mipmap-mdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index f5c1856c..00000000
Binary files a/src/de/serienstream/res/mipmap-mdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/serienstream/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/src/de/serienstream/res/mipmap-xhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 0f790191..00000000
Binary files a/src/de/serienstream/res/mipmap-xhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/serienstream/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/src/de/serienstream/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 25655d87..00000000
Binary files a/src/de/serienstream/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/serienstream/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/src/de/serienstream/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index e598be57..00000000
Binary files a/src/de/serienstream/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/serienstream/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/src/de/serienstream/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 50887149..00000000
Binary files a/src/de/serienstream/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/serienstream/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/src/de/serienstream/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 9ad66cf9..00000000
Binary files a/src/de/serienstream/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/serienstream/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/src/de/serienstream/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 846822fa..00000000
Binary files a/src/de/serienstream/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/streamcloud/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/src/de/streamcloud/res/mipmap-hdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 8c5bf007..00000000
Binary files a/src/de/streamcloud/res/mipmap-hdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/streamcloud/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/src/de/streamcloud/res/mipmap-hdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 68d25f33..00000000
Binary files a/src/de/streamcloud/res/mipmap-hdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/streamcloud/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/src/de/streamcloud/res/mipmap-mdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 11c72b22..00000000
Binary files a/src/de/streamcloud/res/mipmap-mdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/streamcloud/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/src/de/streamcloud/res/mipmap-mdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index e4635082..00000000
Binary files a/src/de/streamcloud/res/mipmap-mdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/streamcloud/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/src/de/streamcloud/res/mipmap-xhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 0f790191..00000000
Binary files a/src/de/streamcloud/res/mipmap-xhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/streamcloud/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/src/de/streamcloud/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index c935b1e2..00000000
Binary files a/src/de/streamcloud/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/streamcloud/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/src/de/streamcloud/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index e598be57..00000000
Binary files a/src/de/streamcloud/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/streamcloud/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/src/de/streamcloud/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index c7e083ea..00000000
Binary files a/src/de/streamcloud/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/de/streamcloud/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/src/de/streamcloud/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 9ad66cf9..00000000
Binary files a/src/de/streamcloud/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/de/streamcloud/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/src/de/streamcloud/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index d0da73c8..00000000
Binary files a/src/de/streamcloud/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/en/allanime/res/web_hi_res_512.png b/src/en/allanime/res/web_hi_res_512.png
deleted file mode 100644
index 77e5e5ca..00000000
Binary files a/src/en/allanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/allanimechi/res/web_hi_res_512.png b/src/en/allanimechi/res/web_hi_res_512.png
deleted file mode 100644
index 337bc317..00000000
Binary files a/src/en/allanimechi/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/animeowl/build.gradle b/src/en/animeowl/build.gradle
index a03357bc..e5849d46 100644
--- a/src/en/animeowl/build.gradle
+++ b/src/en/animeowl/build.gradle
@@ -1,7 +1,7 @@
 ext {
     extName = 'AnimeOwl'
     extClass = '.AnimeOwl'
-    extVersionCode = 21
+    extVersionCode = 22
 }
 
 apply from: "$rootDir/common.gradle"
@@ -9,4 +9,4 @@ apply from: "$rootDir/common.gradle"
 dependencies {
     implementation(project(":lib:synchrony"))
     implementation(project(":lib:playlist-utils"))
-}
\ No newline at end of file
+}
diff --git a/src/en/animeowl/res/web_hi_res_512.png b/src/en/animeowl/res/web_hi_res_512.png
deleted file mode 100644
index 8305be17..00000000
Binary files a/src/en/animeowl/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/animeowl/src/eu/kanade/tachiyomi/animeextension/en/animeowl/AnimeOwl.kt b/src/en/animeowl/src/eu/kanade/tachiyomi/animeextension/en/animeowl/AnimeOwl.kt
index dee4ddad..b53606e8 100644
--- a/src/en/animeowl/src/eu/kanade/tachiyomi/animeextension/en/animeowl/AnimeOwl.kt
+++ b/src/en/animeowl/src/eu/kanade/tachiyomi/animeextension/en/animeowl/AnimeOwl.kt
@@ -38,7 +38,7 @@ class AnimeOwl : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
 
     override val name = "AnimeOwl"
 
-    override val baseUrl = "https://animeowl.live"
+    override val baseUrl = "https://animeowl.me"
 
     override val lang = "en"
 
diff --git a/src/en/animepahe/res/web_hi_res_512.png b/src/en/animepahe/res/web_hi_res_512.png
deleted file mode 100644
index 84c0ab15..00000000
Binary files a/src/en/animepahe/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/animeparadise/res/web_hi_res_512.png b/src/en/animeparadise/res/web_hi_res_512.png
deleted file mode 100644
index 1927b8de..00000000
Binary files a/src/en/animeparadise/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/animetake/res/web_hi_res_512.png b/src/en/animetake/res/web_hi_res_512.png
deleted file mode 100644
index 5741c7d1..00000000
Binary files a/src/en/animetake/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/aniplay/ic_launcher-playstore.png b/src/en/aniplay/ic_launcher-playstore.png
deleted file mode 100644
index 7e70c67f..00000000
Binary files a/src/en/aniplay/ic_launcher-playstore.png and /dev/null differ
diff --git a/src/en/aniplay/res/web_hi_res_512.png b/src/en/aniplay/res/web_hi_res_512.png
deleted file mode 100644
index f56e465f..00000000
Binary files a/src/en/aniplay/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/asiaflix/res/web_hi_res_512.png b/src/en/asiaflix/res/web_hi_res_512.png
deleted file mode 100644
index a7cebae2..00000000
Binary files a/src/en/asiaflix/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/bestdubbedanime/res/web_hi_res_512.png b/src/en/bestdubbedanime/res/web_hi_res_512.png
deleted file mode 100644
index 6a31bcaa..00000000
Binary files a/src/en/bestdubbedanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/dopebox/res/play_store_512.png b/src/en/dopebox/res/play_store_512.png
deleted file mode 100644
index c67510b7..00000000
Binary files a/src/en/dopebox/res/play_store_512.png and /dev/null differ
diff --git a/src/en/dramacool/res/play_store_512.png b/src/en/dramacool/res/play_store_512.png
deleted file mode 100644
index 6b1a72a2..00000000
Binary files a/src/en/dramacool/res/play_store_512.png and /dev/null differ
diff --git a/src/en/edytjedhgmdhm/res/web_hi_res_512.png b/src/en/edytjedhgmdhm/res/web_hi_res_512.png
deleted file mode 100644
index 5c314e3c..00000000
Binary files a/src/en/edytjedhgmdhm/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/fmovies/res/web_hi_res_512.png b/src/en/fmovies/res/web_hi_res_512.png
deleted file mode 100644
index 116e1e1c..00000000
Binary files a/src/en/fmovies/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/gogoanime/res/web_hi_res_512.png b/src/en/gogoanime/res/web_hi_res_512.png
deleted file mode 100644
index a681ed1f..00000000
Binary files a/src/en/gogoanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/hahomoe/res/web_hi_res_512.png b/src/en/hahomoe/res/web_hi_res_512.png
deleted file mode 100644
index 0fe6a622..00000000
Binary files a/src/en/hahomoe/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/hanime/res/web_hi_res_500.png b/src/en/hanime/res/web_hi_res_500.png
deleted file mode 100644
index d80d06d9..00000000
Binary files a/src/en/hanime/res/web_hi_res_500.png and /dev/null differ
diff --git a/src/en/hentaimama/ic_launcher-playstore.png b/src/en/hentaimama/ic_launcher-playstore.png
deleted file mode 100644
index a3de5ca0..00000000
Binary files a/src/en/hentaimama/ic_launcher-playstore.png and /dev/null differ
diff --git a/src/en/hentaimama/res/web_hi_res_500.png b/src/en/hentaimama/res/web_hi_res_500.png
deleted file mode 100644
index a3de5ca0..00000000
Binary files a/src/en/hentaimama/res/web_hi_res_500.png and /dev/null differ
diff --git a/src/en/kaido/res/play_store_512.png b/src/en/kaido/res/play_store_512.png
deleted file mode 100644
index 4115b0c6..00000000
Binary files a/src/en/kaido/res/play_store_512.png and /dev/null differ
diff --git a/src/en/kawaiifu/res/web_hi_res_512.png b/src/en/kawaiifu/res/web_hi_res_512.png
deleted file mode 100644
index 40e21f8c..00000000
Binary files a/src/en/kawaiifu/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/kayoanime/res/web_hi_res_512.png b/src/en/kayoanime/res/web_hi_res_512.png
deleted file mode 100644
index 6931c263..00000000
Binary files a/src/en/kayoanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/kickassanime/res/web_hi_res_512.png b/src/en/kickassanime/res/web_hi_res_512.png
deleted file mode 100644
index 01378e9b..00000000
Binary files a/src/en/kickassanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/kimoitv/res/web_hi_res_512.png b/src/en/kimoitv/res/web_hi_res_512.png
deleted file mode 100644
index 9ee07beb..00000000
Binary files a/src/en/kimoitv/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/kissanime/res/web_hi_res_512.png b/src/en/kissanime/res/web_hi_res_512.png
deleted file mode 100644
index 582bb486..00000000
Binary files a/src/en/kissanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-hdpi/ic_launcher_background.png b/src/en/kisskh/res/mipmap-hdpi/ic_launcher_background.png
deleted file mode 100644
index ec6292a2..00000000
Binary files a/src/en/kisskh/res/mipmap-hdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-hdpi/ic_launcher_foreground.png b/src/en/kisskh/res/mipmap-hdpi/ic_launcher_foreground.png
deleted file mode 100644
index 071fd1db..00000000
Binary files a/src/en/kisskh/res/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-hdpi/ic_launcher_monochrome.png b/src/en/kisskh/res/mipmap-hdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 071fd1db..00000000
Binary files a/src/en/kisskh/res/mipmap-hdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-mdpi/ic_launcher_background.png b/src/en/kisskh/res/mipmap-mdpi/ic_launcher_background.png
deleted file mode 100644
index df2d7e08..00000000
Binary files a/src/en/kisskh/res/mipmap-mdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-mdpi/ic_launcher_foreground.png b/src/en/kisskh/res/mipmap-mdpi/ic_launcher_foreground.png
deleted file mode 100644
index 1050e1ca..00000000
Binary files a/src/en/kisskh/res/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-mdpi/ic_launcher_monochrome.png b/src/en/kisskh/res/mipmap-mdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 1050e1ca..00000000
Binary files a/src/en/kisskh/res/mipmap-mdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-xhdpi/ic_launcher_background.png b/src/en/kisskh/res/mipmap-xhdpi/ic_launcher_background.png
deleted file mode 100644
index 08c6199c..00000000
Binary files a/src/en/kisskh/res/mipmap-xhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-xhdpi/ic_launcher_foreground.png b/src/en/kisskh/res/mipmap-xhdpi/ic_launcher_foreground.png
deleted file mode 100644
index 8593420b..00000000
Binary files a/src/en/kisskh/res/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-xhdpi/ic_launcher_monochrome.png b/src/en/kisskh/res/mipmap-xhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 8593420b..00000000
Binary files a/src/en/kisskh/res/mipmap-xhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-xxhdpi/ic_launcher_background.png b/src/en/kisskh/res/mipmap-xxhdpi/ic_launcher_background.png
deleted file mode 100644
index 8b158f91..00000000
Binary files a/src/en/kisskh/res/mipmap-xxhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-xxhdpi/ic_launcher_foreground.png b/src/en/kisskh/res/mipmap-xxhdpi/ic_launcher_foreground.png
deleted file mode 100644
index 1d3082f7..00000000
Binary files a/src/en/kisskh/res/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/src/en/kisskh/res/mipmap-xxhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 1d3082f7..00000000
Binary files a/src/en/kisskh/res/mipmap-xxhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-xxxhdpi/ic_launcher_background.png b/src/en/kisskh/res/mipmap-xxxhdpi/ic_launcher_background.png
deleted file mode 100644
index a1092411..00000000
Binary files a/src/en/kisskh/res/mipmap-xxxhdpi/ic_launcher_background.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/src/en/kisskh/res/mipmap-xxxhdpi/ic_launcher_foreground.png
deleted file mode 100644
index 9def206c..00000000
Binary files a/src/en/kisskh/res/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/src/en/kisskh/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/src/en/kisskh/res/mipmap-xxxhdpi/ic_launcher_monochrome.png
deleted file mode 100644
index 9def206c..00000000
Binary files a/src/en/kisskh/res/mipmap-xxxhdpi/ic_launcher_monochrome.png and /dev/null differ
diff --git a/src/en/myanime/res/web_hi_res_512.png b/src/en/myanime/res/web_hi_res_512.png
deleted file mode 100644
index abee430c..00000000
Binary files a/src/en/myanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/noobsubs/res/web_hi_res_512.png b/src/en/noobsubs/res/web_hi_res_512.png
deleted file mode 100644
index 0e2027a2..00000000
Binary files a/src/en/noobsubs/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/putlocker/res/web_hi_res_512.png b/src/en/putlocker/res/web_hi_res_512.png
deleted file mode 100644
index c0b04c76..00000000
Binary files a/src/en/putlocker/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/rule34video/res/web_hi_res_500.png b/src/en/rule34video/res/web_hi_res_500.png
deleted file mode 100644
index 7457e072..00000000
Binary files a/src/en/rule34video/res/web_hi_res_500.png and /dev/null differ
diff --git a/src/en/sflix/res/play_store_512.png b/src/en/sflix/res/play_store_512.png
deleted file mode 100644
index 6e157d8a..00000000
Binary files a/src/en/sflix/res/play_store_512.png and /dev/null differ
diff --git a/src/en/superstream/res/web_hi_res_512.png b/src/en/superstream/res/web_hi_res_512.png
deleted file mode 100644
index bd2158b7..00000000
Binary files a/src/en/superstream/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/uhdmovies/res/web_hi_res_512.png b/src/en/uhdmovies/res/web_hi_res_512.png
deleted file mode 100644
index 42b1f7c6..00000000
Binary files a/src/en/uhdmovies/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/uniquestream/res/web_hi_res_512.png b/src/en/uniquestream/res/web_hi_res_512.png
deleted file mode 100644
index 73a3a7b0..00000000
Binary files a/src/en/uniquestream/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/wcofun/res/web_hi_res_512.png b/src/en/wcofun/res/web_hi_res_512.png
deleted file mode 100644
index fe248b2d..00000000
Binary files a/src/en/wcofun/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/en/wcostream/res/play_store_512.png b/src/en/wcostream/res/play_store_512.png
deleted file mode 100644
index b2e10c2a..00000000
Binary files a/src/en/wcostream/res/play_store_512.png and /dev/null differ
diff --git a/src/es/animefenix/build.gradle b/src/es/animefenix/build.gradle
index be565367..38c7f15a 100644
--- a/src/es/animefenix/build.gradle
+++ b/src/es/animefenix/build.gradle
@@ -1,7 +1,7 @@
 ext {
     extName = 'Animefenix'
     extClass = '.Animefenix'
-    extVersionCode = 55
+    extVersionCode = 57
 }
 
 apply from: "$rootDir/common.gradle"
@@ -17,9 +17,9 @@ dependencies {
     implementation(project(':lib:filemoon-extractor'))
     implementation(project(':lib:voe-extractor'))
     implementation(project(':lib:streamlare-extractor'))
-    implementation(project(':lib:fastream-extractor'))
     implementation(project(':lib:dood-extractor'))
     implementation(project(':lib:upstream-extractor'))
     implementation(project(':lib:streamhidevid-extractor'))
     implementation(project(':lib:universal-extractor'))
+    implementation(project(':lib:amazon-extractor'))
 }
diff --git a/src/es/animefenix/src/eu/kanade/tachiyomi/animeextension/es/animefenix/AnimeFenixFilters.kt b/src/es/animefenix/src/eu/kanade/tachiyomi/animeextension/es/animefenix/AnimeFenixFilters.kt
index eaab6fbf..5bdebcd9 100644
--- a/src/es/animefenix/src/eu/kanade/tachiyomi/animeextension/es/animefenix/AnimeFenixFilters.kt
+++ b/src/es/animefenix/src/eu/kanade/tachiyomi/animeextension/es/animefenix/AnimeFenixFilters.kt
@@ -12,30 +12,6 @@ object AnimeFenixFilters {
         fun toQueryPart(name: String) = vals[state].second.takeIf { it.isNotEmpty() }?.let { "&$name=${vals[state].second}" } ?: run { "" }
     }
 
-    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.parseCheckbox(
-        options: Array<Pair<String, String>>,
-        name: String,
-    ): String {
-        return (this.getFirst<R>() as CheckBoxFilterList).state
-            .mapNotNull { checkbox ->
-                if (checkbox.state) {
-                    options.find { it.first == checkbox.name }!!.second
-                } else {
-                    null
-                }
-            }.joinToString("&$name[]=").let {
-                if (it.isBlank()) {
-                    ""
-                } else {
-                    "&$name[]=$it"
-                }
-            }
-    }
-
     private inline fun <reified R> AnimeFilterList.asQueryPart(name: String): String {
         return (this.getFirst<R>() as QueryPartFilter).toQueryPart(name)
     }
@@ -51,111 +27,118 @@ object AnimeFenixFilters {
     internal fun getSearchParameters(filters: AnimeFilterList): FilterSearchParams {
         if (filters.isEmpty()) return FilterSearchParams()
         return FilterSearchParams(
-            filters.parseCheckbox<GenresFilter>(AnimeFenixFiltersData.GENRES, "genero") +
-                filters.parseCheckbox<YearsFilter>(AnimeFenixFiltersData.YEARS, "year") +
-                filters.parseCheckbox<TypesFilter>(AnimeFenixFiltersData.TYPES, "type") +
-                filters.parseCheckbox<StateFilter>(AnimeFenixFiltersData.STATE, "estado") +
-                filters.asQueryPart<SortFilter>("order"),
+            filters.asQueryPart<StateFilter>("estado") +
+                filters.asQueryPart<TypesFilter>("tipo") +
+                filters.asQueryPart<GenresFilter>("genero") +
+                filters.asQueryPart<YearsFilter>("estreno") +
+                filters.asQueryPart<LangFilter>("idioma"),
         )
     }
 
     val FILTER_LIST get() = AnimeFilterList(
         AnimeFilter.Header("La busqueda por texto ignora el filtro"),
+        StateFilter(),
+        TypesFilter(),
         GenresFilter(),
         YearsFilter(),
-        TypesFilter(),
-        StateFilter(),
-        SortFilter(),
+        LangFilter(),
     )
 
-    class GenresFilter : CheckBoxFilterList("Género", AnimeFenixFiltersData.GENRES.map { CheckBoxVal(it.first, false) })
-
-    class YearsFilter : CheckBoxFilterList("Año", AnimeFenixFiltersData.YEARS.map { CheckBoxVal(it.first, false) })
-
-    class TypesFilter : CheckBoxFilterList("Tipo", AnimeFenixFiltersData.TYPES.map { CheckBoxVal(it.first, false) })
-
-    class StateFilter : CheckBoxFilterList("Estado", AnimeFenixFiltersData.STATE.map { CheckBoxVal(it.first, false) })
-
-    class SortFilter : QueryPartFilter("Orden", AnimeFenixFiltersData.SORT)
+    class StateFilter : QueryPartFilter("Estado", AnimeFenixFiltersData.STATE)
+    class TypesFilter : QueryPartFilter("Tipo", AnimeFenixFiltersData.TYPES)
+    class GenresFilter : QueryPartFilter("Género", AnimeFenixFiltersData.GENRES)
+    class YearsFilter : QueryPartFilter("Año", AnimeFenixFiltersData.YEARS)
+    class LangFilter : QueryPartFilter("Idioma", AnimeFenixFiltersData.LANGUAGE)
 
     private object AnimeFenixFiltersData {
-        val YEARS = (1990..Calendar.getInstance().get(Calendar.YEAR)).map { Pair("$it", "$it") }.reversed().toTypedArray()
+        val STATE = arrayOf(
+            Pair("Todos", ""),
+            Pair("Emisión", "2"),
+            Pair("Finalizado", "1"),
+            Pair("Próximamente", "3"),
+        )
 
         val TYPES = arrayOf(
-            Pair("TV", "tv"),
-            Pair("Película", "movie"),
-            Pair("Especial", "special"),
-            Pair("OVA", "ova"),
-            Pair("DONGHUA", "donghua"),
-        )
-
-        val STATE = arrayOf(
-            Pair("Emisión", "1"),
-            Pair("Finalizado", "2"),
-            Pair("Próximamente", "3"),
-            Pair("En Cuarentena", "4"),
-        )
-
-        val SORT = arrayOf(
-            Pair("Por Defecto", "default"),
-            Pair("Recientemente Actualizados", "updated"),
-            Pair("Recientemente Agregados", "added"),
-            Pair("Nombre A-Z", "title"),
-            Pair("Calificación", "likes"),
-            Pair("Más Vistos", "visits"),
+            Pair("Todos", ""),
+            Pair("TV", "1"),
+            Pair("Película", "2"),
+            Pair("OVA", "3"),
+            Pair("Especial", "4"),
+            Pair("Serie", "9"),
+            Pair("Dorama", "11"),
+            Pair("Corto", "14"),
+            Pair("Donghua", "15"),
+            Pair("ONA", "16"),
+            Pair("Live Action", "17"),
+            Pair("Manhwa", "18"),
+            Pair("Teatral", "19"),
         )
 
         val GENRES = arrayOf(
-            Pair("Acción", "accion"),
-            Pair("Ángeles", "angeles"),
-            Pair("Artes Marciales", "artes-marciales"),
-            Pair("Aventura", "aventura"),
-            Pair("Ciencia Ficción", "Ciencia Ficción"),
-            Pair("Comedia", "comedia"),
-            Pair("Cyberpunk", "cyberpunk"),
-            Pair("Demonios", "demonios"),
-            Pair("Deportes", "deportes"),
-            Pair("Dragones", "dragones"),
-            Pair("Drama", "drama"),
-            Pair("Ecchi", "ecchi"),
-            Pair("Escolares", "escolares"),
-            Pair("Fantasía", "fantasia"),
-            Pair("Gore", "gore"),
-            Pair("Harem", "harem"),
-            Pair("Histórico", "historico"),
-            Pair("Horror", "horror"),
-            Pair("Infantil", "infantil"),
-            Pair("Isekai", "isekai"),
-            Pair("Josei", "josei"),
-            Pair("Juegos", "juegos"),
-            Pair("Magia", "magia"),
-            Pair("Mecha", "mecha"),
-            Pair("Militar", "militar"),
-            Pair("Misterio", "misterio"),
-            Pair("Música", "Musica"),
-            Pair("Ninjas", "ninjas"),
-            Pair("Parodia", "parodia"),
-            Pair("Policía", "policia"),
-            Pair("Psicológico", "psicologico"),
-            Pair("Recuerdos de la vida", "Recuerdos de la vida"),
-            Pair("Romance", "romance"),
-            Pair("Samurai", "samurai"),
-            Pair("Sci-Fi", "sci-fi"),
-            Pair("Seinen", "seinen"),
-            Pair("Shoujo", "shoujo"),
-            Pair("Shoujo Ai", "shoujo-ai"),
-            Pair("Shounen", "shounen"),
-            Pair("Slice of life", "slice-of-life"),
-            Pair("Sobrenatural", "sobrenatural"),
-            Pair("Space", "space"),
-            Pair("Spokon", "spokon"),
-            Pair("Steampunk", "steampunk"),
-            Pair("Superpoder", "superpoder"),
-            Pair("Thriller", "thriller"),
-            Pair("Vampiro", "vampiro"),
-            Pair("Yaoi", "yaoi"),
-            Pair("Yuri", "yuri"),
-            Pair("Zombies", "zombies"),
+            Pair("Todos", ""),
+            Pair("Acción", "1"),
+            Pair("Escolares", "2"),
+            Pair("Romance", "3"),
+            Pair("Shoujo", "4"),
+            Pair("Comedia", "5"),
+            Pair("Drama", "6"),
+            Pair("Seinen", "7"),
+            Pair("Deportes", "8"),
+            Pair("Shounen", "9"),
+            Pair("Recuentos de la vida", "10"),
+            Pair("Ecchi", "11"),
+            Pair("Sobrenatural", "12"),
+            Pair("Fantasía", "13"),
+            Pair("Magia", "14"),
+            Pair("Superpoderes", "15"),
+            Pair("Demencia", "16"),
+            Pair("Misterio", "17"),
+            Pair("Psicológico", "18"),
+            Pair("Suspenso", "19"),
+            Pair("Ciencia Ficción", "20"),
+            Pair("Mecha", "21"),
+            Pair("Militar", "22"),
+            Pair("Aventuras", "23"),
+            Pair("Historico", "24"),
+            Pair("Infantil", "25"),
+            Pair("Artes Marciales", "26"),
+            Pair("Terror", "27"),
+            Pair("Harem", "28"),
+            Pair("Josei", "29"),
+            Pair("Parodia", "30"),
+            Pair("Policía", "31"),
+            Pair("Juegos", "32"),
+            Pair("Carreras", "33"),
+            Pair("Samurai", "34"),
+            Pair("Espacial", "35"),
+            Pair("Música", "36"),
+            Pair("Yuri", "37"),
+            Pair("Demonios", "38"),
+            Pair("Vampiros", "39"),
+            Pair("Yaoi", "40"),
+            Pair("Humor Negro", "41"),
+            Pair("Crimen", "42"),
+            Pair("Hentai", "43"),
+            Pair("Youtuber", "44"),
+            Pair("MaiNess Random", "45"),
+            Pair("Donghua", "46"),
+            Pair("Horror", "47"),
+            Pair("Sin Censura", "48"),
+            Pair("Gore", "49"),
+            Pair("Live Action", "50"),
+            Pair("Isekai", "51"),
+            Pair("Gourmet", "52"),
+            Pair("spokon", "53"),
+            Pair("Zombies", "54"),
+            Pair("Idols", "55"),
         )
+
+        val LANGUAGE = arrayOf(
+            Pair("Todos", ""),
+            Pair("Japonés", "1"),
+            Pair("Latino", "2"),
+        )
+
+        val YEARS = arrayOf(Pair("Todos", "")) + (1967..Calendar.getInstance().get(Calendar.YEAR)).map { Pair("$it", "$it") }.reversed().toTypedArray()
     }
 }
diff --git a/src/es/animefenix/src/eu/kanade/tachiyomi/animeextension/es/animefenix/Animefenix.kt b/src/es/animefenix/src/eu/kanade/tachiyomi/animeextension/es/animefenix/Animefenix.kt
index dc1487bd..adb7fef5 100644
--- a/src/es/animefenix/src/eu/kanade/tachiyomi/animeextension/es/animefenix/Animefenix.kt
+++ b/src/es/animefenix/src/eu/kanade/tachiyomi/animeextension/es/animefenix/Animefenix.kt
@@ -11,9 +11,9 @@ 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.amazonextractor.AmazonExtractor
 import eu.kanade.tachiyomi.lib.burstcloudextractor.BurstCloudExtractor
 import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
-import eu.kanade.tachiyomi.lib.fastreamextractor.FastreamExtractor
 import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
 import eu.kanade.tachiyomi.lib.mp4uploadextractor.Mp4uploadExtractor
 import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
@@ -28,37 +28,35 @@ import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
 import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
 import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.util.asJsoup
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
-import okhttp3.HttpUrl.Companion.toHttpUrl
+import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
 import okhttp3.Request
 import okhttp3.Response
+import org.jsoup.nodes.Element
+import org.jsoup.select.Elements
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
-import java.net.URLDecoder
 
 class Animefenix : ConfigurableAnimeSource, AnimeHttpSource() {
 
     override val name = "AnimeFenix"
 
-    override val baseUrl = "https://www3.animefenix.tv"
+    override val baseUrl = "https://animefenix2.tv"
 
     override val lang = "es"
 
-    override val supportsLatest = true
+    override val supportsLatest = false
 
-    private val preferences: SharedPreferences by lazy { Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) }
+    private val preferences: SharedPreferences by lazy {
+        Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
+    }
 
     companion object {
-        private val SERVER_REGEX = """tabsArray\['?\d+'?]\s*=\s*['\"](https[^'\"]+)['\"]""".toRegex()
         private const val PREF_QUALITY_KEY = "preferred_quality"
         private const val PREF_QUALITY_DEFAULT = "1080"
         private val QUALITY_LIST = arrayOf("1080", "720", "480", "360")
 
         private const val PREF_SERVER_KEY = "preferred_server"
-        private const val PREF_SERVER_DEFAULT = "Amazon"
+        private const val PREF_SERVER_DEFAULT = "Mp4Upload"
         private val SERVER_LIST = arrayOf(
             "YourUpload", "Voe", "Mp4Upload", "Doodstream",
             "Upload", "BurstCloud", "Upstream", "StreamTape",
@@ -67,33 +65,45 @@ class Animefenix : ConfigurableAnimeSource, AnimeHttpSource() {
         )
     }
 
-    override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/animes?order=likes&page=$page")
+    override fun animeDetailsParse(response: Response): SAnime {
+        val document = response.asJsoup()
+        val animeDetails = SAnime.create().apply {
+            title = document.selectFirst("h1.text-4xl")?.ownText() ?: ""
+            status = document.select(".relative .rounded").getStatus()
+            description = document.selectFirst(".mb-6 p.text-gray-300")?.text()
+            genre = document.select(".flex-wrap a").joinToString { it.text().trim() }
+            thumbnail_url = document.selectFirst("#anime_image")?.getImageUrl()
+        }
+        return animeDetails
+    }
+
+    override fun popularAnimeRequest(page: Int) = GET("$baseUrl/directorio/anime?p=$page&estado=2", headers)
 
     override fun popularAnimeParse(response: Response): AnimesPage {
         val document = response.asJsoup()
-        val elements = document.select("div.container .grid.gap-4 a[href]")
-        val nextPage = document.select("nav[aria-label=Pagination] span:containsOwn(Next)").any()
+        val elements = document.select(".grid-animes li article a")
+        val nextPage = document.select(".right:not(.disabledd)").any()
         val animeList = elements.map { element ->
             SAnime.create().apply {
-                setUrlWithoutDomain(element.selectFirst("a")!!.attr("abs:href"))
-                title = element.selectFirst("div h3.text-primary")!!.ownText()
-                thumbnail_url = element.selectFirst("img.object-cover")?.attr("abs:src")
+                setUrlWithoutDomain(element.attr("abs:href"))
+                title = element.selectFirst("p:not(.gray)")?.text() ?: ""
+                thumbnail_url = element.selectFirst(".main-img img")?.getImageUrl()
             }
         }
         return AnimesPage(animeList, nextPage)
     }
 
-    override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/animes?order=added&page=$page")
+    override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException()
 
-    override fun latestUpdatesParse(response: Response) = popularAnimeParse(response)
+    override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException()
 
     override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
         val params = AnimeFenixFilters.getSearchParameters(filters)
 
         return when {
-            query.isNotBlank() -> GET("$baseUrl/animes?q=$query&page=$page", headers)
-            params.filter.isNotBlank() -> GET("$baseUrl/animes${params.getQuery()}&page=$page", headers)
-            else -> GET("$baseUrl/animes?order=likes&page=$page")
+            query.isNotBlank() -> GET("$baseUrl/directorio/anime?q=$query&p=$page", headers)
+            params.filter.isNotBlank() -> GET("$baseUrl/directorio/anime${params.getQuery()}&page=$page", headers)
+            else -> popularAnimeRequest(page)
         }
     }
 
@@ -101,115 +111,77 @@ class Animefenix : ConfigurableAnimeSource, AnimeHttpSource() {
 
     override fun episodeListParse(response: Response): List<SEpisode> {
         val document = response.asJsoup()
-        return document.select("div.container > div > ul > li").map { element ->
+        return document.select(".divide-y li > a").map {
+            val title = it.select(".font-semibold").text()
             SEpisode.create().apply {
-                name = element.selectFirst("span > span")!!.ownText()
-                setUrlWithoutDomain(element.selectFirst("a")!!.attr("abs:href"))
+                name = title
+                episode_number = title.substringAfter("Episodio").toFloatOrNull() ?: 0F
+                setUrlWithoutDomain(it.attr("abs:href"))
             }
         }
     }
 
     override fun videoListParse(response: Response): List<Video> {
         val document = response.asJsoup()
-        val videoList = mutableListOf<Video>()
-        val serversData = document.selectFirst("script:containsData(var tabsArray)")?.data() ?: throw Exception("No se encontraron servidores")
-        val servers = SERVER_REGEX.findAll(serversData).map { it.groupValues[1] }.toList()
-
-        servers.parallelForEachBlocking { server ->
-            val decodedUrl = URLDecoder.decode(server, "UTF-8")
-            val realUrl = try {
-                client.newCall(GET(decodedUrl)).execute().asJsoup().selectFirst("script")!!
-                    .data().substringAfter("src=\"").substringBefore("\"")
-            } catch (e: Exception) { "" }
-
-            try {
-                serverVideoResolver(realUrl).let { videoList.addAll(it) }
-            } catch (_: Exception) { }
-        }
-        return videoList.filter { it.url.contains("https") || it.url.contains("http") }
+        val script = document.selectFirst("script:containsData(var tabsArray)") ?: return emptyList()
+        return script.data().substringAfter("<iframe").split("src='")
+            .map { it.substringBefore("'").substringAfter("redirect.php?id=").trim() }
+            .parallelCatchingFlatMapBlocking { url ->
+                serverVideoResolver(url)
+            }
     }
 
+    /*-------------------------------- Video extractors ------------------------------------*/
+    private val universalExtractor by lazy { UniversalExtractor(client) }
+    private val voeExtractor by lazy { VoeExtractor(client) }
+    private val okruExtractor by lazy { OkruExtractor(client) }
+    private val filemoonExtractor by lazy { FilemoonExtractor(client) }
+    private val uqloadExtractor by lazy { UqloadExtractor(client) }
+    private val mp4uploadExtractor by lazy { Mp4uploadExtractor(client) }
+    private val streamwishExtractor by lazy { StreamWishExtractor(client, headers) }
+    private val doodExtractor by lazy { DoodExtractor(client) }
+    private val streamlareExtractor by lazy { StreamlareExtractor(client) }
+    private val yourUploadExtractor by lazy { YourUploadExtractor(client) }
+    private val burstcloudExtractor by lazy { BurstCloudExtractor(client) }
+    private val upstreamExtractor by lazy { UpstreamExtractor(client) }
+    private val streamTapeExtractor by lazy { StreamTapeExtractor(client) }
+    private val streamHideVidExtractor by lazy { StreamHideVidExtractor(client, headers) }
+    private val filelionsExtractor by lazy { StreamWishExtractor(client, headers) }
+    private val amazonExtractor by lazy { AmazonExtractor(client) }
+
     private fun serverVideoResolver(url: String): List<Video> {
-        val videoList = mutableListOf<Video>()
-        val embedUrl = url.lowercase()
-        try {
+        return runCatching {
             when {
-                embedUrl.contains("voe") -> {
-                    VoeExtractor(client).videosFromUrl(url).also(videoList::addAll)
-                }
-                (embedUrl.contains("amazon") || embedUrl.contains("amz")) && !embedUrl.contains("disable") -> {
-                    val video = amazonExtractor(baseUrl + url.substringAfter(".."))
-                    if (video.isNotBlank()) {
-                        if (url.contains("&ext=es")) {
-                            videoList.add(Video(video, "AmazonES", video))
-                        } else {
-                            videoList.add(Video(video, "Amazon", video))
-                        }
-                    }
-                }
-                embedUrl.contains("ok.ru") || embedUrl.contains("okru") -> {
-                    OkruExtractor(client).videosFromUrl(url).also(videoList::addAll)
-                }
-                embedUrl.contains("filemoon") || embedUrl.contains("moonplayer") -> {
-                    val vidHeaders = headers.newBuilder()
-                        .add("Origin", "https://${url.toHttpUrl().host}")
-                        .add("Referer", "https://${url.toHttpUrl().host}/")
-                        .build()
-                    FilemoonExtractor(client).videosFromUrl(url, prefix = "Filemoon:", headers = vidHeaders).also(videoList::addAll)
-                }
-                embedUrl.contains("uqload") -> {
-                    UqloadExtractor(client).videosFromUrl(url).also(videoList::addAll)
-                }
-                embedUrl.contains("mp4upload") -> {
-                    Mp4uploadExtractor(client).videosFromUrl(url, headers).let { videoList.addAll(it) }
-                }
-                embedUrl.contains("wishembed") || embedUrl.contains("embedwish") || embedUrl.contains("streamwish") || embedUrl.contains("strwish") || embedUrl.contains("wish") -> {
-                    val docHeaders = headers.newBuilder()
-                        .add("Origin", "https://streamwish.to")
-                        .add("Referer", "https://streamwish.to/")
-                        .build()
-                    StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "StreamWish:$it" }).also(videoList::addAll)
-                }
-                embedUrl.contains("doodstream") || embedUrl.contains("dood.") -> {
-                    DoodExtractor(client).videoFromUrl(url, "DoodStream")?.let { videoList.add(it) }
-                }
-                embedUrl.contains("streamlare") -> {
-                    StreamlareExtractor(client).videosFromUrl(url).let { videoList.addAll(it) }
-                }
-                embedUrl.contains("yourupload") || embedUrl.contains("upload") -> {
-                    YourUploadExtractor(client).videoFromUrl(url, headers = headers).let { videoList.addAll(it) }
-                }
-                embedUrl.contains("burstcloud") || embedUrl.contains("burst") -> {
-                    BurstCloudExtractor(client).videoFromUrl(url, headers = headers).let { videoList.addAll(it) }
-                }
-                embedUrl.contains("fastream") -> {
-                    FastreamExtractor(client, headers).videosFromUrl(url).also(videoList::addAll)
-                }
-                embedUrl.contains("upstream") -> {
-                    UpstreamExtractor(client).videosFromUrl(url).let { videoList.addAll(it) }
-                }
-                embedUrl.contains("streamtape") || embedUrl.contains("stp") || embedUrl.contains("stape") -> {
-                    StreamTapeExtractor(client).videoFromUrl(url)?.let { videoList.add(it) }
-                }
-                embedUrl.contains("ahvsh") || embedUrl.contains("streamhide") -> {
-                    StreamHideVidExtractor(client, headers).videosFromUrl(url).let { videoList.addAll(it) }
-                }
-                embedUrl.contains("/stream/fl.php") -> {
+                arrayOf("voe", "robertordercharacter", "donaldlineelse").any(url) -> voeExtractor.videosFromUrl(url)
+                arrayOf("amazon", "amz").any(url) -> amazonExtractor.videosFromUrl(url)
+                arrayOf("ok.ru", "okru").any(url) -> okruExtractor.videosFromUrl(url)
+                arrayOf("moon").any(url) -> filemoonExtractor.videosFromUrl(url, prefix = "Filemoon:")
+                arrayOf("uqload").any(url) -> uqloadExtractor.videosFromUrl(url)
+                arrayOf("mp4upload").any(url) -> mp4uploadExtractor.videosFromUrl(url, headers)
+                arrayOf("wish").any(url) -> streamwishExtractor.videosFromUrl(url, videoNameGen = { "StreamWish:$it" })
+                arrayOf("doodstream", "dood.").any(url) -> doodExtractor.videosFromUrl(url, "DoodStream")
+                arrayOf("streamlare").any(url) -> streamlareExtractor.videosFromUrl(url)
+                arrayOf("yourupload", "upload").any(url) -> yourUploadExtractor.videoFromUrl(url, headers = headers)
+                arrayOf("burstcloud", "burst").any(url) -> burstcloudExtractor.videoFromUrl(url, headers = headers)
+                arrayOf("upstream").any(url) -> upstreamExtractor.videosFromUrl(url)
+                arrayOf("streamtape", "stp", "stape").any(url) -> streamTapeExtractor.videosFromUrl(url)
+                arrayOf("ahvsh", "streamhide").any(url) -> streamHideVidExtractor.videosFromUrl(url)
+                arrayOf("/stream/fl.php").any(url) -> {
                     val video = url.substringAfter("/stream/fl.php?v=")
                     if (client.newCall(GET(video)).execute().code == 200) {
-                        videoList.add(Video(video, "FireLoad", video))
+                        listOf(Video(video, "FireLoad", video))
+                    } else {
+                        emptyList()
                     }
                 }
-                embedUrl.contains("filelions") || embedUrl.contains("lion") -> {
-                    StreamWishExtractor(client, headers).videosFromUrl(url, videoNameGen = { "FileLions:$it" }).also(videoList::addAll)
-                }
-                else ->
-                    UniversalExtractor(client).videosFromUrl(url, headers).let { videoList.addAll(it) }
+                arrayOf("lion").any(url) -> filelionsExtractor.videosFromUrl(url, videoNameGen = { "FileLions:$it" })
+                else -> universalExtractor.videosFromUrl(url, headers)
             }
-        } catch (_: Exception) { }
-        return videoList
+        }.getOrElse { emptyList() }
     }
 
+    private fun Array<String>.any(url: String): Boolean = this.any { url.contains(it, ignoreCase = true) }
+
     override fun List<Video>.sort(): List<Video> {
         val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!
         val server = preferences.getString(PREF_SERVER_KEY, PREF_SERVER_DEFAULT)!!
@@ -222,56 +194,32 @@ class Animefenix : ConfigurableAnimeSource, AnimeHttpSource() {
         ).reversed()
     }
 
-    override fun animeDetailsParse(response: Response) = SAnime.create().apply {
-        val document = response.asJsoup()
-        with(document.selectFirst("main > div.relative > div.container > div.flex")!!) {
-            title = selectFirst("h1.font-bold")!!.ownText()
-            genre = select("div:has(h2:containsOwn(Géneros)) > div.flex > a").joinToString { it.text() }
-            status = parseStatus(selectFirst("li:has(> span:containsOwn(Estado))")!!.ownText())
-            description = select("div:has(h2:containsOwn(Sinopsis)) > p").text()
-        }
-    }
-
-    private fun parseStatus(statusString: String): Int {
+    private fun Elements.getStatus(): Int {
         return when {
-            statusString.contains("Emisión") -> SAnime.ONGOING
-            statusString.contains("Finalizado") -> SAnime.COMPLETED
+            text().contains("finalizado", true) -> SAnime.COMPLETED
+            text().contains("emision", true) -> SAnime.ONGOING
             else -> SAnime.UNKNOWN
         }
     }
 
-    private fun amazonExtractor(url: String): String {
-        val document = client.newCall(GET(url)).execute().asJsoup()
-        val videoURl = document.selectFirst("script:containsData(sources: [)")!!.data()
-            .substringAfter("[{\"file\":\"")
-            .substringBefore("\",").replace("\\", "")
-
-        return try {
-            if (client.newCall(GET(videoURl)).execute().code == 200) videoURl else ""
-        } catch (e: Exception) {
-            ""
+    private fun Element.getImageUrl(): String? {
+        return when {
+            isValidUrl("data-src") -> attr("abs:data-src")
+            isValidUrl("data-lazy-src") -> attr("abs:data-lazy-src")
+            isValidUrl("srcset") -> attr("abs:srcset").substringBefore(" ")
+            isValidUrl("src") -> attr("abs:src")
+            else -> ""
         }
     }
 
+    private fun Element.isValidUrl(attrName: String): Boolean {
+        if (!hasAttr(attrName)) return false
+        return !attr(attrName).contains("data:image/")
+    }
+
     override fun getFilterList(): AnimeFilterList = AnimeFenixFilters.FILTER_LIST
 
     override fun setupPreferenceScreen(screen: PreferenceScreen) {
-        ListPreference(screen.context).apply {
-            key = PREF_QUALITY_KEY
-            title = "Preferred quality"
-            entries = QUALITY_LIST
-            entryValues = QUALITY_LIST
-            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)
-
         ListPreference(screen.context).apply {
             key = PREF_SERVER_KEY
             title = "Preferred server"
@@ -287,21 +235,21 @@ class Animefenix : ConfigurableAnimeSource, AnimeHttpSource() {
                 preferences.edit().putString(key, entry).commit()
             }
         }.also(screen::addPreference)
-    }
 
-    suspend inline fun <A> Iterable<A>.parallelForEach(crossinline f: suspend (A) -> Unit) {
-        coroutineScope {
-            for (item in this@parallelForEach) {
-                launch(Dispatchers.IO) {
-                    f(item)
-                }
+        ListPreference(screen.context).apply {
+            key = PREF_QUALITY_KEY
+            title = "Preferred quality"
+            entries = QUALITY_LIST
+            entryValues = QUALITY_LIST
+            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()
             }
-        }
-    }
-
-    inline fun <A> Iterable<A>.parallelForEachBlocking(crossinline f: suspend (A) -> Unit) {
-        runBlocking {
-            this@parallelForEachBlocking.parallelForEach(f)
-        }
+        }.also(screen::addPreference)
     }
 }
diff --git a/src/es/animefenix/src/eu/kanade/tachiyomi/animeextension/es/animefenix/extractors/SolidFilesExtractor.kt b/src/es/animefenix/src/eu/kanade/tachiyomi/animeextension/es/animefenix/extractors/SolidFilesExtractor.kt
deleted file mode 100644
index a66b611e..00000000
--- a/src/es/animefenix/src/eu/kanade/tachiyomi/animeextension/es/animefenix/extractors/SolidFilesExtractor.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.es.animefenix.extractors
-
-import eu.kanade.tachiyomi.animesource.model.Video
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.util.asJsoup
-import okhttp3.OkHttpClient
-
-class SolidFilesExtractor(private val client: OkHttpClient) {
-    fun videosFromUrl(url: String, prefix: String = ""): List<Video> {
-        val videoList = mutableListOf<Video>()
-        return try {
-            val document = client.newCall(GET(url)).execute().asJsoup()
-            document.select("script").forEach { script ->
-                if (script.data().contains("\"downloadUrl\":")) {
-                    val data = script.data().substringAfter("\"downloadUrl\":").substringBefore(",")
-                    val url = data.replace("\"", "")
-                    val videoUrl = url
-                    val quality = prefix + "SolidFiles"
-                    videoList.add(Video(videoUrl, quality, videoUrl))
-                }
-            }
-            videoList
-        } catch (e: Exception) {
-            videoList
-        }
-    }
-}
diff --git a/src/es/cinecalidad/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/src/es/cinecalidad/res/mipmap-hdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index a31f7028..00000000
Binary files a/src/es/cinecalidad/res/mipmap-hdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/es/cinecalidad/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/src/es/cinecalidad/res/mipmap-hdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 3ce663b6..00000000
Binary files a/src/es/cinecalidad/res/mipmap-hdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/es/cinecalidad/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/src/es/cinecalidad/res/mipmap-mdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 21d5008b..00000000
Binary files a/src/es/cinecalidad/res/mipmap-mdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/es/cinecalidad/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/src/es/cinecalidad/res/mipmap-mdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 49b2a43e..00000000
Binary files a/src/es/cinecalidad/res/mipmap-mdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/es/cinecalidad/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/src/es/cinecalidad/res/mipmap-xhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 776ce9a3..00000000
Binary files a/src/es/cinecalidad/res/mipmap-xhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/es/cinecalidad/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/src/es/cinecalidad/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index e18190fe..00000000
Binary files a/src/es/cinecalidad/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/es/cinecalidad/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/src/es/cinecalidad/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 9de1ea8f..00000000
Binary files a/src/es/cinecalidad/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/es/cinecalidad/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/src/es/cinecalidad/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index b65fd053..00000000
Binary files a/src/es/cinecalidad/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/es/cinecalidad/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/src/es/cinecalidad/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 81b316ba..00000000
Binary files a/src/es/cinecalidad/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/es/cinecalidad/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/src/es/cinecalidad/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 13dcfcb4..00000000
Binary files a/src/es/cinecalidad/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/es/cineplus123/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/src/es/cineplus123/res/mipmap-hdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 3f50df92..00000000
Binary files a/src/es/cineplus123/res/mipmap-hdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/es/cineplus123/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/src/es/cineplus123/res/mipmap-hdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index ca607167..00000000
Binary files a/src/es/cineplus123/res/mipmap-hdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/es/cineplus123/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/src/es/cineplus123/res/mipmap-mdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 5a270b5a..00000000
Binary files a/src/es/cineplus123/res/mipmap-mdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/es/cineplus123/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/src/es/cineplus123/res/mipmap-mdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 8efd6289..00000000
Binary files a/src/es/cineplus123/res/mipmap-mdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/es/cineplus123/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/src/es/cineplus123/res/mipmap-xhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 36d4e2d1..00000000
Binary files a/src/es/cineplus123/res/mipmap-xhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/es/cineplus123/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/src/es/cineplus123/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 5091966c..00000000
Binary files a/src/es/cineplus123/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/es/cineplus123/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/src/es/cineplus123/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index aacf215b..00000000
Binary files a/src/es/cineplus123/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/es/cineplus123/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/src/es/cineplus123/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 636d2123..00000000
Binary files a/src/es/cineplus123/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/es/cineplus123/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/src/es/cineplus123/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 50e3aba3..00000000
Binary files a/src/es/cineplus123/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/es/cineplus123/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/src/es/cineplus123/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 923c8960..00000000
Binary files a/src/es/cineplus123/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/es/latanime/res/web_hi_res_512.png b/src/es/latanime/res/web_hi_res_512.png
deleted file mode 100644
index c67e40f7..00000000
Binary files a/src/es/latanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/es/otakuverso/build.gradle b/src/es/otakuverso/build.gradle
new file mode 100644
index 00000000..830bd251
--- /dev/null
+++ b/src/es/otakuverso/build.gradle
@@ -0,0 +1,27 @@
+ext {
+    extName = 'Otakuverso'
+    extClass = '.Otakuverso'
+    extVersionCode = 1
+}
+
+apply from: "$rootDir/common.gradle"
+
+dependencies {
+    implementation(project(':lib:mp4upload-extractor'))
+    implementation(project(':lib:streamtape-extractor'))
+    implementation(project(':lib:yourupload-extractor'))
+    implementation(project(':lib:uqload-extractor'))
+    implementation(project(':lib:okru-extractor'))
+    implementation(project(':lib:burstcloud-extractor'))
+    implementation(project(':lib:streamwish-extractor'))
+    implementation(project(':lib:filemoon-extractor'))
+    implementation(project(':lib:voe-extractor'))
+    implementation(project(':lib:streamlare-extractor'))
+    implementation(project(':lib:dood-extractor'))
+    implementation(project(':lib:upstream-extractor'))
+    implementation(project(':lib:streamhidevid-extractor'))
+    implementation(project(':lib:universal-extractor'))
+    implementation(project(':lib:sendvid-extractor'))
+    implementation(project(':lib:playlist-utils'))
+    implementation(libs.jsunpacker)
+}
\ No newline at end of file
diff --git a/src/es/otakuverso/res/mipmap-hdpi/ic_launcher.png b/src/es/otakuverso/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..cf3d0126
Binary files /dev/null and b/src/es/otakuverso/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/src/es/otakuverso/res/mipmap-mdpi/ic_launcher.png b/src/es/otakuverso/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..cf3d0126
Binary files /dev/null and b/src/es/otakuverso/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/src/es/otakuverso/res/mipmap-xhdpi/ic_launcher.png b/src/es/otakuverso/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..cf3d0126
Binary files /dev/null and b/src/es/otakuverso/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/src/es/otakuverso/res/mipmap-xxhdpi/ic_launcher.png b/src/es/otakuverso/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..cf3d0126
Binary files /dev/null and b/src/es/otakuverso/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/src/es/otakuverso/res/mipmap-xxxhdpi/ic_launcher.png b/src/es/otakuverso/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..cf3d0126
Binary files /dev/null and b/src/es/otakuverso/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/src/es/otakuverso/src/eu/kanade/tachiyomi/animeextension/es/otakuverso/Otakuverso.kt b/src/es/otakuverso/src/eu/kanade/tachiyomi/animeextension/es/otakuverso/Otakuverso.kt
new file mode 100644
index 00000000..025b34a2
--- /dev/null
+++ b/src/es/otakuverso/src/eu/kanade/tachiyomi/animeextension/es/otakuverso/Otakuverso.kt
@@ -0,0 +1,339 @@
+package eu.kanade.tachiyomi.animeextension.es.otakuverso
+
+import android.app.Application
+import android.content.SharedPreferences
+import android.util.Log
+import androidx.preference.ListPreference
+import androidx.preference.PreferenceScreen
+import eu.kanade.tachiyomi.animeextension.es.otakuverso.extractors.UnpackerExtractor
+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.burstcloudextractor.BurstCloudExtractor
+import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
+import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
+import eu.kanade.tachiyomi.lib.mp4uploadextractor.Mp4uploadExtractor
+import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
+import eu.kanade.tachiyomi.lib.sendvidextractor.SendvidExtractor
+import eu.kanade.tachiyomi.lib.streamhidevidextractor.StreamHideVidExtractor
+import eu.kanade.tachiyomi.lib.streamlareextractor.StreamlareExtractor
+import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
+import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
+import eu.kanade.tachiyomi.lib.universalextractor.UniversalExtractor
+import eu.kanade.tachiyomi.lib.upstreamextractor.UpstreamExtractor
+import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
+import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
+import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.network.POST
+import eu.kanade.tachiyomi.network.await
+import eu.kanade.tachiyomi.util.asJsoup
+import eu.kanade.tachiyomi.util.parallelCatchingFlatMap
+import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
+import okhttp3.FormBody
+import okhttp3.HttpUrl.Companion.toHttpUrl
+import okhttp3.Request
+import okhttp3.Response
+import org.jsoup.nodes.Document
+import org.jsoup.nodes.Element
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.get
+
+class Otakuverso : ConfigurableAnimeSource, AnimeHttpSource() {
+
+    override val name = "Otakuverso"
+
+    override val baseUrl = "https://otakuverso.net"
+
+    override val lang = "es"
+
+    override val supportsLatest = false
+
+    private val preferences: SharedPreferences by lazy {
+        Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
+    }
+
+    companion object {
+        private const val PREF_QUALITY_KEY = "preferred_quality"
+        private const val PREF_QUALITY_DEFAULT = "1080"
+        private val QUALITY_LIST = arrayOf("1080", "720", "480", "360")
+
+        private const val PREF_SERVER_KEY = "preferred_server"
+        private const val PREF_SERVER_DEFAULT = "YourUpload"
+        private val SERVER_LIST = arrayOf(
+            "YourUpload", "Voe", "Mp4Upload", "Doodstream",
+            "Upload", "BurstCloud", "Upstream", "StreamTape",
+            "Fastream", "Filemoon", "StreamWish", "Okru",
+            "Amazon", "AmazonES", "Fireload", "FileLions",
+        )
+    }
+
+    override fun animeDetailsParse(response: Response): SAnime {
+        val document = response.asJsoup()
+        return SAnime.create().apply {
+            title = document.selectFirst("#back_data_perfil .inn-text h1")?.text().orEmpty()
+            description = document.selectFirst("#back_data_perfil .inn-text p.font14")?.ownText()
+            genre = document.select(".pre .text-deco-none.font-GDSherpa-Regular").joinToString { it.text() }
+            status = with(document.select("#back_data_perfil .inn-text .btn-anime-info")) {
+                when {
+                    text().contains("finalizado", true) -> SAnime.COMPLETED
+                    text().contains("emision", true) || text().contains("emitiéndose", true) -> SAnime.ONGOING
+                    else -> SAnime.UNKNOWN
+                }
+            }
+            document.select(".col-xl-12 .font-GDSherpa-Regular")
+                .map { it.select(".text-white").text() to it.select(".lila-color").text() }
+                .forEach { (title, content) ->
+                    when {
+                        title.contains("Creador(a)", true) -> author = content
+                        title.contains("Director(a)", true) -> artist = content
+                    }
+                }
+        }
+    }
+
+    private fun getToken(): Pair<String, String> {
+        try {
+            val request = client.newCall(GET("$baseUrl/animes")).execute()
+            val document = request.asJsoup()
+            val token = document.selectFirst("[name=\"_token\"]")?.attr("value").orEmpty()
+            val xsrfToken = client.cookieJar.loadForRequest("$baseUrl/animes".toHttpUrl())
+                .firstOrNull { it.name == "XSRF-TOKEN" }?.let { "${it.name}=${it.value}" }
+                .orEmpty()
+            return token to xsrfToken
+        } catch (e: Exception) {
+            Log.i("bruh err", e.toString())
+            return "" to ""
+        }
+    }
+
+    override fun popularAnimeRequest(page: Int): Request {
+        val (token, xsrfToken) = getToken()
+        val data = FormBody.Builder()
+            .add("_token", token)
+            .add("page", "$page")
+            .add("search_genero", "0")
+            .add("search_anno", "0")
+            .add("search_tipo", "0")
+            .add("search_orden", "0")
+            .add("search_estado", "0")
+            .add("Cookie", xsrfToken)
+            .build()
+
+        return POST("$baseUrl/animes", body = data, headers = headers)
+    }
+
+    override fun popularAnimeParse(response: Response): AnimesPage {
+        val document = response.asJsoup()
+        val elements = document.select(".row [data-original-title]")
+        val nextPage = document.select(".pagination a[rel=next]").any()
+        val animeList = elements.map { element ->
+            SAnime.create().apply {
+                title = element.selectFirst(".font-GDSherpa-Bold")?.text().orEmpty()
+                thumbnail_url = element.selectFirst("img")?.getImageUrl()
+                setUrlWithoutDomain(element.attr("abs:href"))
+            }
+        }
+        return AnimesPage(animeList, nextPage)
+    }
+
+    override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException()
+
+    override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException()
+
+    override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
+        val params = OtakuversoFilters.getSearchParameters(filters)
+        return when {
+            query.isNotBlank() -> GET("$baseUrl/buscador?q=$query&page=$page", headers)
+            params.isFiltered() -> searchRequest(params, page)
+            else -> popularAnimeRequest(page)
+        }
+    }
+
+    private fun searchRequest(params: OtakuversoFilters.FilterSearchParams, page: Int): Request {
+        val formBody = params.body
+        val (token, xsrfToken) = getToken()
+        val data = FormBody.Builder().apply {
+            for (i in 0 until formBody.size) {
+                add(formBody.name(i), formBody.value(i))
+            }
+            add("page", "$page")
+            add("_token", token)
+            add("Cookie", xsrfToken)
+        }.build()
+
+        return POST("$baseUrl/animes", body = data, headers = headers)
+    }
+
+    override fun searchAnimeParse(response: Response) = popularAnimeParse(response)
+
+    private fun parseEpisodeList(document: Document): List<SEpisode> {
+        return document.select(".pl-lg-4 .container-fluid .row .col-6.text-center").map {
+            val episode = it.select(".font-GDSherpa-Bold a")
+            val episodeNumber = episode.text().substringAfter("Episodio").trim().toFloat()
+            SEpisode.create().apply {
+                name = episode.text()
+                episode_number = episodeNumber
+                scanlator = it.select(".font14 .bog").text().trim()
+                setUrlWithoutDomain(episode.attr("abs:href"))
+            }
+        }
+    }
+
+    override fun episodeListParse(response: Response): List<SEpisode> {
+        val document = response.asJsoup()
+        val pageable = document.select(".dropdown-menu").any()
+        if (pageable) {
+            return document.select(".dropdown-menu a")
+                .map { it.attr("abs:href") }
+                .parallelCatchingFlatMapBlocking {
+                    val page = client.newCall(GET(it)).execute().asJsoup()
+                    parseEpisodeList(page)
+                }
+        }
+        return parseEpisodeList(document)
+    }
+
+    override suspend fun getVideoList(episode: SEpisode): List<Video> {
+        val response = client.newCall(videoListRequest(episode)).await()
+        val document = response.asJsoup()
+        return document.select("#ssel option")
+            .map { it.attr("value") }
+            .parallelCatchingFlatMap { id ->
+                val url = getRealLink(id)
+                serverVideoResolver(url)
+            }
+    }
+
+    private fun getRealLink(id: String): String {
+        val serverResponse = client.newCall(GET("$baseUrl/play-video?id=$id")).execute()
+        val serverLink = """"url":"([^"]+)""".toRegex()
+            .find(serverResponse.body.string())
+            ?.groupValues?.get(1)
+            ?.replace("\\/", "/")
+            .orEmpty()
+        return when {
+            serverLink.startsWith("http") -> serverLink
+            serverLink.startsWith("//") -> "https:$serverLink"
+            else -> ""
+        }
+    }
+
+    override fun getFilterList(): AnimeFilterList = OtakuversoFilters.FILTER_LIST
+
+    /*-------------------------------- Video extractors ------------------------------------*/
+    private val universalExtractor by lazy { UniversalExtractor(client) }
+    private val voeExtractor by lazy { VoeExtractor(client) }
+    private val okruExtractor by lazy { OkruExtractor(client) }
+    private val filemoonExtractor by lazy { FilemoonExtractor(client) }
+    private val uqloadExtractor by lazy { UqloadExtractor(client) }
+    private val mp4uploadExtractor by lazy { Mp4uploadExtractor(client) }
+    private val streamwishExtractor by lazy { StreamWishExtractor(client, headers) }
+    private val doodExtractor by lazy { DoodExtractor(client) }
+    private val streamlareExtractor by lazy { StreamlareExtractor(client) }
+    private val yourUploadExtractor by lazy { YourUploadExtractor(client) }
+    private val burstcloudExtractor by lazy { BurstCloudExtractor(client) }
+    private val upstreamExtractor by lazy { UpstreamExtractor(client) }
+    private val streamTapeExtractor by lazy { StreamTapeExtractor(client) }
+    private val streamHideVidExtractor by lazy { StreamHideVidExtractor(client, headers) }
+    private val filelionsExtractor by lazy { StreamWishExtractor(client, headers) }
+    private val sendvidExtractor by lazy { SendvidExtractor(client, headers) }
+    private val luluExtractor by lazy { UnpackerExtractor(client, headers) }
+
+    private fun serverVideoResolver(url: String): List<Video> {
+        return when {
+            arrayOf("voe", "robertordercharacter", "donaldlineelse").any(url) -> voeExtractor.videosFromUrl(url)
+            arrayOf("ok.ru", "okru").any(url) -> okruExtractor.videosFromUrl(url)
+            arrayOf("moon").any(url) -> filemoonExtractor.videosFromUrl(url, prefix = "Filemoon:")
+            arrayOf("uqload").any(url) -> uqloadExtractor.videosFromUrl(url)
+            arrayOf("mp4upload").any(url) -> mp4uploadExtractor.videosFromUrl(url, headers)
+            arrayOf("wish").any(url) -> streamwishExtractor.videosFromUrl(url, videoNameGen = { "StreamWish:$it" })
+            arrayOf("doodstream", "dood.").any(url) -> doodExtractor.videosFromUrl(url, "DoodStream")
+            arrayOf("streamlare").any(url) -> streamlareExtractor.videosFromUrl(url)
+            arrayOf("yourupload", "upload").any(url) -> yourUploadExtractor.videoFromUrl(url, headers = headers)
+            arrayOf("burstcloud", "burst").any(url) -> burstcloudExtractor.videoFromUrl(url, headers = headers)
+            arrayOf("upstream").any(url) -> upstreamExtractor.videosFromUrl(url)
+            arrayOf("streamtape", "stp", "stape").any(url) -> streamTapeExtractor.videosFromUrl(url)
+            arrayOf("ahvsh", "streamhide").any(url) -> streamHideVidExtractor.videosFromUrl(url)
+            arrayOf("/stream/fl.php").any(url) -> {
+                val video = url.substringAfter("/stream/fl.php?v=")
+                if (client.newCall(GET(video)).execute().code == 200) {
+                    listOf(Video(video, "FireLoad", video))
+                } else {
+                    emptyList()
+                }
+            }
+            arrayOf("lion").any(url) -> filelionsExtractor.videosFromUrl(url, videoNameGen = { "FileLions:$it" })
+            arrayOf("sendvid").any(url) -> sendvidExtractor.videosFromUrl(url)
+            arrayOf("lulu").any(url) -> luluExtractor.videosFromUrl(url)
+            else -> universalExtractor.videosFromUrl(url, headers)
+        }
+    }
+
+    override fun List<Video>.sort(): List<Video> {
+        val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!
+        val server = preferences.getString(PREF_SERVER_KEY, PREF_SERVER_DEFAULT)!!
+        return this.sortedWith(
+            compareBy(
+                { it.quality.contains(server, true) },
+                { it.quality.contains(quality) },
+                { Regex("""(\d+)p""").find(it.quality)?.groupValues?.get(1)?.toIntOrNull() ?: 0 },
+            ),
+        ).reversed()
+    }
+
+    private fun Element.getImageUrl(): String? {
+        return when {
+            isValidUrl("data-src") -> attr("abs:data-src")
+            isValidUrl("data-lazy-src") -> attr("abs:data-lazy-src")
+            isValidUrl("srcset") -> attr("abs:srcset").substringBefore(" ")
+            isValidUrl("src") -> attr("abs:src")
+            else -> ""
+        }
+    }
+
+    private fun Element.isValidUrl(attrName: String): Boolean {
+        if (!hasAttr(attrName)) return false
+        return !attr(attrName).contains("data:image/")
+    }
+
+    private fun Array<String>.any(url: String): Boolean = this.any { url.contains(it, ignoreCase = true) }
+
+    override fun setupPreferenceScreen(screen: PreferenceScreen) {
+        ListPreference(screen.context).apply {
+            key = PREF_SERVER_KEY
+            title = "Preferred server"
+            entries = SERVER_LIST
+            entryValues = SERVER_LIST
+            setDefaultValue(PREF_SERVER_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)
+
+        ListPreference(screen.context).apply {
+            key = PREF_QUALITY_KEY
+            title = "Preferred quality"
+            entries = QUALITY_LIST
+            entryValues = QUALITY_LIST
+            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)
+    }
+}
diff --git a/src/es/otakuverso/src/eu/kanade/tachiyomi/animeextension/es/otakuverso/OtakuversoFilters.kt b/src/es/otakuverso/src/eu/kanade/tachiyomi/animeextension/es/otakuverso/OtakuversoFilters.kt
new file mode 100644
index 00000000..073c4488
--- /dev/null
+++ b/src/es/otakuverso/src/eu/kanade/tachiyomi/animeextension/es/otakuverso/OtakuversoFilters.kt
@@ -0,0 +1,143 @@
+package eu.kanade.tachiyomi.animeextension.es.otakuverso
+
+import eu.kanade.tachiyomi.animesource.model.AnimeFilter
+import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
+import okhttp3.FormBody
+import java.util.Calendar
+
+object OtakuversoFilters {
+    open class QueryPartFilter(displayName: String, val vals: Array<Pair<String, String>>) : AnimeFilter.Select<String>(
+        displayName,
+        vals.map { it.first }.toTypedArray(),
+    )
+
+    private inline fun <reified R> AnimeFilterList.getFirst(): R {
+        return this.filterIsInstance<R>().first()
+    }
+
+    data class FilterSearchParams(
+        val body: FormBody,
+    ) {
+        fun isFiltered(): Boolean {
+            return (0 until body.size).any { body.value(it) != "0" }
+        }
+    }
+
+    internal fun getSearchParameters(filters: AnimeFilterList): FilterSearchParams {
+        if (filters.isEmpty()) return FilterSearchParams(FormBody.Builder().build())
+
+        val formBuilder = FormBody.Builder()
+        filters.getFirst<GenresFilter>().let { filter ->
+            formBuilder.add("search_genero", filter.vals[filter.state].second)
+        }
+        filters.getFirst<TypesFilter>().let { filter ->
+            formBuilder.add("search_tipo", filter.vals[filter.state].second)
+        }
+        filters.getFirst<StatusFilter>().let { filter ->
+            formBuilder.add("search_estado", filter.vals[filter.state].second)
+        }
+        filters.getFirst<YearsFilter>().let { filter ->
+            formBuilder.add("search_anno", filter.vals[filter.state].second)
+        }
+        filters.getFirst<SortFilter>().let { filter ->
+            formBuilder.add("search_orden", filter.vals[filter.state].second)
+        }
+        return FilterSearchParams(formBuilder.build())
+    }
+
+    val FILTER_LIST get() = AnimeFilterList(
+        AnimeFilter.Header("La busqueda por texto ignora el filtro"),
+        GenresFilter(),
+        TypesFilter(),
+        StatusFilter(),
+        YearsFilter(),
+        SortFilter(),
+    )
+
+    class GenresFilter : QueryPartFilter("Género", OtakuversoFiltersData.GENRES)
+
+    class TypesFilter : QueryPartFilter("Tipo", OtakuversoFiltersData.TYPES)
+
+    class StatusFilter : QueryPartFilter("Estado", OtakuversoFiltersData.STATUS)
+
+    class YearsFilter : QueryPartFilter("Año", OtakuversoFiltersData.YEARS)
+
+    class SortFilter : QueryPartFilter("Orden", OtakuversoFiltersData.SORT)
+
+    private object OtakuversoFiltersData {
+        val GENRES = arrayOf(
+            Pair("Todos", "0"),
+            Pair("Aventura", "jR"),
+            Pair("Misterio", "k5"),
+            Pair("Shounen", "l5"),
+            Pair("Acción", "mO"),
+            Pair("Fantasía", "nR"),
+            Pair("Demonios", "oj"),
+            Pair("Histórico", "p2"),
+            Pair("Sobrenatural", "q2"),
+            Pair("Artes Marciales", "rE"),
+            Pair("Comedia", "vm"),
+            Pair("Superpoderes", "wR"),
+            Pair("Magia", "x9"),
+            Pair("Deportes", "y7"),
+            Pair("Drama", "zY"),
+            Pair("Escolares", "AO"),
+            Pair("Ciencia Ficción", "BX"),
+            Pair("Horror", "Dx"),
+            Pair("Psicológico", "Ev"),
+            Pair("Juegos", "G7"),
+            Pair("Romance", "J2"),
+            Pair("Seinen", "KR"),
+            Pair("Recuentos de la vida", "Lw"),
+            Pair("Mecha", "MA"),
+            Pair("Shoujo", "N6"),
+            Pair("Policía", "Op"),
+            Pair("Suspenso", "Pw"),
+            Pair("Música", "Ql"),
+            Pair("Parodia", "Rq"),
+            Pair("Ecchi", "VM"),
+            Pair("Terror", "WJ"),
+            Pair("Militar", "XW"),
+            Pair("Vampiros", "YK"),
+            Pair("Samurai", "ZJ"),
+            Pair("Infantil", "1R"),
+            Pair("Harem", "2K"),
+            Pair("Escuela", "3M"),
+            Pair("Carreras", "41"),
+            Pair("Lucha", "5B"),
+            Pair("Gore", "6n"),
+            Pair("Latino", "7j"),
+            Pair("Fútbol", "8m"),
+            Pair("Espacial", "9x"),
+            Pair("Josei", "0v"),
+            Pair("Comida", "gJY"),
+            Pair("School", "jRR"),
+            Pair("Yuri", "kR5"),
+            Pair("Yaoi", "lY5"),
+            Pair("Shounen Ai", "mZO"),
+        )
+
+        val TYPES = arrayOf(
+            Pair("Todos", "0"),
+            Pair("Serie", "1"),
+            Pair("Película", "2"),
+            Pair("Especial", "3"),
+            Pair("OVA", "4"),
+        )
+
+        val STATUS = arrayOf(
+            Pair("Todos", "0"),
+            Pair("Emitiendose", "1"),
+            Pair("Próximo", "2"),
+            Pair("Finalizado", "3"),
+        )
+
+        val YEARS = arrayOf(Pair("Todos", "0")) + (1980..Calendar.getInstance().get(Calendar.YEAR)).map { Pair("$it", "$it") }.reversed().toTypedArray()
+
+        val SORT = arrayOf(
+            Pair("Default", "0"),
+            Pair("Ascendente", "1"),
+            Pair("Descendente", "2"),
+        )
+    }
+}
diff --git a/src/es/otakuverso/src/eu/kanade/tachiyomi/animeextension/es/otakuverso/extractors/UnpackerExtractor.kt b/src/es/otakuverso/src/eu/kanade/tachiyomi/animeextension/es/otakuverso/extractors/UnpackerExtractor.kt
new file mode 100644
index 00000000..5555e497
--- /dev/null
+++ b/src/es/otakuverso/src/eu/kanade/tachiyomi/animeextension/es/otakuverso/extractors/UnpackerExtractor.kt
@@ -0,0 +1,31 @@
+package eu.kanade.tachiyomi.animeextension.es.otakuverso.extractors
+
+import dev.datlag.jsunpacker.JsUnpacker
+import eu.kanade.tachiyomi.animesource.model.Video
+import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.util.asJsoup
+import okhttp3.Headers
+import okhttp3.OkHttpClient
+
+class UnpackerExtractor(private val client: OkHttpClient, private val headers: Headers) {
+    private val playlistUtils by lazy { PlaylistUtils(client, headers) }
+
+    fun videosFromUrl(url: String): List<Video> {
+        val doc = client.newCall(GET(url, headers)).execute()
+            .asJsoup()
+
+        val script = doc.selectFirst("script:containsData(eval)")
+            ?.data()
+            ?.let(JsUnpacker::unpackAndCombine)
+            ?: return emptyList()
+
+        val playlistUrl = script.substringAfter("file:\"").substringBefore('"')
+
+        return playlistUtils.extractFromHls(
+            playlistUrl,
+            referer = playlistUrl,
+            videoNameGen = { "Lulu:$it" },
+        )
+    }
+}
diff --git a/src/fr/animesama/res/web_hi_res_512.png b/src/fr/animesama/res/web_hi_res_512.png
deleted file mode 100644
index ebaf597e..00000000
Binary files a/src/fr/animesama/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/fr/empirestreaming/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/src/fr/empirestreaming/res/mipmap-hdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 8dc560dd..00000000
Binary files a/src/fr/empirestreaming/res/mipmap-hdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/fr/empirestreaming/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/src/fr/empirestreaming/res/mipmap-hdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 6b3ec01b..00000000
Binary files a/src/fr/empirestreaming/res/mipmap-hdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/fr/empirestreaming/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/src/fr/empirestreaming/res/mipmap-mdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index f8feb6e5..00000000
Binary files a/src/fr/empirestreaming/res/mipmap-mdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/fr/empirestreaming/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/src/fr/empirestreaming/res/mipmap-mdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 4af4a29a..00000000
Binary files a/src/fr/empirestreaming/res/mipmap-mdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/fr/empirestreaming/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/src/fr/empirestreaming/res/mipmap-xhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 1b560124..00000000
Binary files a/src/fr/empirestreaming/res/mipmap-xhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/fr/empirestreaming/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/src/fr/empirestreaming/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 93321f34..00000000
Binary files a/src/fr/empirestreaming/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/fr/empirestreaming/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/src/fr/empirestreaming/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index 369383ac..00000000
Binary files a/src/fr/empirestreaming/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/fr/empirestreaming/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/src/fr/empirestreaming/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 06a62196..00000000
Binary files a/src/fr/empirestreaming/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/fr/empirestreaming/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/src/fr/empirestreaming/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png
deleted file mode 100644
index de26e98f..00000000
Binary files a/src/fr/empirestreaming/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png and /dev/null differ
diff --git a/src/fr/empirestreaming/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/src/fr/empirestreaming/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png
deleted file mode 100644
index 7cad125f..00000000
Binary files a/src/fr/empirestreaming/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png and /dev/null differ
diff --git a/src/fr/frenchanime/res/web_hi_res_512.png b/src/fr/frenchanime/res/web_hi_res_512.png
deleted file mode 100644
index 0089d6ef..00000000
Binary files a/src/fr/frenchanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/fr/jetanime/res/web_hi_res_512.png b/src/fr/jetanime/res/web_hi_res_512.png
deleted file mode 100644
index b219ab1b..00000000
Binary files a/src/fr/jetanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/fr/mykdrama/res/web_hi_res_512.png b/src/fr/mykdrama/res/web_hi_res_512.png
deleted file mode 100644
index 579972f1..00000000
Binary files a/src/fr/mykdrama/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/fr/otakufr/res/web_hi_res_512.png b/src/fr/otakufr/res/web_hi_res_512.png
deleted file mode 100644
index d992179a..00000000
Binary files a/src/fr/otakufr/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/fr/wiflix/res/web_hi_res_512.png b/src/fr/wiflix/res/web_hi_res_512.png
deleted file mode 100644
index 1aacf919..00000000
Binary files a/src/fr/wiflix/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/hi/animesaga/build.gradle b/src/hi/animesaga/build.gradle
index 1da6278d..bcfeeaa0 100644
--- a/src/hi/animesaga/build.gradle
+++ b/src/hi/animesaga/build.gradle
@@ -3,7 +3,7 @@ ext {
     extClass = '.AniSAGA'
     themePkg = 'dooplay'
     baseUrl = 'https://www.anisaga.org'
-    overrideVersionCode = 15
+    overrideVersionCode = 16
     isNsfw = false
 }
 
diff --git a/src/hi/animesaga/src/eu/kanade/tachiyomi/animeextension/hi/animesaga/AniSAGA.kt b/src/hi/animesaga/src/eu/kanade/tachiyomi/animeextension/hi/animesaga/AniSAGA.kt
index c9e15245..6c077aed 100644
--- a/src/hi/animesaga/src/eu/kanade/tachiyomi/animeextension/hi/animesaga/AniSAGA.kt
+++ b/src/hi/animesaga/src/eu/kanade/tachiyomi/animeextension/hi/animesaga/AniSAGA.kt
@@ -14,7 +14,7 @@ class AniSAGA : DooPlay(
     "AniSAGA",
     "https://www.anisaga.org",
 ) {
-    private val videoHost = "https://cdn.anisaga.org"
+    private val videoHost = "https://plyrxcdn.site/"
 
     // ============================== Popular ===============================
     override fun popularAnimeSelector() = "div.top-imdb-list > div.top-imdb-item"
diff --git a/src/hi/yomovies/res/web_hi_res_512.png b/src/hi/yomovies/res/web_hi_res_512.png
deleted file mode 100644
index d8cce433..00000000
Binary files a/src/hi/yomovies/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/id/kuramanime/res/web_hi_res_512.png b/src/id/kuramanime/res/web_hi_res_512.png
deleted file mode 100644
index 8f1628be..00000000
Binary files a/src/id/kuramanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/id/kuronime/res/web_hi_res_512.png b/src/id/kuronime/res/web_hi_res_512.png
deleted file mode 100644
index a469dc18..00000000
Binary files a/src/id/kuronime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/id/minioppai/res/web_hi_res_512.png b/src/id/minioppai/res/web_hi_res_512.png
deleted file mode 100644
index 06ca48d3..00000000
Binary files a/src/id/minioppai/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/id/neonime/res/web_hi_res_128.png b/src/id/neonime/res/web_hi_res_128.png
deleted file mode 100644
index 170b0247..00000000
Binary files a/src/id/neonime/res/web_hi_res_128.png and /dev/null differ
diff --git a/src/id/oploverz/res/web_hi_res_512.png b/src/id/oploverz/res/web_hi_res_512.png
deleted file mode 100644
index f6e7473a..00000000
Binary files a/src/id/oploverz/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/id/otakudesu/res/web_hi_res_512.png b/src/id/otakudesu/res/web_hi_res_512.png
deleted file mode 100644
index fe706242..00000000
Binary files a/src/id/otakudesu/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/id/samehadaku/res/web_hi_res_512.png b/src/id/samehadaku/res/web_hi_res_512.png
deleted file mode 100644
index b8a3e6a8..00000000
Binary files a/src/id/samehadaku/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/it/animeunity/res/web_hi_res_512.png b/src/it/animeunity/res/web_hi_res_512.png
deleted file mode 100644
index 005a0666..00000000
Binary files a/src/it/animeunity/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/it/animeworld/res/play_store_512.png b/src/it/animeworld/res/play_store_512.png
deleted file mode 100644
index 470fb01b..00000000
Binary files a/src/it/animeworld/res/play_store_512.png and /dev/null differ
diff --git a/src/it/streamingcommunity/res/web_hi_res_512.png b/src/it/streamingcommunity/res/web_hi_res_512.png
deleted file mode 100644
index bb51a179..00000000
Binary files a/src/it/streamingcommunity/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/it/toonitalia/res/web_hi_res_512.png b/src/it/toonitalia/res/web_hi_res_512.png
deleted file mode 100644
index bb20f995..00000000
Binary files a/src/it/toonitalia/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/it/vvvvid/res/web_hi_res_512.png b/src/it/vvvvid/res/web_hi_res_512.png
deleted file mode 100644
index 2b0c990f..00000000
Binary files a/src/it/vvvvid/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/ko/aniweek/res/web_hi_res_512.png b/src/ko/aniweek/res/web_hi_res_512.png
deleted file mode 100644
index c4fb09a4..00000000
Binary files a/src/ko/aniweek/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/pl/desuonline/res/web_hi_res_512.png b/src/pl/desuonline/res/web_hi_res_512.png
deleted file mode 100644
index 641868dd..00000000
Binary files a/src/pl/desuonline/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/pl/wbijam/res/web_hi_res_512.png b/src/pl/wbijam/res/web_hi_res_512.png
deleted file mode 100644
index 6da98071..00000000
Binary files a/src/pl/wbijam/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/pt/anidong/AndroidManifest.xml b/src/pt/anidong/AndroidManifest.xml
deleted file mode 100644
index 2970f0d2..00000000
--- a/src/pt/anidong/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.anidong.AniDongUrlActivity"
-            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="anidong.net"
-                    android:pathPattern="/anime/..*"
-                    android:scheme="https" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/src/pt/anidong/build.gradle b/src/pt/anidong/build.gradle
deleted file mode 100644
index 57fb4d05..00000000
--- a/src/pt/anidong/build.gradle
+++ /dev/null
@@ -1,7 +0,0 @@
-ext {
-    extName = 'AniDong'
-    extClass = '.AniDong'
-    extVersionCode = 2
-}
-
-apply from: "$rootDir/common.gradle"
diff --git a/src/pt/anidong/res/mipmap-hdpi/ic_launcher.png b/src/pt/anidong/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index 50be877d..00000000
Binary files a/src/pt/anidong/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/anidong/res/mipmap-mdpi/ic_launcher.png b/src/pt/anidong/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index b23fff3a..00000000
Binary files a/src/pt/anidong/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/anidong/res/mipmap-xhdpi/ic_launcher.png b/src/pt/anidong/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index 71ddb7b8..00000000
Binary files a/src/pt/anidong/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/anidong/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/anidong/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index 720b33eb..00000000
Binary files a/src/pt/anidong/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/anidong/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/anidong/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index a0cb538f..00000000
Binary files a/src/pt/anidong/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/AniDong.kt b/src/pt/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/AniDong.kt
deleted file mode 100644
index ea22f1d3..00000000
--- a/src/pt/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/AniDong.kt
+++ /dev/null
@@ -1,264 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.anidong
-
-import eu.kanade.tachiyomi.animeextension.pt.anidong.dto.EpisodeDto
-import eu.kanade.tachiyomi.animeextension.pt.anidong.dto.EpisodeListDto
-import eu.kanade.tachiyomi.animeextension.pt.anidong.dto.SearchResultDto
-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.network.GET
-import eu.kanade.tachiyomi.network.POST
-import eu.kanade.tachiyomi.network.awaitSuccess
-import eu.kanade.tachiyomi.util.asJsoup
-import kotlinx.serialization.json.Json
-import okhttp3.FormBody
-import okhttp3.Request
-import okhttp3.Response
-import org.jsoup.nodes.Document
-import org.jsoup.nodes.Element
-import uy.kohesive.injekt.injectLazy
-
-class AniDong : ParsedAnimeHttpSource() {
-
-    override val name = "AniDong"
-
-    override val baseUrl = "https://anidong.net"
-
-    override val lang = "pt-BR"
-
-    override val supportsLatest = true
-
-    private val json: Json by injectLazy()
-
-    private val apiHeaders by lazy {
-        headersBuilder() // sets user-agent
-            .add("Referer", baseUrl)
-            .add("x-requested-with", "XMLHttpRequest")
-            .build()
-    }
-
-    // ============================== Popular ===============================
-    override fun popularAnimeRequest(page: Int) = GET(baseUrl)
-
-    override fun popularAnimeSelector() = "article.top10_animes_item > a"
-
-    override fun popularAnimeFromElement(element: Element) = SAnime.create().apply {
-        setUrlWithoutDomain(element.attr("href"))
-        title = element.attr("title")
-        thumbnail_url = element.selectFirst("img")?.attr("src")
-    }
-
-    override fun popularAnimeNextPageSelector() = null
-
-    // =============================== Latest ===============================
-    override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/lancamentos/page/$page/")
-
-    override fun latestUpdatesSelector() = "article.main_content_article > a"
-
-    override fun latestUpdatesFromElement(element: Element) = popularAnimeFromElement(element)
-
-    override fun latestUpdatesNextPageSelector() = "div.paginacao > a.next"
-
-    // =============================== 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.asJsoup()).apply {
-            setUrlWithoutDomain(response.request.url.toString())
-            initialized = true
-        }
-
-        return AnimesPage(listOf(details), false)
-    }
-
-    override fun getFilterList() = AniDongFilters.FILTER_LIST
-
-    private val nonce by lazy {
-        client.newCall(GET("$baseUrl/?js_global=1&ver=6.2.2")).execute()
-            .body.string()
-            .substringAfter("search_nonce")
-            .substringAfter("'")
-            .substringBefore("'")
-    }
-
-    override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
-        val params = AniDongFilters.getSearchParameters(filters)
-
-        val body = FormBody.Builder()
-            .add("letra", "")
-            .add("action", "show_animes_ajax")
-            .add("nome", query)
-            .add("status", params.status)
-            .add("formato", params.format)
-            .add("search_nonce", nonce)
-            .add("paged", page.toString())
-            .apply {
-                params.genres.forEach { add("generos[]", it) }
-            }.build()
-
-        return POST("$baseUrl/wp-admin/admin-ajax.php", headers = apiHeaders, body = body)
-    }
-
-    override fun searchAnimeParse(response: Response): AnimesPage {
-        val searchData: SearchResultDto = response.body.string()
-            .takeIf { it.trim() != "402" }
-            ?.let(json::decodeFromString)
-            ?: return AnimesPage(emptyList(), false)
-
-        val animes = searchData.animes.map {
-            SAnime.create().apply {
-                setUrlWithoutDomain(it.url)
-                title = it.title
-                thumbnail_url = it.thumbnail_url
-            }
-        }
-
-        val hasNextPage = searchData.pages > 1 && searchData.animes.size == 10
-
-        return AnimesPage(animes, hasNextPage)
-    }
-
-    override fun searchAnimeSelector(): String {
-        throw UnsupportedOperationException()
-    }
-
-    override fun searchAnimeFromElement(element: Element): SAnime {
-        throw UnsupportedOperationException()
-    }
-
-    override fun searchAnimeNextPageSelector(): String? {
-        throw UnsupportedOperationException()
-    }
-
-    // =========================== Anime Details ============================
-    override fun animeDetailsParse(document: Document) = SAnime.create().apply {
-        val doc = getRealDoc(document)
-        val infos = doc.selectFirst("div.anime_infos")!!
-
-        setUrlWithoutDomain(doc.location())
-        title = infos.selectFirst("div > h3")!!.ownText()
-        thumbnail_url = infos.selectFirst("img")?.attr("src")
-        genre = infos.select("div[itemprop=genre] a").eachText().joinToString()
-        artist = infos.selectFirst("div[itemprop=productionCompany]")?.text()
-
-        status = doc.selectFirst("div:contains(Status) span")?.text().let {
-            when {
-                it == null -> SAnime.UNKNOWN
-                it == "Completo" -> SAnime.COMPLETED
-                it.contains("Lançamento") -> SAnime.ONGOING
-                else -> SAnime.UNKNOWN
-            }
-        }
-
-        description = buildString {
-            infos.selectFirst("div.anime_name + div.anime_info")?.text()?.also {
-                append("Nomes alternativos: $it\n")
-            }
-
-            doc.selectFirst("div[itemprop=description]")?.text()?.also {
-                append("\n$it")
-            }
-        }
-    }
-
-    // ============================== Episodes ==============================
-    override fun episodeListSelector(): String {
-        throw UnsupportedOperationException()
-    }
-
-    override fun episodeFromElement(element: Element): SEpisode {
-        throw UnsupportedOperationException()
-    }
-
-    override fun episodeListParse(response: Response): List<SEpisode> {
-        val doc = getRealDoc(response.asJsoup())
-
-        val id = doc.selectFirst("link[rel=shortlink]")!!.attr("href").substringAfter("=")
-        val body = FormBody.Builder()
-            .add("action", "show_videos")
-            .add("anime_id", id)
-            .build()
-
-        val res = client.newCall(POST("$baseUrl/api", apiHeaders, body)).execute()
-            .body.string()
-        val data = json.decodeFromString<EpisodeListDto>(res)
-
-        return buildList {
-            data.episodes.forEach { add(episodeFromObject(it, "Episódio")) }
-            data.movies.forEach { add(episodeFromObject(it, "Filme")) }
-            data.ovas.forEach { add(episodeFromObject(it, "OVA")) }
-            sortByDescending { it.episode_number }
-        }
-    }
-
-    private fun episodeFromObject(episode: EpisodeDto, prefix: String) = SEpisode.create().apply {
-        setUrlWithoutDomain(episode.epi_url)
-        episode_number = episode.epi_num.toFloatOrNull() ?: 0F
-        name = "$prefix ${episode.epi_num}"
-    }
-
-    // ============================ Video Links =============================
-    override fun videoListParse(response: Response): List<Video> {
-        val doc = response.asJsoup()
-        return doc.select("div.player_option").flatMap {
-            val url = it.attr("data-playerlink")
-            val playerName = it.text().trim()
-            videosFromUrl(url, playerName)
-        }
-    }
-
-    private fun videosFromUrl(url: String, playerName: String): List<Video> {
-        val scriptData = client.newCall(GET(url, apiHeaders)).execute()
-            .asJsoup()
-            .selectFirst("script:containsData(sources)")
-            ?.data() ?: return emptyList()
-
-        return scriptData.substringAfter("sources: [").substringBefore("]")
-            .split("{")
-            .drop(1)
-            .map {
-                val videoUrl = it.substringAfter("file: \"").substringBefore('"')
-                val label = it.substringAfter("label: \"", "Unknown").substringBefore('"')
-                val quality = "$playerName - $label"
-                Video(videoUrl, quality, videoUrl, headers = apiHeaders)
-            }
-    }
-
-    override fun videoFromElement(element: Element): Video {
-        throw UnsupportedOperationException()
-    }
-
-    override fun videoListSelector(): String {
-        throw UnsupportedOperationException()
-    }
-
-    override fun videoUrlParse(document: Document): String {
-        throw UnsupportedOperationException()
-    }
-
-    // ============================= Utilities ==============================
-    private fun getRealDoc(document: Document): Document {
-        if (!document.location().contains("/video/")) return document
-
-        return document.selectFirst(".episodioControleItem:has(i.ri-grid-fill)")?.let {
-            client.newCall(GET(it.attr("href"), headers)).execute()
-                .asJsoup()
-        } ?: document
-    }
-
-    companion object {
-        const val PREFIX_SEARCH = "id:"
-    }
-}
diff --git a/src/pt/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/AniDongFilters.kt b/src/pt/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/AniDongFilters.kt
deleted file mode 100644
index 28f949e8..00000000
--- a/src/pt/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/AniDongFilters.kt
+++ /dev/null
@@ -1,124 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.anidong
-
-import eu.kanade.tachiyomi.animesource.model.AnimeFilter
-import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
-
-object AniDongFilters {
-    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, val pairs: Array<Pair<String, String>>) :
-        AnimeFilter.Group<AnimeFilter.CheckBox>(name, pairs.map { CheckBoxVal(it.first, false) })
-
-    private class CheckBoxVal(name: String, state: Boolean = false) : AnimeFilter.CheckBox(name, state)
-
-    private inline fun <reified R> AnimeFilterList.asQueryPart(): String {
-        return (getFirst<R>() as QueryPartFilter).toQueryPart()
-    }
-
-    private inline fun <reified R> AnimeFilterList.getFirst(): R {
-        return first { it is R } as R
-    }
-
-    private inline fun <reified R> AnimeFilterList.parseCheckbox(
-        options: Array<Pair<String, String>>,
-    ): List<String> {
-        return (getFirst<R>() as CheckBoxFilterList).state
-            .asSequence()
-            .filter { it.state }
-            .map { checkbox -> options.find { it.first == checkbox.name }!!.second }
-            .filter(String::isNotBlank)
-            .toList()
-    }
-
-    class StatusFilter : QueryPartFilter("Status", AniDongFiltersData.STATUS_LIST)
-    class FormatFilter : QueryPartFilter("Formato", AniDongFiltersData.FORMAT_LIST)
-
-    class GenresFilter : CheckBoxFilterList("Gêneros", AniDongFiltersData.GENRES_LIST)
-
-    val FILTER_LIST get() = AnimeFilterList(
-        StatusFilter(),
-        FormatFilter(),
-        GenresFilter(),
-    )
-
-    data class FilterSearchParams(
-        val status: String = "",
-        val format: String = "",
-        val genres: List<String> = emptyList(),
-    )
-
-    internal fun getSearchParameters(filters: AnimeFilterList): FilterSearchParams {
-        if (filters.isEmpty()) return FilterSearchParams()
-
-        return FilterSearchParams(
-            filters.asQueryPart<StatusFilter>(),
-            filters.asQueryPart<FormatFilter>(),
-            filters.parseCheckbox<GenresFilter>(AniDongFiltersData.GENRES_LIST),
-        )
-    }
-
-    private object AniDongFiltersData {
-        private val SELECT = Pair("<Selecione>", "")
-
-        val STATUS_LIST = arrayOf(
-            SELECT,
-            Pair("Lançamento", "Lançamento"),
-            Pair("Completo", "Completo"),
-        )
-
-        val FORMAT_LIST = arrayOf(
-            SELECT,
-            Pair("Donghua", "Anime"),
-            Pair("Filme", "Filme"),
-        )
-
-        val GENRES_LIST = arrayOf(
-            Pair("Artes Marciais", "9"),
-            Pair("Aventura", "6"),
-            Pair("Ação", "2"),
-            Pair("Boys Love", "43"),
-            Pair("Comédia", "15"),
-            Pair("Corrida", "94"),
-            Pair("Cultivo", "12"),
-            Pair("Demônios", "18"),
-            Pair("Detetive", "24"),
-            Pair("Drama", "16"),
-            Pair("Escolar", "77"),
-            Pair("Espaço", "54"),
-            Pair("Esporte", "95"),
-            Pair("Fantasia", "7"),
-            Pair("Guerra", "26"),
-            Pair("Harém", "17"),
-            Pair("Histórico", "8"),
-            Pair("Horror", "44"),
-            Pair("Isekai", "72"),
-            Pair("Jogo", "25"),
-            Pair("Mecha", "40"),
-            Pair("Militar", "21"),
-            Pair("Mistério", "3"),
-            Pair("Mitolgia", "96"),
-            Pair("Mitologia", "19"),
-            Pair("O Melhor Donghua", "91"),
-            Pair("Polícia", "57"),
-            Pair("Política", "63"),
-            Pair("Psicológico", "33"),
-            Pair("Reencarnação", "30"),
-            Pair("Romance", "11"),
-            Pair("Sci-Fi", "39"),
-            Pair("Slice of Life", "84"),
-            Pair("Sobrenatural", "4"),
-            Pair("Super Poder", "67"),
-            Pair("Suspense", "32"),
-            Pair("Tragédia", "58"),
-            Pair("Vampiro", "82"),
-        )
-    }
-}
diff --git a/src/pt/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/AniDongUrlActivity.kt b/src/pt/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/AniDongUrlActivity.kt
deleted file mode 100644
index 883d9a50..00000000
--- a/src/pt/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/AniDongUrlActivity.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.anidong
-
-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://anidong.net/anime/<item> intents
- * and redirects them to the main Aniyomi process.
- */
-class AniDongUrlActivity : 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 item = pathSegments[1]
-            val mainIntent = Intent().apply {
-                action = "eu.kanade.tachiyomi.ANIMESEARCH"
-                putExtra("query", "${AniDong.PREFIX_SEARCH}$item")
-                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/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/dto/AniDongDto.kt b/src/pt/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/dto/AniDongDto.kt
deleted file mode 100644
index 4945071c..00000000
--- a/src/pt/anidong/src/eu/kanade/tachiyomi/animeextension/pt/anidong/dto/AniDongDto.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.anidong.dto
-
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.builtins.ListSerializer
-import kotlinx.serialization.json.JsonArray
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.JsonObject
-import kotlinx.serialization.json.JsonTransformingSerializer
-
-@Serializable
-data class SearchResultDto(
-    val animes: List<AnimeDto>,
-    @SerialName("total_pages")
-    val pages: Int,
-)
-
-@Serializable
-data class AnimeDto(
-    @SerialName("anime_capa")
-    val thumbnail_url: String,
-    @SerialName("anime_permalink")
-    val url: String,
-    @SerialName("anime_title")
-    val title: String,
-)
-
-@Serializable
-data class EpisodeListDto(
-    @Serializable(with = EpisodeListSerializer::class)
-    @SerialName("episodios")
-    val episodes: List<EpisodeDto>,
-    @Serializable(with = EpisodeListSerializer::class)
-    @SerialName("filmes")
-    val movies: List<EpisodeDto>,
-    @Serializable(with = EpisodeListSerializer::class)
-    val ovas: List<EpisodeDto>,
-)
-
-@Serializable
-data class EpisodeDto(
-    val epi_num: String,
-    val epi_url: String,
-)
-
-object EpisodeListSerializer :
-    JsonTransformingSerializer<List<EpisodeDto>>(ListSerializer(EpisodeDto.serializer())) {
-    override fun transformDeserialize(element: JsonElement): JsonElement =
-        when (element) {
-            is JsonObject -> JsonArray(element.values.toList())
-            else -> JsonArray(emptyList())
-        }
-}
diff --git a/src/pt/animesgratis/build.gradle b/src/pt/animesgratis/build.gradle
index a9f7edf9..8e0c3b14 100644
--- a/src/pt/animesgratis/build.gradle
+++ b/src/pt/animesgratis/build.gradle
@@ -3,7 +3,7 @@ ext {
     extClass = '.Q1N'
     themePkg = 'dooplay'
     baseUrl = 'https://q1n.net'
-    overrideVersionCode = 17
+    overrideVersionCode = 18
 }
 
 apply from: "$rootDir/common.gradle"
diff --git a/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/Q1N.kt b/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/Q1N.kt
index ef9a0bb1..03e410bc 100644
--- a/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/Q1N.kt
+++ b/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/Q1N.kt
@@ -129,6 +129,7 @@ class Q1N : DooPlay(
             "mixdrop" in name -> mixDropExtractor.videoFromUrl(url)
             "streamtape" in name -> streamTapeExtractor.videosFromUrl(url)
             "noa" in name -> noaExtractor.videosFromUrl(url)
+            "mdplayer" in name -> noaExtractor.videosFromUrl(url, "MDPLAYER")
             "/player/" in url -> bloggerExtractor.videosFromUrl(url, headers)
             else -> emptyList()
         }
diff --git a/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/extractors/NoaExtractor.kt b/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/extractors/NoaExtractor.kt
index 5bb5d42c..9755a9a1 100644
--- a/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/extractors/NoaExtractor.kt
+++ b/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/extractors/NoaExtractor.kt
@@ -6,7 +6,7 @@ import okhttp3.Headers
 import okhttp3.OkHttpClient
 
 class NoaExtractor(private val client: OkHttpClient, private val headers: Headers) {
-    fun videosFromUrl(url: String): List<Video> {
+    fun videosFromUrl(url: String, name: String = "NOA"): List<Video> {
         val body = client.newCall(GET(url)).execute()
             .body.string()
 
@@ -16,7 +16,7 @@ class NoaExtractor(private val client: OkHttpClient, private val headers: Header
                     .substringAfter(":\"")
                     .substringBefore('"')
                     .replace("\\", "")
-                listOf(Video(videoUrl, "NOA", videoUrl, headers))
+                listOf(Video(videoUrl, name, videoUrl, headers))
             }
 
             "sources:" in body -> {
@@ -31,7 +31,7 @@ class NoaExtractor(private val client: OkHttpClient, private val headers: Header
                             .substringAfter(":\"")
                             .substringBefore('"')
                             .replace("\\", "")
-                        Video(videoUrl, "NOA - $label", videoUrl, headers)
+                        Video(videoUrl, "$name - $label", videoUrl, headers)
                     }
             }
 
diff --git a/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/extractors/RuplayExtractor.kt b/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/extractors/RuplayExtractor.kt
index 0f6e4a73..aa2bcc52 100644
--- a/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/extractors/RuplayExtractor.kt
+++ b/src/pt/animesgratis/src/eu/kanade/tachiyomi/animeextension/pt/animesgratis/extractors/RuplayExtractor.kt
@@ -15,7 +15,7 @@ class RuplayExtractor(private val client: OkHttpClient) {
             .split(",")
             .map {
                 val videoUrl = it.substringAfter("]")
-                val quality = it.substringAfter("[").substringBefore("]")
+                val quality = it.substringAfter("[", "").substringBefore("]").ifEmpty { "Default" }
                 val headers = Headers.headersOf("Referer", videoUrl)
                 Video(videoUrl, "Ruplay - $quality", videoUrl, headers = headers)
             }
diff --git a/src/pt/anitube/build.gradle b/src/pt/anitube/build.gradle
index d20560a0..9f22f339 100644
--- a/src/pt/anitube/build.gradle
+++ b/src/pt/anitube/build.gradle
@@ -1,7 +1,7 @@
 ext {
     extName = 'Anitube'
     extClass = '.Anitube'
-    extVersionCode = 23
+    extVersionCode = 24
 }
 
 apply from: "$rootDir/common.gradle"
diff --git a/src/pt/anitube/res/web_hi_res_512.png b/src/pt/anitube/res/web_hi_res_512.png
deleted file mode 100644
index a1f94f75..00000000
Binary files a/src/pt/anitube/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeExtractor.kt b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeExtractor.kt
index ddf1dcb4..1736832d 100644
--- a/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeExtractor.kt
+++ b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeExtractor.kt
@@ -1,6 +1,7 @@
 package eu.kanade.tachiyomi.animeextension.pt.anitube.extractors
 
 import android.content.SharedPreferences
+import android.util.Base64
 import android.util.Log
 import eu.kanade.tachiyomi.animesource.model.Video
 import eu.kanade.tachiyomi.network.GET
@@ -14,6 +15,9 @@ import okhttp3.OkHttpClient
 import okhttp3.Request
 import org.jsoup.nodes.Document
 import java.net.ProtocolException
+import java.text.SimpleDateFormat
+import java.util.Calendar
+import java.util.Locale
 
 class AnitubeExtractor(
     private val headers: Headers,
@@ -132,32 +136,86 @@ class AnitubeExtractor(
         return "https://widgets.outbrain.com/outbrain.js"
     }
 
-    private fun getAuthCode(serverUrl: String, thumbUrl: String, link: String): String {
-        var authCode = preferences.getString(PREF_AUTHCODE_KEY, "")!!
+    private fun getAuthCode(serverUrl: String, thumbUrl: String, link: String): String? {
+        try {
+            var authCode = preferences.getString(PREF_AUTHCODE_KEY, "")!!
 
-        if (authCode.isNotBlank()) {
-            Log.d(tag, "AuthCode found in preferences")
+            if (authCode.isNotBlank()) {
+                Log.d(tag, "AuthCode found in preferences")
 
-            val response = checkVideoExists("${serverUrl}$authCode")
+                val authArgs = Base64.decode(authCode.substringAfter("="), Base64.DEFAULT).let(::String)
+                val url = "$serverUrl?$authArgs".toHttpUrl()
 
-            if (response.exists || response.code == 500) {
-                Log.d(tag, "AuthCode is OK")
+                val serverTime =
+                    SimpleDateFormat("M/d/yyyy h:m:s a", Locale.ENGLISH).parse(
+                        url.queryParameter("server_time") ?: "",
+                    )
+
+                val calendar = Calendar.getInstance()
+                serverTime?.let { calendar.setTime(it) }
+
+                url.queryParameter("validminutes")?.toInt()
+                    ?.let { calendar.add(Calendar.MINUTE, it) }
+
+                if (Calendar.getInstance() < calendar) {
+                    Log.d(tag, "AuthCode is OK")
+                    return authCode
+                }
+                Log.d(tag, "AuthCode is invalid")
+            }
+
+            Log.d(tag, "Fetching new authCode")
+
+            val adsUrl = getAdsUrl(serverUrl, thumbUrl, link, headers)
+
+            val adsContent = client.newCall(GET(adsUrl)).execute().body.string()
+
+            val body = FormBody.Builder()
+                .add("category", "client")
+                .add("type", "premium")
+                .add("ad", adsContent)
+                .build()
+
+            val newHeaders = headers.newBuilder()
+                .set("Referer", "https://${SITE_URL.toHttpUrl().host}/")
+                .add("Accept", "*/*")
+                .add("Cache-Control", "no-cache")
+                .add("Pragma", "no-cache")
+                .add("Connection", "keep-alive")
+                .add("Sec-Fetch-Dest", "empty")
+                .add("Sec-Fetch-Mode", "cors")
+                .add("Sec-Fetch-Site", "same-site")
+                .build()
+
+            authCode =
+                client.newCall(POST(ADS_URL, headers = newHeaders, body = body))
+                    .execute()
+                    .body.string()
+                    .substringAfter("\"publicidade\"")
+                    .substringAfter('"')
+                    .substringBefore('"')
+
+            if (authCode.startsWith("?wmsAuthSign=")) {
+                Log.d(tag, "Auth code fetched successfully")
+                preferences.edit().putString(PREF_AUTHCODE_KEY, authCode).commit()
                 return authCode
             }
-            Log.d(tag, "AuthCode is invalid")
+
+            Log.e(
+                tag,
+                "Failed to fetch \"publicidade\" code, the current response: $authCode",
+            )
+        } catch (e: Exception) {
+            Log.e(tag, e.toString())
         }
 
-        Log.d(tag, "Fetching new authCode")
+        preferences.edit().putString(PREF_AUTHCODE_KEY, "").commit()
 
-        val adsUrl = getAdsUrl(serverUrl, thumbUrl, link, headers)
+        return null
+    }
 
-        val adsContent = client.newCall(GET(adsUrl)).execute().body.string()
-
-        val body = FormBody.Builder()
-            .add("category", "client")
-            .add("type", "premium")
-            .add("ad", adsContent)
-            .build()
+    private fun getVideoToken(videoUrl: String, authCode: String?): String {
+        val token = authCode ?: "undefined"
 
         val newHeaders = headers.newBuilder()
             .set("Referer", "https://${SITE_URL.toHttpUrl().host}/")
@@ -170,27 +228,10 @@ class AnitubeExtractor(
             .add("Sec-Fetch-Site", "same-site")
             .build()
 
-        val publicidade =
-            client.newCall(POST(ADS_URL, headers = newHeaders, body = body))
-                .execute()
-                .body.string()
-                .substringAfter("\"publicidade\"")
-                .substringAfter('"')
-                .substringBefore('"')
-
-        if (publicidade.isBlank()) {
-            Log.e(
-                tag,
-                "Failed to fetch \"publicidade\" code, the current response: $publicidade",
-            )
-
-            throw Exception("Por favor, abra o vídeo uma vez no navegador para liberar o IP")
-        }
-
-        authCode =
+        val videoToken =
             client.newCall(
                 GET(
-                    "$ADS_URL?token=$publicidade",
+                    "$ADS_URL?token=$token&url=$videoUrl",
                     headers = newHeaders,
                 ),
             )
@@ -200,25 +241,25 @@ class AnitubeExtractor(
                 .substringAfter('"')
                 .substringBefore('"')
 
-        if (authCode.startsWith("?")) {
-            Log.d(tag, "Auth code fetched successfully")
-            preferences.edit().putString(PREF_AUTHCODE_KEY, authCode).commit()
-        } else {
-            Log.e(
-                tag,
-                "Failed to fetch auth code, the current response: $authCode",
-            )
+        if (videoToken.startsWith("?")) {
+            Log.d(tag, "Video token fetched successfully")
+            return videoToken
         }
 
-        return authCode
+        Log.e(
+            tag,
+            "Failed to fetch video token, the current response: $videoToken",
+        )
+
+        return ""
     }
 
     fun getVideoList(doc: Document): List<Video> {
+        Log.d(tag, "Starting to fetch video list")
+
         val hasFHD = doc.selectFirst("div.abaItem:contains(FULLHD)") != null
         val serverUrl = doc.selectFirst("meta[itemprop=contentURL]")!!
             .attr("content")
-            .replace("cdn1", "cdn3")
-            .replace("cdn80", "cdn8")
         val thumbUrl = doc.selectFirst("meta[itemprop=thumbnailUrl]")!!
             .attr("content")
         val type = serverUrl.split("/").get(3)
@@ -231,6 +272,8 @@ class AnitubeExtractor(
             }
         } + listOf("appfullhd")
 
+        Log.d(tag, "Found ${paths.size} videos")
+
         val firstLink =
             doc.selectFirst("div.video_container > a, div.playerContainer > a")!!.attr("href")
 
@@ -240,16 +283,35 @@ class AnitubeExtractor(
             .mapIndexed { index, quality ->
                 object {
                     var path = paths[index]
-                    var url = serverUrl.replace(type, path) + authCode
+                    var url = serverUrl.replace(type, path)
                     var quality = "$quality - Anitube"
                 }
             }
             .parallelCatchingFlatMapBlocking {
-                if (!checkVideoExists(it.url).exists) {
-                    Log.d(tag, "Video not exists: ${it.url.substringBefore("?")}")
-                    return@parallelCatchingFlatMapBlocking emptyList()
+                if (!authCode.isNullOrBlank() && checkVideoExists(it.url + authCode).exists) {
+                    return@parallelCatchingFlatMapBlocking listOf(
+                        Video(
+                            it.url + authCode,
+                            it.quality,
+                            it.url + authCode,
+                            headers = headers,
+                        ),
+                    )
                 }
-                listOf(Video(it.url, it.quality, it.url, headers = headers))
+                val videoToken = getVideoToken(it.url, authCode)
+                if (videoToken.isNotBlank() && checkVideoExists(it.url + videoToken).exists) {
+                    return@parallelCatchingFlatMapBlocking listOf(
+                        Video(
+                            it.url + videoToken,
+                            it.quality,
+                            it.url + videoToken,
+                            headers = headers,
+                        ),
+                    )
+                }
+
+                Log.d(tag, "Video not exists: ${it.url.substringBefore("?")}")
+                return@parallelCatchingFlatMapBlocking emptyList()
             }
             .reversed()
     }
diff --git a/src/pt/flixei/AndroidManifest.xml b/src/pt/flixei/AndroidManifest.xml
deleted file mode 100644
index 6fa0bad2..00000000
--- a/src/pt/flixei/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.flixei.FlixeiUrlActivity"
-            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="flixei.com"
-                    android:pathPattern="/assistir/..*/..*"
-                    android:scheme="https" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/src/pt/flixei/build.gradle b/src/pt/flixei/build.gradle
deleted file mode 100644
index efc6facf..00000000
--- a/src/pt/flixei/build.gradle
+++ /dev/null
@@ -1,12 +0,0 @@
-ext {
-    extName = 'Flixei'
-    extClass = '.Flixei'
-    extVersionCode = 8
-}
-
-apply from: "$rootDir/common.gradle"
-
-dependencies {
-    implementation(project(":lib:streamtape-extractor"))
-    implementation(project(":lib:mixdrop-extractor"))
-}
diff --git a/src/pt/flixei/res/mipmap-hdpi/ic_launcher.png b/src/pt/flixei/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index 61d07595..00000000
Binary files a/src/pt/flixei/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/flixei/res/mipmap-mdpi/ic_launcher.png b/src/pt/flixei/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 8b2f31da..00000000
Binary files a/src/pt/flixei/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/flixei/res/mipmap-xhdpi/ic_launcher.png b/src/pt/flixei/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index 58738047..00000000
Binary files a/src/pt/flixei/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/flixei/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/flixei/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index 0dee2e43..00000000
Binary files a/src/pt/flixei/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/flixei/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/flixei/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 678679b5..00000000
Binary files a/src/pt/flixei/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/flixei/src/eu/kanade/tachiyomi/animeextension/pt/flixei/Flixei.kt b/src/pt/flixei/src/eu/kanade/tachiyomi/animeextension/pt/flixei/Flixei.kt
deleted file mode 100644
index 1aad72bc..00000000
--- a/src/pt/flixei/src/eu/kanade/tachiyomi/animeextension/pt/flixei/Flixei.kt
+++ /dev/null
@@ -1,346 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.flixei
-
-import android.app.Application
-import androidx.preference.ListPreference
-import androidx.preference.PreferenceScreen
-import eu.kanade.tachiyomi.animeextension.pt.flixei.dto.AnimeDto
-import eu.kanade.tachiyomi.animeextension.pt.flixei.dto.ApiResultsDto
-import eu.kanade.tachiyomi.animeextension.pt.flixei.dto.EpisodeDto
-import eu.kanade.tachiyomi.animeextension.pt.flixei.dto.PlayersDto
-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.mixdropextractor.MixDropExtractor
-import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
-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.json.Json
-import okhttp3.MediaType.Companion.toMediaType
-import okhttp3.Request
-import okhttp3.RequestBody.Companion.toRequestBody
-import okhttp3.Response
-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 Flixei : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
-
-    override val name = "Flixei"
-
-    override val baseUrl = "https://flixei.com"
-
-    override val lang = "pt-BR"
-
-    override val supportsLatest = true
-
-    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 {
-        val body = "slider=3".toFormBody()
-        return POST("$baseUrl/includes/ajax/home.php", body = body)
-    }
-
-    override fun popularAnimeParse(response: Response): AnimesPage {
-        val results = response.parseAs<ApiResultsDto<AnimeDto>>()
-        val animes = results.items.values.map(::parseAnimeFromObject)
-        return AnimesPage(animes, false)
-    }
-
-    private fun parseAnimeFromObject(anime: AnimeDto) = SAnime.create().apply {
-        title = anime.title
-        setUrlWithoutDomain("/assistir/filme/${anime.url}/online/gratis")
-        thumbnail_url = "$baseUrl/content/movies/posterPt/185/${anime.id}.webp"
-    }
-
-    override fun popularAnimeFromElement(element: Element): SAnime {
-        throw UnsupportedOperationException()
-    }
-
-    override fun popularAnimeNextPageSelector(): String? {
-        throw UnsupportedOperationException()
-    }
-
-    override fun popularAnimeSelector(): String {
-        throw UnsupportedOperationException()
-    }
-
-    // =============================== Latest ===============================
-    override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/filmes/estreia/$page")
-
-    override fun latestUpdatesSelector() = "div.generalMoviesList > a.gPoster"
-
-    override fun latestUpdatesFromElement(element: Element) = SAnime.create().apply {
-        title = element.selectFirst("div.i span")!!.text()
-        thumbnail_url = element.selectFirst("img")?.attr("src")
-        setUrlWithoutDomain(element.attr("abs:href"))
-    }
-
-    override fun latestUpdatesNextPageSelector() = "div.paginationSystem a.next"
-
-    // =============================== Search ===============================
-    override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage {
-        return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
-            val path = query.removePrefix(PREFIX_SEARCH)
-            client.newCall(GET("$baseUrl/assistir/$path/online/gratis"))
-                .awaitSuccess()
-                .use(::searchAnimeByPathParse)
-        } else {
-            super.getSearchAnime(page, query, filters)
-        }
-    }
-
-    private fun searchAnimeByPathParse(response: Response): AnimesPage {
-        val details = animeDetailsParse(response.asJsoup()).apply {
-            setUrlWithoutDomain(response.request.url.toString())
-            initialized = true
-        }
-
-        return AnimesPage(listOf(details), false)
-    }
-
-    override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
-        return GET("$baseUrl/pesquisar/$query")
-    }
-
-    override fun searchAnimeSelector() = latestUpdatesSelector()
-
-    override fun searchAnimeFromElement(element: Element) = latestUpdatesFromElement(element)
-
-    override fun searchAnimeNextPageSelector() = null
-
-    // =========================== Anime Details ============================
-    override fun animeDetailsParse(document: Document) = SAnime.create().apply {
-        setUrlWithoutDomain(document.location())
-        thumbnail_url = document.selectFirst("meta[property=og:image]")?.attr("content")
-        val container = document.selectFirst("div.moviePresent")!!
-        with(container) {
-            title = selectFirst("h2.tit")!!.text()
-            genre = select("div.genres > span").eachText().joinToString()
-            author = getInfo("Diretor")
-            artist = getInfo("Produtoras")
-            description = buildString {
-                selectFirst("p")?.text()?.also { append(it + "\n\n") }
-                getInfo("Título")?.also { append("Título original: $it\n") }
-                getInfo("Serie de")?.also { append("ano: $it\n") }
-                getInfo("Elenco")?.also { append("Elenco: $it\n") }
-                getInfo("Qualidade")?.also { append("Qualidade: $it\n") }
-            }
-        }
-    }
-
-    // ============================== Episodes ==============================
-    private fun getSeasonEps(seasonElement: Element): List<SEpisode> {
-        val id = seasonElement.attr("data-load-episodes")
-        val sname = seasonElement.text()
-        val body = "getEpisodes=$id".toFormBody()
-        val response = client.newCall(POST("$EMBED_WAREZ_URL/serieAjax.php", body = body)).execute()
-        val episodes = response.parseAs<ApiResultsDto<EpisodeDto>>().items.values.map {
-            SEpisode.create().apply {
-                name = "Temp $sname: Ep ${it.name}"
-                episode_number = it.name.toFloatOrNull() ?: 0F
-                url = it.id
-            }
-        }
-        return episodes
-    }
-
-    override fun episodeListParse(response: Response): List<SEpisode> {
-        val docUrl = response.asJsoup().selectFirst("div#playButton")!!
-            .attr("onclick")
-            .substringAfter("'")
-            .substringBefore("'")
-        return if (response.request.url.toString().contains("/serie/")) {
-            client.newCall(GET(docUrl)).execute()
-                .asJsoup()
-                .select("div#seasons div.item[data-load-episodes]")
-                .flatMap(::getSeasonEps)
-                .reversed()
-        } else {
-            listOf(
-                SEpisode.create().apply {
-                    name = "Filme"
-                    episode_number = 1F
-                    url = "$EMBED_WAREZ_URL/filme/" + docUrl.substringAfter("=")
-                },
-            )
-        }
-    }
-    override fun episodeFromElement(element: Element): SEpisode {
-        throw UnsupportedOperationException()
-    }
-
-    override fun episodeListSelector(): String {
-        throw UnsupportedOperationException()
-    }
-
-    // ============================ Video Links =============================
-    override fun videoListRequest(episode: SEpisode): Request {
-        val url = episode.url
-        return if (url.startsWith("https")) {
-            // Its an real url, maybe from a movie
-            GET(url, headers)
-        } else {
-            POST("$EMBED_WAREZ_URL/serieAjax.php", body = "getAudios=$url".toFormBody())
-        }
-    }
-
-    override fun videoListParse(response: Response): List<Video> {
-        val body = response.body.string()
-        // Pair<Language, Query>
-        val items = if (body.startsWith("{")) {
-            val data = json.decodeFromString<ApiResultsDto<PlayersDto>>(body)
-            data.items.values.flatMap {
-                val lang = if (it.audio == "1") "LEGENDADO" else "DUBLADO"
-                it.iterator().mapNotNull { (server, status) ->
-                    if (status == "3") {
-                        Pair(lang, "?id=${it.id}&sv=$server")
-                    } else {
-                        null
-                    }
-                }
-            }
-        } else {
-            val doc = response.asJsoup(body)
-            doc.select("div.selectAudioButton").flatMap {
-                val lang = it.text()
-                val id = it.attr("data-load-hosts")
-                doc.select("div[data-load-embed=$id]").map { element ->
-                    lang to "?id=$id&sv=${element.attr("data-load-embed-host")}"
-                }
-            }.ifEmpty {
-                val lang = doc.selectFirst("div.selectAudio > b")!!.text()
-                    .substringBefore("/")
-                    .uppercase()
-                val id = doc.selectFirst("*[data-load-embed]")!!.attr("data-load-embed")
-                doc.select("div.buttonLoadHost").map {
-                    lang to "?id=$id&sv=${it.attr("data-load-embed-host")}"
-                }
-            }
-        }
-        return items.parallelCatchingFlatMapBlocking(::getVideosFromItem)
-    }
-
-    private val streamtapeExtractor by lazy { StreamTapeExtractor(client) }
-    private val mixdropExtractor by lazy { MixDropExtractor(client) }
-
-    private fun getVideosFromItem(item: Pair<String, String>): List<Video> {
-        val (lang, query) = item
-        val headers = headersBuilder().set("referer", WAREZ_URL).build()
-        val hostUrl = if ("warezcdn" in query) {
-            "$WAREZ_URL/player/player.php$query"
-        } else {
-            client.newCall(GET("$WAREZ_URL/embed/getPlay.php$query", headers))
-                .execute()
-                .body.string()
-                .substringAfter("location.href=\"")
-                .substringBefore("\";")
-        }
-
-        return when (query.substringAfter("sv=")) {
-            "streamtape" -> streamtapeExtractor.videosFromUrl(hostUrl, "Streamtape($lang)")
-            "mixdrop" -> mixdropExtractor.videoFromUrl(hostUrl, lang)
-            else -> null // TODO: Add warezcdn extractor
-        }.orEmpty()
-    }
-
-    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_PLAYER_KEY
-            title = PREF_PLAYER_TITLE
-            entries = PREF_PLAYER_ARRAY
-            entryValues = PREF_PLAYER_ARRAY
-            setDefaultValue(PREF_PLAYER_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)
-
-        ListPreference(screen.context).apply {
-            key = PREF_LANGUAGE_KEY
-            title = PREF_LANGUAGE_TITLE
-            entries = PREF_LANGUAGE_ENTRIES
-            entryValues = PREF_LANGUAGE_VALUES
-            setDefaultValue(PREF_LANGUAGE_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 Element.getInfo(item: String) = selectFirst("*:containsOwn($item) b")?.text()
-
-    private fun String.toFormBody() = toRequestBody("application/x-www-form-urlencoded".toMediaType())
-
-    override fun List<Video>.sort(): List<Video> {
-        val player = preferences.getString(PREF_PLAYER_KEY, PREF_PLAYER_DEFAULT)!!
-        val language = preferences.getString(PREF_LANGUAGE_KEY, PREF_LANGUAGE_DEFAULT)!!
-        return sortedWith(
-            compareBy(
-                { it.quality.contains(player) },
-                { it.quality.contains(language) },
-            ),
-        ).reversed()
-    }
-
-    companion object {
-
-        const val PREFIX_SEARCH = "path:"
-
-        private const val EMBED_WAREZ_URL = "https://embed.warezcdn.net"
-        private const val WAREZ_URL = "https://warezcdn.com"
-
-        private const val PREF_PLAYER_KEY = "pref_player"
-        private const val PREF_PLAYER_DEFAULT = "MixDrop"
-        private const val PREF_PLAYER_TITLE = "Player/Server favorito"
-        private val PREF_PLAYER_ARRAY = arrayOf(
-            "MixDrop",
-            "Streamtape",
-        )
-
-        private const val PREF_LANGUAGE_KEY = "pref_language"
-        private const val PREF_LANGUAGE_DEFAULT = "LEG"
-        private const val PREF_LANGUAGE_TITLE = "Língua/tipo preferido"
-        private val PREF_LANGUAGE_ENTRIES = arrayOf("Legendado", "Dublado")
-        private val PREF_LANGUAGE_VALUES = arrayOf("LEG", "DUB")
-    }
-}
diff --git a/src/pt/flixei/src/eu/kanade/tachiyomi/animeextension/pt/flixei/FlixeiUrlActivity.kt b/src/pt/flixei/src/eu/kanade/tachiyomi/animeextension/pt/flixei/FlixeiUrlActivity.kt
deleted file mode 100644
index de531bdc..00000000
--- a/src/pt/flixei/src/eu/kanade/tachiyomi/animeextension/pt/flixei/FlixeiUrlActivity.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.flixei
-
-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://flixei.com/assistir/<type>/<item> intents
- * and redirects them to the main Aniyomi process.
- */
-class FlixeiUrlActivity : Activity() {
-
-    private val tag = javaClass.simpleName
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        val pathSegments = intent?.data?.pathSegments
-        if (pathSegments != null && pathSegments.size > 2) {
-            val type = pathSegments[1]
-            val item = pathSegments[2]
-            val mainIntent = Intent().apply {
-                action = "eu.kanade.tachiyomi.ANIMESEARCH"
-                putExtra("query", "${Flixei.PREFIX_SEARCH}$type/$item")
-                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/flixei/src/eu/kanade/tachiyomi/animeextension/pt/flixei/dto/FlixeiDto.kt b/src/pt/flixei/src/eu/kanade/tachiyomi/animeextension/pt/flixei/dto/FlixeiDto.kt
deleted file mode 100644
index e3849cd9..00000000
--- a/src/pt/flixei/src/eu/kanade/tachiyomi/animeextension/pt/flixei/dto/FlixeiDto.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.flixei.dto
-
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class ApiResultsDto<T>(
-    @SerialName("list")
-    val items: Map<String, T>,
-)
-
-@Serializable
-data class AnimeDto(val id: String, val title: String, val url: String)
-
-@Serializable
-data class EpisodeDto(val id: String, val name: String)
-
-@Serializable
-data class PlayersDto(
-    val id: String,
-    val audio: String,
-    val mixdropStatus: String = "0",
-    val streamtapeStatus: String = "0",
-    val warezcdnStatus: String = "0",
-) {
-    operator fun iterator(): List<Pair<String, String>> {
-        return listOf(
-            "streamtape" to streamtapeStatus,
-            "mixdrop" to mixdropStatus,
-            "warezcdn" to warezcdnStatus,
-        )
-    }
-}
diff --git a/src/pt/listadeanimes/build.gradle b/src/pt/listadeanimes/build.gradle
deleted file mode 100644
index 6ac76a1d..00000000
--- a/src/pt/listadeanimes/build.gradle
+++ /dev/null
@@ -1,7 +0,0 @@
-ext {
-    extName = 'Lista de Animes'
-    extClass = '.ListaDeAnimes'
-    extVersionCode = 2
-}
-
-apply from: "$rootDir/common.gradle"
diff --git a/src/pt/listadeanimes/res/mipmap-hdpi/ic_launcher.png b/src/pt/listadeanimes/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index 5cee6385..00000000
Binary files a/src/pt/listadeanimes/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/listadeanimes/res/mipmap-mdpi/ic_launcher.png b/src/pt/listadeanimes/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index a09f0d88..00000000
Binary files a/src/pt/listadeanimes/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/listadeanimes/res/mipmap-xhdpi/ic_launcher.png b/src/pt/listadeanimes/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index fe66479c..00000000
Binary files a/src/pt/listadeanimes/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/listadeanimes/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/listadeanimes/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index 4d18c5d5..00000000
Binary files a/src/pt/listadeanimes/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/listadeanimes/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/listadeanimes/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 91b2c05b..00000000
Binary files a/src/pt/listadeanimes/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/listadeanimes/src/eu/kanade/tachiyomi/animeextension/pt/listadeanimes/ListaDeAnimes.kt b/src/pt/listadeanimes/src/eu/kanade/tachiyomi/animeextension/pt/listadeanimes/ListaDeAnimes.kt
deleted file mode 100644
index b4b3b04f..00000000
--- a/src/pt/listadeanimes/src/eu/kanade/tachiyomi/animeextension/pt/listadeanimes/ListaDeAnimes.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.listadeanimes
-
-import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
-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.network.GET
-import eu.kanade.tachiyomi.util.asJsoup
-import okhttp3.Request
-import okhttp3.Response
-import org.jsoup.nodes.Document
-import org.jsoup.nodes.Element
-
-class ListaDeAnimes : ParsedAnimeHttpSource() {
-    override val name = "Lista de Animes"
-
-    override val baseUrl = "https://www.listadeanimes.com"
-
-    override val lang = "pt-BR"
-
-    override val supportsLatest = false
-
-    override fun headersBuilder() = super.headersBuilder()
-        .add("Referer", baseUrl)
-
-    // ============================== Popular ===============================
-    override fun popularAnimeRequest(page: Int) = GET("$baseUrl/page/$page")
-
-    override fun popularAnimeSelector() = "article.post.excerpt > div.capa:not(:has(a[href=$baseUrl/anime-lista-online]))"
-
-    override fun popularAnimeFromElement(element: Element) = SAnime.create().apply {
-        setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
-        val img = element.selectFirst("img")!!
-        title = titleCase(img.attr("title").substringBefore(" todos os episódios"))
-        thumbnail_url = img.attr("data-src")
-    }
-
-    override fun popularAnimeNextPageSelector() = "a.next.page-numbers"
-
-    // =============================== Latest ===============================
-    override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException()
-    override fun latestUpdatesSelector(): String = throw UnsupportedOperationException()
-    override fun latestUpdatesFromElement(element: Element): SAnime = throw UnsupportedOperationException()
-    override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException()
-
-    // =============================== Search ===============================
-    override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList) = GET("$baseUrl/page/$page?s=$query")
-    override fun searchAnimeParse(response: Response) = popularAnimeParse(response)
-    override fun searchAnimeSelector() = popularAnimeSelector()
-    override fun searchAnimeFromElement(element: Element) = popularAnimeFromElement(element)
-    override fun searchAnimeNextPageSelector() = popularAnimeNextPageSelector()
-
-    // =========================== Anime Details ============================
-    override fun animeDetailsParse(document: Document) = SAnime.create().apply {
-        setUrlWithoutDomain(document.location())
-        val titleText = document.selectFirst("h1.title.single-title")!!.text()
-        title = titleCase(titleText.substringBefore(" todos os episódios"))
-        thumbnail_url = document.selectFirst("img.aligncenter.size-full")?.attr("src")
-        val infos = document.selectFirst("div#content.post-single-content > center")
-        val infosText = infos?.run {
-            html()
-                .replace("<br>", "\n")
-                .replace("<b>", "")
-                .replace("</b>", "")
-        }?.let { "\n\n$it" }.orEmpty()
-
-        val sinopse = document.selectFirst("div#content > *:contains(Sinopse)")?.nextElementSibling()
-        description = (sinopse?.text() ?: "Sem sinopse.") + infosText
-        genre = document.select("a[rel=tag]").joinToString { it.text() }
-    }
-
-    // ============================== Episodes ==============================
-    override fun episodeListSelector() = "div.videos > ul"
-
-    override fun episodeListParse(response: Response): List<SEpisode> {
-        val doc = response.asJsoup()
-        return doc.select("div.videos > ul > li:gt(0)")
-            .map(::episodeFromElement)
-            .reversed()
-    }
-    override fun episodeFromElement(element: Element): SEpisode {
-        return SEpisode.create().apply {
-            episode_number = runCatching {
-                element.selectFirst("string")!!
-                    .text()
-                    .substringAfter(" ")
-                    .toFloat()
-            }.getOrDefault(0F)
-            name = element.text().substringAfter("► ")
-            url = element.attr("id")
-        }
-    }
-
-    // ============================ Video Links =============================
-    override suspend fun getVideoList(episode: SEpisode): List<Video> {
-        return listOf(Video(episode.url, episode.name, episode.url))
-    }
-
-    override fun videoListSelector() = throw UnsupportedOperationException()
-    override fun videoListRequest(episode: SEpisode) = throw UnsupportedOperationException()
-    override fun videoListParse(response: Response) = throw UnsupportedOperationException()
-    override fun videoFromElement(element: Element) = throw UnsupportedOperationException()
-    override fun videoUrlParse(document: Document) = throw UnsupportedOperationException()
-
-    // ============================= Utilities ==============================
-    private fun titleCase(str: String): String {
-        return str.split(' ')
-            .map { it.replaceFirstChar(Char::uppercase) }
-            .joinToString(" ")
-    }
-}
diff --git a/src/pt/megaflix/AndroidManifest.xml b/src/pt/megaflix/AndroidManifest.xml
deleted file mode 100644
index c7f04aa4..00000000
--- a/src/pt/megaflix/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.megaflix.MegaflixUrlActivity"
-            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="megaflix.co"
-                    android:pathPattern="/..*/..*/"
-                    android:scheme="https" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/src/pt/megaflix/build.gradle b/src/pt/megaflix/build.gradle
deleted file mode 100644
index a5713572..00000000
--- a/src/pt/megaflix/build.gradle
+++ /dev/null
@@ -1,20 +0,0 @@
-ext {
-    extName = 'Megaflix'
-    extClass = '.Megaflix'
-    extVersionCode = 24
-    isNsfw = true
-}
-
-apply from: "$rootDir/common.gradle"
-
-dependencies {
-    implementation(project(':lib:mixdrop-extractor'))
-    implementation(project(":lib:streamtape-extractor"))
-    implementation(project(":lib:voe-extractor"))
-    implementation(project(":lib:filemoon-extractor"))
-    implementation(project(":lib:vidhide-extractor"))
-    implementation(project(":lib:streamwish-extractor"))
-    implementation(project(":lib:playlist-utils"))
-    // for mixdrop and megaflix
-    implementation(libs.jsunpacker)
-}
diff --git a/src/pt/megaflix/res/mipmap-hdpi/ic_launcher.png b/src/pt/megaflix/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index bf99313a..00000000
Binary files a/src/pt/megaflix/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/megaflix/res/mipmap-mdpi/ic_launcher.png b/src/pt/megaflix/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 0bf5f9da..00000000
Binary files a/src/pt/megaflix/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/megaflix/res/mipmap-xhdpi/ic_launcher.png b/src/pt/megaflix/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index 6ea93116..00000000
Binary files a/src/pt/megaflix/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/megaflix/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/megaflix/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index c441ac81..00000000
Binary files a/src/pt/megaflix/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/megaflix/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/megaflix/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 524bfd1d..00000000
Binary files a/src/pt/megaflix/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/Megaflix.kt b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/Megaflix.kt
deleted file mode 100644
index e64a0785..00000000
--- a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/Megaflix.kt
+++ /dev/null
@@ -1,317 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.megaflix
-
-import android.app.Application
-import androidx.preference.ListPreference
-import androidx.preference.PreferenceScreen
-import eu.kanade.tachiyomi.animeextension.pt.megaflix.extractors.MegaflixExtractor
-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.filemoonextractor.FilemoonExtractor
-import eu.kanade.tachiyomi.lib.mixdropextractor.MixDropExtractor
-import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
-import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
-import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
-import eu.kanade.tachiyomi.lib.vidhideextractor.VidHideExtractor
-import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.network.await
-import eu.kanade.tachiyomi.network.awaitSuccess
-import eu.kanade.tachiyomi.util.asJsoup
-import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
-import eu.kanade.tachiyomi.util.parallelFlatMapBlocking
-import okhttp3.Request
-import okhttp3.Response
-import org.jsoup.nodes.Document
-import org.jsoup.nodes.Element
-import uy.kohesive.injekt.Injekt
-import uy.kohesive.injekt.api.get
-
-class Megaflix : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
-
-    override val name = "Megaflix"
-
-    override val baseUrl = "https://megaflix.ac"
-
-    override val lang = "pt-BR"
-
-    override val supportsLatest = true
-
-    override fun headersBuilder() = super.headersBuilder().add("Referer", "$baseUrl/")
-
-    private val preferences by lazy {
-        Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
-    }
-
-    // ============================== Popular ===============================
-    override fun popularAnimeRequest(page: Int) = GET(baseUrl)
-
-    override fun popularAnimeSelector() = "section#widget_list_movies_series-5 li > article"
-
-    override fun popularAnimeFromElement(element: Element) = SAnime.create().apply {
-        title = element.selectFirst("h2.entry-title")!!.text()
-        setUrlWithoutDomain(element.selectFirst("a.lnk-blk")!!.attr("href"))
-        thumbnail_url = element.selectFirst("img")?.absUrl("src")
-    }
-
-    override fun popularAnimeNextPageSelector() = null
-
-    // =============================== Latest ===============================
-    override fun latestUpdatesRequest(page: Int): Request {
-        val pageType = preferences.getString(PREF_LATEST_PAGE_KEY, PREF_LATEST_PAGE_DEFAULT)!!
-        return GET("$baseUrl/$pageType/page/$page")
-    }
-
-    override fun latestUpdatesSelector() = "li > article"
-
-    override fun latestUpdatesFromElement(element: Element) = popularAnimeFromElement(element)
-
-    override fun latestUpdatesNextPageSelector() = "div.nav-links > a:containsOwn(PRÓXIMO)"
-
-    // =============================== Search ===============================
-    override suspend fun getSearchAnime(
-        page: Int,
-        query: String,
-        filters: AnimeFilterList,
-    ): AnimesPage {
-        return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
-            val path = query.removePrefix(PREFIX_SEARCH)
-            client.newCall(GET("$baseUrl/$path"))
-                .awaitSuccess()
-                .use(::searchAnimeByPathParse)
-        } else {
-            super.getSearchAnime(page, query, filters)
-        }
-    }
-
-    private fun searchAnimeByPathParse(response: Response): AnimesPage {
-        val details = animeDetailsParse(response.asJsoup()).apply {
-            setUrlWithoutDomain(response.request.url.toString())
-            initialized = true
-        }
-
-        return AnimesPage(listOf(details), false)
-    }
-
-    override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
-        return if (query.isNotBlank()) {
-            GET("$baseUrl/page/$page/?s=$query")
-        } else {
-            val genre = MegaflixFilters.getGenre(filters)
-            GET("$baseUrl/categoria/$genre/page/$page")
-        }
-    }
-
-    override fun searchAnimeSelector() = latestUpdatesSelector()
-
-    override fun searchAnimeFromElement(element: Element) = popularAnimeFromElement(element)
-
-    override fun searchAnimeNextPageSelector() = latestUpdatesNextPageSelector()
-
-    override fun getFilterList() = MegaflixFilters.FILTER_LIST
-
-    // =========================== Anime Details ============================
-    override fun animeDetailsParse(document: Document) = SAnime.create().apply {
-        setUrlWithoutDomain(document.location())
-        val infos = document.selectFirst("div.bd > article.post.single")!!
-        title = infos.selectFirst("h1.entry-title")!!.text()
-        thumbnail_url = infos.selectFirst("img")?.absUrl("src")
-        genre = infos.select("span.genres > a").eachText().joinToString()
-        description = infos.selectFirst("div.description")?.text()
-    }
-
-    // ============================== Episodes ==============================
-    override fun episodeListSelector() = "li > article.episodes"
-    private fun seasonListSelector() = "section.episodes div.choose-season > a"
-
-    override fun episodeListParse(response: Response): List<SEpisode> {
-        val doc = response.asJsoup()
-        val seasons = doc.select(seasonListSelector())
-        return when {
-            seasons.isEmpty() -> listOf(
-                SEpisode.create().apply {
-                    name = "Filme"
-                    setUrlWithoutDomain(doc.location())
-                    episode_number = 1F
-                },
-            )
-
-            else -> seasons.parallelFlatMapBlocking(::episodesFromSeason).reversed()
-        }
-    }
-
-    private suspend fun episodesFromSeason(seasonElement: Element): List<SEpisode> {
-        return seasonElement.attr("href").let { url ->
-            client.newCall(GET(url, headers)).await()
-                .asJsoup()
-                .select(episodeListSelector())
-                .map(::episodeFromElement)
-        }
-    }
-
-    override fun episodeFromElement(element: Element) = SEpisode.create().apply {
-        name = element.selectFirst("h2.entry-title")!!.text()
-        setUrlWithoutDomain(element.selectFirst("a.lnk-blk")!!.attr("href"))
-        episode_number = element.selectFirst("span.num-epi")?.run {
-            text().split("x").last().toFloatOrNull() ?: 0F
-        } ?: 0F
-    }
-
-    // ============================ Video Links =============================
-    override fun videoListParse(response: Response): List<Video> {
-        val items = response.asJsoup().select(videoListSelector())
-        return items
-            .parallelCatchingFlatMapBlocking { element ->
-                val language = element.text().substringAfter("-")
-                val id = element.attr("href")
-                val url = element.closest("body")?.selectFirst("div$id iframe")
-                    ?.let {
-                        val iframeUrl = it.attr("src")
-                        client.newCall(GET(iframeUrl, headers))
-                            .execute()
-                            .asJsoup()
-                            .selectFirst("iframe")
-                            ?.attr("src")
-                    } ?: return@parallelCatchingFlatMapBlocking emptyList()
-
-                getVideoList(url, language)
-            }
-    }
-
-    /*--------------------------------Video extractors------------------------------------*/
-    private val webViewResolver by lazy { WebViewResolver() }
-    private val playlistUtils by lazy { PlaylistUtils(client, headers) }
-
-    private val mixdropExtractor by lazy { MixDropExtractor(client) }
-    private val streamtapeExtractor by lazy { StreamTapeExtractor(client) }
-    private val megaflixExtractor by lazy { MegaflixExtractor(client, headers) }
-    private val voeExtractor by lazy { VoeExtractor(client) }
-    private val filemoonExtractor by lazy { FilemoonExtractor(client) }
-    private val vidHideExtractor by lazy { VidHideExtractor(client, headers) }
-    private val streamWishExtractor by lazy { StreamWishExtractor(client, headers) }
-
-    private fun getVideoList(url: String, language: String): List<Video> {
-        return when {
-            arrayOf("mixdrop", "mixdroop", "mix").any(url) -> mixdropExtractor.videoFromUrl(url, language)
-            arrayOf("streamtape", "stp", "stape").any(url) -> streamtapeExtractor.videosFromUrl(url, "StreamTape - $language")
-            arrayOf("mflix").any(url) -> megaflixExtractor.videosFromUrl(url, language)
-            arrayOf("voe").any(url) -> voeExtractor.videosFromUrl(url, "$language ")
-            arrayOf("filemoon", "moonplayer").any(url) -> filemoonExtractor.videosFromUrl(url, prefix = "$language Filemoon:")
-            arrayOf("vidhide", "vid.").any(url) -> vidHideExtractor.videosFromUrl(url, videoNameGen = { "$language VidHide:$it" })
-            arrayOf("wishembed", "streamwish", "strwish", "wish", "jwplayerhls").any(url) -> streamWishExtractor.videosFromUrl(url, videoNameGen = { "$language StreamWish:$it" })
-            arrayOf("fembedder").any(url) -> {
-                val webViewResult = webViewResolver.getUrl(url, headers)
-                if (webViewResult.isBlank()) {
-                    return emptyList()
-                }
-                return if (webViewResult.contains("m3u8")) {
-                    playlistUtils.extractFromHls(webViewResult)
-                } else {
-                    listOf(Video(url, "Default", url))
-                }
-            }
-            else -> emptyList()
-        }
-    }
-
-    override fun videoListSelector() = "aside.video-options li a"
-
-    override fun videoFromElement(element: Element) = throw UnsupportedOperationException()
-
-    override fun videoUrlParse(document: Document) = 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_ENTRIES
-            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)
-
-        ListPreference(screen.context).apply {
-            key = PREF_LANGUAGE_KEY
-            title = PREF_LANGUAGE_TITLE
-            entries = PREF_LANGUAGE_VALUES
-            entryValues = PREF_LANGUAGE_VALUES
-            setDefaultValue(PREF_LANGUAGE_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)
-
-        ListPreference(screen.context).apply {
-            key = PREF_LATEST_PAGE_KEY
-            title = PREF_LATEST_PAGE_TITLE
-            entries = PREF_LATEST_PAGE_ENTRIES
-            entryValues = PREF_LATEST_PAGE_VALUES
-            setDefaultValue(PREF_LATEST_PAGE_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 ==============================
-    override fun List<Video>.sort(): List<Video> {
-        val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!
-        val lang = preferences.getString(PREF_LANGUAGE_KEY, PREF_LANGUAGE_DEFAULT)!!
-        return sortedWith(
-            compareBy(
-                { it.quality.contains(quality) },
-                { it.quality.contains(lang) },
-            ),
-        ).reversed()
-    }
-
-    private fun Array<String>.any(url: String): Boolean = this.any { url.contains(it, ignoreCase = true) }
-
-    companion object {
-        const val PREFIX_SEARCH = "path:"
-
-        private const val PREF_QUALITY_KEY = "preferred_quality"
-        private const val PREF_QUALITY_TITLE = "Qualidade preferida"
-        private const val PREF_QUALITY_DEFAULT = "720p"
-        private val PREF_QUALITY_ENTRIES = arrayOf("360p", "480p", "720p", "1080p")
-
-        private const val PREF_LANGUAGE_KEY = "pref_language"
-        private const val PREF_LANGUAGE_DEFAULT = "Legendado"
-        private const val PREF_LANGUAGE_TITLE = "Língua/tipo preferido"
-        private val PREF_LANGUAGE_VALUES = arrayOf("Legendado", "Dublado")
-
-        private const val PREF_LATEST_PAGE_KEY = "pref_latest_page"
-        private const val PREF_LATEST_PAGE_DEFAULT = "series"
-        private const val PREF_LATEST_PAGE_TITLE = "Página de últimos adicionados"
-        private val PREF_LATEST_PAGE_ENTRIES = arrayOf(
-            "Filmes",
-            "Séries",
-        )
-        private val PREF_LATEST_PAGE_VALUES = arrayOf(
-            "filmes",
-            "series",
-        )
-    }
-}
diff --git a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/MegaflixFilters.kt b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/MegaflixFilters.kt
deleted file mode 100644
index 07f6de38..00000000
--- a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/MegaflixFilters.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.megaflix
-
-import eu.kanade.tachiyomi.animesource.model.AnimeFilter
-import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
-
-object MegaflixFilters {
-
-    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
-    }
-
-    private inline fun <reified R> AnimeFilterList.asQueryPart(): String {
-        return (first { it is R } as QueryPartFilter).toQueryPart()
-    }
-
-    class GenreFilter : QueryPartFilter("Gênero", MegaflixFiltersData.GENRES)
-
-    val FILTER_LIST get() = AnimeFilterList(
-        AnimeFilter.Header(MegaflixFiltersData.IGNORE_SEARCH_MSG),
-        GenreFilter(),
-    )
-
-    fun getGenre(filters: AnimeFilterList) = filters.asQueryPart<GenreFilter>()
-
-    private object MegaflixFiltersData {
-        const val IGNORE_SEARCH_MSG = "NOTA: O filtro é IGNORADO ao usar a pesquisa."
-
-        val GENRES = arrayOf(
-            Pair("Animação", "animacao"),
-            Pair("Aventura", "aventura"),
-            Pair("Ação", "acao"),
-            Pair("Biografia", "biografia"),
-            Pair("Comédia", "comedia"),
-            Pair("Crime", "crime"),
-            Pair("Documentário", "documentario"),
-            Pair("Drama", "drama"),
-            Pair("Esporte", "esporte"),
-            Pair("Família", "familia"),
-            Pair("Fantasia", "fantasia"),
-            Pair("Faroeste", "faroeste"),
-            Pair("Ficção científica", "ficcao-cientifica"),
-            Pair("Guerra", "guerra"),
-            Pair("História", "historia"),
-            Pair("Mistério", "misterio"),
-            Pair("Musical", "musical"),
-            Pair("Música", "musica"),
-            Pair("Romance", "romance"),
-            Pair("Show", "show"),
-            Pair("Terror", "terror"),
-            Pair("Thriller", "thriller"),
-        )
-    }
-}
diff --git a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/MegaflixUrlActivity.kt b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/MegaflixUrlActivity.kt
deleted file mode 100644
index cec9a93d..00000000
--- a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/MegaflixUrlActivity.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.megaflix
-
-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://megaflix.ac/<type>/<item> intents
- * and redirects them to the main Aniyomi process.
- */
-class MegaflixUrlActivity : 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 path = "${pathSegments[0]}/${pathSegments[1]}"
-            val mainIntent = Intent().apply {
-                action = "eu.kanade.tachiyomi.ANIMESEARCH"
-                putExtra("query", "${Megaflix.PREFIX_SEARCH}$path")
-                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/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/WebViewResolver.kt b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/WebViewResolver.kt
deleted file mode 100644
index a1c377b0..00000000
--- a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/WebViewResolver.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.megaflix
-
-import android.annotation.SuppressLint
-import android.app.Application
-import android.os.Handler
-import android.os.Looper
-import android.webkit.WebResourceRequest
-import android.webkit.WebResourceResponse
-import android.webkit.WebView
-import android.webkit.WebViewClient
-import okhttp3.Headers
-import uy.kohesive.injekt.injectLazy
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
-
-class WebViewResolver() {
-    private val context: Application by injectLazy()
-    private val handler by lazy { Handler(Looper.getMainLooper()) }
-
-    @SuppressLint("SetJavaScriptEnabled")
-    fun getUrl(origRequestUrl: String, origRequestheader: Headers): String {
-        val latch = CountDownLatch(1)
-        var webView: WebView? = null
-        var resultUrl = ""
-        val headers = origRequestheader.toMultimap().mapValues { it.value.getOrNull(0) ?: "" }.toMutableMap()
-
-        handler.post {
-            val webview = WebView(context)
-            webView = webview
-            with(webview.settings) {
-                javaScriptEnabled = true
-                domStorageEnabled = true
-                databaseEnabled = true
-                useWideViewPort = false
-                loadWithOverviewMode = false
-                userAgentString = origRequestheader["User-Agent"]
-            }
-            webview.webViewClient = object : WebViewClient() {
-                override fun shouldInterceptRequest(
-                    view: WebView,
-                    request: WebResourceRequest,
-                ): WebResourceResponse? {
-                    val url = request.url.toString()
-                    if (VIDEO_REGEX.containsMatchIn(url)) {
-                        resultUrl = url
-                        latch.countDown()
-                    }
-                    return super.shouldInterceptRequest(view, request)
-                }
-            }
-
-            webView?.loadUrl(origRequestUrl, headers)
-        }
-
-        latch.await(TIMEOUT_SEC, TimeUnit.SECONDS)
-
-        handler.post {
-            webView?.stopLoading()
-            webView?.destroy()
-            webView = null
-        }
-        return resultUrl
-    }
-
-    companion object {
-        const val TIMEOUT_SEC: Long = 20
-        private val VIDEO_REGEX by lazy { Regex("\\.(mp4|m3u8)") }
-    }
-}
diff --git a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/extractors/MegaflixExtractor.kt b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/extractors/MegaflixExtractor.kt
deleted file mode 100644
index 849511d8..00000000
--- a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/extractors/MegaflixExtractor.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.megaflix.extractors
-
-import dev.datlag.jsunpacker.JsUnpacker
-import eu.kanade.tachiyomi.animesource.model.Video
-import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
-import eu.kanade.tachiyomi.network.GET
-import okhttp3.Headers
-import okhttp3.OkHttpClient
-
-class MegaflixExtractor(private val client: OkHttpClient, private val headers: Headers) {
-    private val playlistUtils by lazy { PlaylistUtils(client, headers) }
-
-    fun videosFromUrl(url: String, lang: String = ""): List<Video> {
-        val unpacked = client.newCall(GET(url, headers)).execute()
-            .body.string()
-            .let(JsUnpacker::unpackAndCombine)
-            ?.replace("\\", "")
-            ?: return emptyList()
-
-        val playlistUrl = unpacked.substringAfter("file':'").substringBefore("'")
-
-        return playlistUtils.extractFromHls(
-            playlistUrl,
-            "https://megaflix.ac",
-            videoNameGen = { "Megaflix($lang) - $it" },
-        )
-    }
-}
diff --git a/src/pt/pifansubs/res/web_hi_res_512.png b/src/pt/pifansubs/res/web_hi_res_512.png
deleted file mode 100644
index e586e291..00000000
Binary files a/src/pt/pifansubs/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/pt/pobreflix/build.gradle b/src/pt/pobreflix/build.gradle
deleted file mode 100644
index a3dcec69..00000000
--- a/src/pt/pobreflix/build.gradle
+++ /dev/null
@@ -1,19 +0,0 @@
-ext {
-    extName = 'Pobreflix'
-    extClass = '.Pobreflix'
-    themePkg = 'dooplay'
-    baseUrl = 'https://pobreflix.global'
-    overrideVersionCode = 18
-    isNsfw = true
-}
-
-apply from: "$rootDir/common.gradle"
-
-dependencies {
-    implementation(project(":lib:filemoon-extractor"))
-    implementation(project(':lib:fireplayer-extractor'))
-    implementation(project(":lib:streamwish-extractor"))
-    implementation(project(":lib:streamtape-extractor"))
-    implementation(project(":lib:playlist-utils"))
-    implementation(libs.jsunpacker)
-}
diff --git a/src/pt/pobreflix/res/mipmap-hdpi/ic_launcher.png b/src/pt/pobreflix/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index d5f7231a..00000000
Binary files a/src/pt/pobreflix/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/pobreflix/res/mipmap-mdpi/ic_launcher.png b/src/pt/pobreflix/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 208cbaa0..00000000
Binary files a/src/pt/pobreflix/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/pobreflix/res/mipmap-xhdpi/ic_launcher.png b/src/pt/pobreflix/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index 30444a76..00000000
Binary files a/src/pt/pobreflix/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/pobreflix/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/pobreflix/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index cbd9fe5d..00000000
Binary files a/src/pt/pobreflix/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/pobreflix/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/pobreflix/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 35b2f3c2..00000000
Binary files a/src/pt/pobreflix/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/Pobreflix.kt b/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/Pobreflix.kt
deleted file mode 100644
index c1159018..00000000
--- a/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/Pobreflix.kt
+++ /dev/null
@@ -1,80 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.pobreflix
-
-import android.util.Base64
-import eu.kanade.tachiyomi.animeextension.pt.pobreflix.extractors.MyStreamExtractor
-import eu.kanade.tachiyomi.animeextension.pt.pobreflix.extractors.PlayerFlixExtractor
-import eu.kanade.tachiyomi.animeextension.pt.pobreflix.extractors.SuperFlixExtractor
-import eu.kanade.tachiyomi.animesource.model.Video
-import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
-import eu.kanade.tachiyomi.lib.fireplayerextractor.FireplayerExtractor
-import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
-import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
-import eu.kanade.tachiyomi.multisrc.dooplay.DooPlay
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.util.asJsoup
-import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
-import okhttp3.HttpUrl.Companion.toHttpUrl
-import okhttp3.Response
-
-class Pobreflix : DooPlay(
-    "pt-BR",
-    "Pobreflix",
-    "https://pobreflix.global",
-) {
-    // ============================== Popular ===============================
-    override fun popularAnimeSelector() = "div.featured div.poster"
-
-    // =============================== Latest ===============================
-    override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/series/page/$page/", headers)
-
-    // ============================ Video Links =============================
-    private val fireplayerExtractor by lazy { FireplayerExtractor(client) }
-    private val filemoonExtractor by lazy { FilemoonExtractor(client) }
-    private val mystreamExtractor by lazy { MyStreamExtractor(client, headers) }
-    private val streamtapeExtractor by lazy { StreamTapeExtractor(client) }
-    private val streamwishExtractor by lazy { StreamWishExtractor(client, headers) }
-    private val playerflixExtractor by lazy { PlayerFlixExtractor(client, headers, ::genericExtractor) }
-    private val superflixExtractor by lazy { SuperFlixExtractor(client, headers, ::genericExtractor) }
-    private val supercdnExtractor by lazy { SuperFlixExtractor(client, headers, ::genericExtractor, "https://supercdn.org") }
-
-    override fun videoListParse(response: Response): List<Video> {
-        val doc = response.asJsoup()
-        return doc.select("div.source-box > a").parallelCatchingFlatMapBlocking {
-            val data = it.attr("href").trim().toHttpUrl().queryParameter("auth")
-                ?.let { Base64.decode(it, Base64.DEFAULT) }
-                ?.let(::String)
-                ?: return@parallelCatchingFlatMapBlocking emptyList()
-            val url = data.replace("\\", "").substringAfter("url\":\"").substringBefore('"')
-            genericExtractor(url)
-        }
-    }
-
-    private fun genericExtractor(url: String, language: String = ""): List<Video> {
-        val langSubstr = if (language.isBlank()) "" else "[$language] "
-        return when {
-            url.contains("superflix") ->
-                superflixExtractor.videosFromUrl(url)
-            url.contains("supercdn") ->
-                supercdnExtractor.videosFromUrl(url)
-            url.contains("filemoon") ->
-                filemoonExtractor.videosFromUrl(url, "${langSubstr}Filemoon - ", headers = headers)
-            url.contains("watch.brplayer") || url.contains("/watch?v=") ->
-                mystreamExtractor.videosFromUrl(url, language)
-            url.contains("brbeast") ->
-                fireplayerExtractor.videosFromUrl(url = url, videoNameGen = { "${langSubstr}BrBeast - $it" })
-            url.contains("embedplayer") ->
-                fireplayerExtractor.videosFromUrl(url = url, videoNameGen = { "${langSubstr}EmbedPlayer - $it" })
-            url.contains("superembeds") ->
-                fireplayerExtractor.videosFromUrl(url = url, videoNameGen = { "${langSubstr}SuperEmbeds - $it" })
-            url.contains("streamtape") ->
-                streamtapeExtractor.videosFromUrl(url, "${langSubstr}Streamtape")
-            url.contains("filelions") ->
-                streamwishExtractor.videosFromUrl(url, videoNameGen = { "${langSubstr}FileLions - $it" })
-            url.contains("streamwish") ->
-                streamwishExtractor.videosFromUrl(url, videoNameGen = { "${langSubstr}Streamwish - $it" })
-            url.contains("playerflix") ->
-                playerflixExtractor.videosFromUrl(url)
-            else -> emptyList()
-        }
-    }
-}
diff --git a/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/extractors/MyStreamExtractor.kt b/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/extractors/MyStreamExtractor.kt
deleted file mode 100644
index b510b9db..00000000
--- a/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/extractors/MyStreamExtractor.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.pobreflix.extractors
-
-import eu.kanade.tachiyomi.animesource.model.Video
-import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
-import eu.kanade.tachiyomi.network.GET
-import okhttp3.Headers
-import okhttp3.OkHttpClient
-
-// From animeworldindia
-class MyStreamExtractor(private val client: OkHttpClient, private val headers: Headers) {
-
-    private val playlistUtils by lazy { PlaylistUtils(client, headers) }
-
-    fun videosFromUrl(url: String, language: String): List<Video> {
-        val host = url.substringBefore("/watch?")
-
-        val response = client.newCall(GET(url, headers)).execute()
-        val body = response.body.string()
-
-        val codePart = body
-            .substringAfter("sniff(") // Video function
-            .substringBefore(",[")
-
-        val streamCode = codePart
-            .substringAfterLast(",\"") // our beloved hash
-            .substringBefore('"')
-
-        val id = codePart.substringAfter(",\"").substringBefore('"') // required ID
-
-        val streamUrl = "$host/m3u8/$id/$streamCode/master.txt?s=1&cache=1"
-
-        val cookie = response.headers.firstOrNull {
-            it.first.startsWith("set-cookie", true) && it.second.startsWith("PHPSESSID", true)
-        }?.second?.substringBefore(";") ?: ""
-
-        val newHeaders = headers.newBuilder()
-            .set("cookie", cookie)
-            .set("accept", "*/*")
-            .build()
-
-        return playlistUtils.extractFromHls(
-            streamUrl,
-            masterHeaders = newHeaders,
-            videoHeaders = newHeaders,
-            videoNameGen = { "[$language] MyStream: $it" },
-        )
-    }
-}
diff --git a/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/extractors/PlayerFlixExtractor.kt b/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/extractors/PlayerFlixExtractor.kt
deleted file mode 100644
index 0dab9340..00000000
--- a/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/extractors/PlayerFlixExtractor.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.pobreflix.extractors
-
-import eu.kanade.tachiyomi.animesource.model.Video
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.util.asJsoup
-import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
-import okhttp3.Headers
-import okhttp3.OkHttpClient
-
-class PlayerFlixExtractor(
-    private val client: OkHttpClient,
-    private val defaultHeaders: Headers,
-    private val genericExtractor: (String, String) -> List<Video>,
-) {
-    fun videosFromUrl(url: String): List<Video> {
-        val doc = client.newCall(GET(url, defaultHeaders)).execute().asJsoup()
-
-        val items = doc.select("#hostList div.buttonLoadHost").mapNotNull {
-            val url = it.attr("onclick")
-                .substringAfter('"', "")
-                .substringBefore('"')
-                ?: return@mapNotNull null
-
-            val language = if (it.hasClass("hostDub")) {
-                "Dublado"
-            } else {
-                "Legendado"
-            }
-
-            language to url // (Language, videoId)
-        }
-
-        return items.parallelCatchingFlatMapBlocking { genericExtractor(it.second, it.first) }
-    }
-}
diff --git a/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/extractors/SuperFlixExtractor.kt b/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/extractors/SuperFlixExtractor.kt
deleted file mode 100644
index 92a2dcbe..00000000
--- a/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/extractors/SuperFlixExtractor.kt
+++ /dev/null
@@ -1,134 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.pobreflix.extractors
-
-import eu.kanade.tachiyomi.animesource.model.Video
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.network.POST
-import eu.kanade.tachiyomi.network.await
-import eu.kanade.tachiyomi.util.asJsoup
-import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.json.Json
-import okhttp3.FormBody
-import okhttp3.Headers
-import okhttp3.HttpUrl.Companion.toHttpUrl
-import okhttp3.OkHttpClient
-import uy.kohesive.injekt.injectLazy
-
-class SuperFlixExtractor(
-    private val client: OkHttpClient,
-    private val defaultHeaders: Headers,
-    private val genericExtractor: (String, String) -> List<Video>,
-    private val host: String = "https://superflixapi.dev",
-) {
-    private val json: Json by injectLazy()
-
-    fun videosFromUrl(url: String): List<Video> {
-        val links = linksFromUrl(url)
-
-        val fixedLinks = links.parallelCatchingFlatMapBlocking {
-            val (language, linkUrl) = it
-            when {
-                linkUrl.contains("?vid=") -> linksFromPlayer(linkUrl, language)
-                else -> listOf(it)
-            }
-        }
-
-        return fixedLinks.parallelCatchingFlatMapBlocking { genericExtractor(it.second, it.first) }
-    }
-
-    private suspend fun linksFromPlayer(url: String, language: String): List<Pair<String, String>> {
-        val httpUrl = url.toHttpUrl()
-        val id = httpUrl.queryParameter("vid")!!
-        val headers = defaultHeaders.newBuilder()
-            .set("referer", "$host/")
-            .set("origin", host)
-            .build()
-
-        val doc = client.newCall(GET(url, headers)).await().asJsoup()
-
-        val baseUrl = "https://" + httpUrl.host
-        val apiUrl = "$baseUrl/ajax_sources.php"
-
-        val apiHeaders = headers.newBuilder()
-            .set("referer", url)
-            .set("origin", baseUrl)
-            .set("X-Requested-With", "XMLHttpRequest")
-            .build()
-
-        return doc.select("ul > li[data-order-value]").mapNotNull {
-            val name = it.attr("data-dropdown-value")
-            val order = it.attr("data-order-value")
-
-            val formBody = FormBody.Builder()
-                .add("vid", id)
-                .add("alternative", name)
-                .add("ord", order)
-                .build()
-
-            val req = client.newCall(POST(apiUrl, apiHeaders, formBody)).await()
-                .body.string()
-
-            runCatching {
-                val iframeUrl = json.decodeFromString<PlayerLinkDto>(req).iframe!!
-                val iframeServer = iframeUrl.toHttpUrl().queryParameter("sv")!!
-                language to when (name) {
-                    "1xbet" -> "https://watch.brplayer.site/watch?v=${iframeServer.trim('/')}"
-                    else -> iframeServer
-                }
-            }.getOrNull()
-        }
-    }
-
-    @Serializable
-    data class PlayerLinkDto(val iframe: String? = null)
-
-    private fun linksFromUrl(url: String): List<Pair<String, String>> {
-        val doc = client.newCall(GET(url, defaultHeaders)).execute().asJsoup()
-
-        val items = doc.select("div.select_languages").mapNotNull {
-            val id = it.nextElementSibling()
-                ?.selectFirst("div[data-id]")
-                ?.attr("data-id")
-                ?: return@mapNotNull null
-
-            val language = it.text()
-                .replace("Disponível", "")
-                .replace("disponível", "")
-                .replace("Apenas", "")
-                .replace("em", "")
-                .trim()
-
-            language to id // (Language, videoId)
-        }
-
-        val headers = defaultHeaders.newBuilder()
-            .set("Origin", host)
-            .set("Referer", url)
-            .set("X-Requested-With", "XMLHttpRequest")
-            .build()
-
-        return items.mapNotNull {
-            runCatching {
-                it.first to getLink(it.second, headers)!!
-            }.getOrNull()
-        }
-    }
-
-    private fun getLink(id: String, headers: Headers): String? {
-        val body = FormBody.Builder()
-            .add("action", "getPlayer")
-            .add("video_id", id)
-            .build()
-
-        val res = client.newCall(POST("$host/api", headers, body)).execute()
-            .body.string()
-
-        return json.decodeFromString<ApiResponseDto>(res).data?.video_url
-    }
-
-    @Serializable
-    data class ApiResponseDto(val data: DataDto? = null)
-
-    @Serializable
-    data class DataDto(val video_url: String? = null)
-}
diff --git a/src/pt/vizer/AndroidManifest.xml b/src/pt/vizer/AndroidManifest.xml
deleted file mode 100644
index b9524492..00000000
--- a/src/pt/vizer/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.vizer.VizerUrlActivity"
-            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="vizer.tv"
-                    android:pathPattern="/..*/..*/..*"
-                    android:scheme="https" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
diff --git a/src/pt/vizer/build.gradle b/src/pt/vizer/build.gradle
deleted file mode 100644
index f5ed1181..00000000
--- a/src/pt/vizer/build.gradle
+++ /dev/null
@@ -1,16 +0,0 @@
-ext {
-    extName = 'Vizer.tv'
-    extClass = '.Vizer'
-    extVersionCode = 24
-    isNsfw = true
-}
-
-apply from: "$rootDir/common.gradle"
-
-dependencies {
-    implementation(project(':lib:fireplayer-extractor'))
-    implementation(project(':lib:mixdrop-extractor'))
-    implementation(project(':lib:playlist-utils'))
-    implementation(project(':lib:streamtape-extractor'))
-    implementation(libs.jsunpacker)
-}
diff --git a/src/pt/vizer/res/mipmap-hdpi/ic_launcher.png b/src/pt/vizer/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index ae34c91d..00000000
Binary files a/src/pt/vizer/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/vizer/res/mipmap-mdpi/ic_launcher.png b/src/pt/vizer/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index b78a281b..00000000
Binary files a/src/pt/vizer/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/vizer/res/mipmap-xhdpi/ic_launcher.png b/src/pt/vizer/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index e07ab4a7..00000000
Binary files a/src/pt/vizer/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/vizer/res/mipmap-xxhdpi/ic_launcher.png b/src/pt/vizer/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index a5654df6..00000000
Binary files a/src/pt/vizer/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/vizer/res/mipmap-xxxhdpi/ic_launcher.png b/src/pt/vizer/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index b904558c..00000000
Binary files a/src/pt/vizer/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/Vizer.kt b/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/Vizer.kt
deleted file mode 100644
index caa95dbb..00000000
--- a/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/Vizer.kt
+++ /dev/null
@@ -1,359 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.vizer
-
-import android.app.Application
-import androidx.preference.ListPreference
-import androidx.preference.PreferenceScreen
-import eu.kanade.tachiyomi.animeextension.pt.vizer.VizerFilters.FilterSearchParams
-import eu.kanade.tachiyomi.animeextension.pt.vizer.dto.EpisodeListDto
-import eu.kanade.tachiyomi.animeextension.pt.vizer.dto.HostersDto
-import eu.kanade.tachiyomi.animeextension.pt.vizer.dto.SearchItemDto
-import eu.kanade.tachiyomi.animeextension.pt.vizer.dto.SearchResultDto
-import eu.kanade.tachiyomi.animeextension.pt.vizer.dto.VideoDto
-import eu.kanade.tachiyomi.animeextension.pt.vizer.dto.VideoListDto
-import eu.kanade.tachiyomi.animeextension.pt.vizer.interceptor.WebViewResolver
-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.fireplayerextractor.FireplayerExtractor
-import eu.kanade.tachiyomi.lib.mixdropextractor.MixDropExtractor
-import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.network.POST
-import eu.kanade.tachiyomi.network.awaitSuccess
-import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
-import eu.kanade.tachiyomi.util.asJsoup
-import eu.kanade.tachiyomi.util.parallelCatchingFlatMap
-import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
-import eu.kanade.tachiyomi.util.parseAs
-import okhttp3.HttpUrl.Companion.toHttpUrl
-import okhttp3.MediaType.Companion.toMediaType
-import okhttp3.Request
-import okhttp3.RequestBody.Companion.toRequestBody
-import okhttp3.Response
-import org.jsoup.nodes.Element
-import uy.kohesive.injekt.Injekt
-import uy.kohesive.injekt.api.get
-import kotlin.time.Duration.Companion.seconds
-
-class Vizer : ConfigurableAnimeSource, AnimeHttpSource() {
-
-    override val name = "Vizer.tv"
-
-    override val baseUrl = "https://novizer.com"
-    private val apiUrl = "$baseUrl/includes/ajax"
-
-    override val lang = "pt-BR"
-
-    override val supportsLatest = true
-
-    override fun headersBuilder() = super.headersBuilder().add("Referer", "$baseUrl/")
-
-    private val episodesClient by lazy {
-        client.newBuilder().rateLimitHost(baseUrl.toHttpUrl(), 1, 1.5.seconds).build()
-    }
-
-    private val preferences by lazy {
-        Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
-    }
-
-    private val webViewResolver by lazy { WebViewResolver(headers) }
-
-    // ============================== Popular ===============================
-    override fun popularAnimeRequest(page: Int): Request {
-        val pageType = preferences.getString(PREF_POPULAR_PAGE_KEY, PREF_POPULAR_PAGE_DEFAULT)!!
-        val params = FilterSearchParams(
-            orderBy = "vzViews",
-            orderWay = "desc",
-            type = pageType,
-        )
-        return searchAnimeRequest(page, "", params)
-    }
-
-    override fun popularAnimeParse(response: Response): AnimesPage {
-        val result = response.parseAs<SearchResultDto>()
-        val animes = result.items.values.map(::animeFromObject)
-        val hasNext = result.quantity == 35
-        return AnimesPage(animes, hasNext)
-    }
-
-    private fun animeFromObject(item: SearchItemDto) = SAnime.create().apply {
-        val (urlslug, imgslug) = when {
-            item.status.isBlank() -> Pair("filme", "movies")
-            else -> Pair("serie", "series")
-        }
-        url = "/$urlslug/online/${item.url}"
-        title = item.title
-        status = when (item.status) {
-            "Retornando" -> SAnime.ONGOING
-            else -> SAnime.COMPLETED
-        }
-        thumbnail_url = "$baseUrl/content/$imgslug/posterPt/342/${item.id}.webp"
-    }
-
-    // =============================== Latest ===============================
-    override fun latestUpdatesRequest(page: Int) = apiRequest("getHomeSliderSeries=1")
-
-    override fun latestUpdatesParse(response: Response): AnimesPage {
-        val parsedData = response.parseAs<SearchResultDto>()
-        val animes = parsedData.items.values.map(::animeFromObject)
-        return AnimesPage(animes, false)
-    }
-
-    // =============================== Search ===============================
-    override fun getFilterList(): AnimeFilterList = VizerFilters.FILTER_LIST
-
-    override fun searchAnimeParse(response: Response) = popularAnimeParse(response)
-
-    override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage {
-        return if (query.startsWith(PREFIX_SEARCH)) {
-            val path = query.removePrefix(PREFIX_SEARCH).replace("/", "/online/")
-            client.newCall(GET("$baseUrl/$path"))
-                .awaitSuccess()
-                .use(::searchAnimeByPathParse)
-        } else {
-            super.getSearchAnime(page, query, filters)
-        }
-    }
-
-    private fun searchAnimeByPathParse(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 = VizerFilters.getSearchParameters(filters)
-        return searchAnimeRequest(page, query, params)
-    }
-
-    private fun searchAnimeRequest(page: Int, query: String, params: FilterSearchParams): Request {
-        val urlBuilder = "$apiUrl/ajaxPagination.php".toHttpUrl().newBuilder()
-            .addQueryParameter("page", "${page - 1}")
-            .addQueryParameter("categoryFilterYearMin", params.minYear)
-            .addQueryParameter("categoryFilterYearMax", params.maxYear)
-            .addQueryParameter("categoryFilterOrderBy", params.orderBy)
-            .addQueryParameter("categoryFilterOrderWay", params.orderWay)
-            .apply {
-                if (query.isNotBlank()) addQueryParameter("search", query)
-
-                when (params.type) {
-                    "Movies" -> {
-                        addQueryParameter("saga", "0")
-                        addQueryParameter("categoriesListMovies", params.genre)
-                    }
-                    else -> {
-                        addQueryParameter("categoriesListSeries", params.genre)
-                        val isAnime = params.type == "anime"
-                        addQueryParameter("anime", if (isAnime) "1" else "0")
-                    }
-                }
-            }
-        return GET(urlBuilder.build(), headers)
-    }
-
-    // =========================== Anime Details ============================
-    override fun animeDetailsParse(response: Response) = SAnime.create().apply {
-        val doc = response.asJsoup()
-        setUrlWithoutDomain(doc.location())
-        title = doc.selectFirst("section.ai > h2")!!.text()
-        thumbnail_url = doc.selectFirst("meta[property=og:image]")!!.attr("content")
-
-        description = buildString {
-            append(doc.selectFirst("span.desc")!!.text() + "\n")
-            doc.selectFirst("div.year")?.also { append("\nAno: ", it.text()) }
-            doc.selectFirst("div.tm")?.also { append("\nDuração: ", it.text()) }
-            doc.selectFirst("a.rating")?.also { append("\nNota: ", it.text()) }
-        }
-    }
-
-    // ============================== Episodes ==============================
-    private fun getSeasonEps(seasonElement: Element): List<SEpisode> {
-        val id = seasonElement.attr("data-season-id")
-        val sname = seasonElement.text()
-        val response = episodesClient.newCall(apiRequest("getEpisodes=$id")).execute()
-        val episodes = response.parseAs<EpisodeListDto>().episodes
-            .values
-            .filter { it.released === true }
-            .map {
-                SEpisode.create().apply {
-                    name = "$sname: Ep ${it.name}".run {
-                        if (!it.title.contains("Episode ")) {
-                            this + " - ${it.title}"
-                        } else {
-                            this
-                        }
-                    }
-                    episode_number = it.name.toFloatOrNull() ?: 0F
-                    url = it.id
-                }
-            }
-        return episodes
-    }
-
-    override fun episodeListParse(response: Response): List<SEpisode> {
-        val doc = response.asJsoup()
-        val seasons = doc.select("div.seasons div.list div.item[data-season-id]")
-        return if (seasons.size > 0) {
-            seasons.flatMap(::getSeasonEps).reversed()
-        } else {
-            listOf(
-                SEpisode.create().apply {
-                    name = "Filme"
-                    episode_number = 1F
-                    url = response.request.url.toString()
-                },
-            )
-        }
-    }
-
-    // ============================ Video Links =============================
-    override fun videoListRequest(episode: SEpisode): Request {
-        val url = episode.url
-        return if (url.startsWith("https")) {
-            // Its an real url, maybe from a movie
-            GET(url, headers)
-        } else {
-            // Fake url, its an ID that will be used to get episode languages
-            // (sub/dub) and then return the video link
-            apiRequest("getEpisodeData=$url")
-        }
-    }
-
-    override fun videoListParse(response: Response): List<Video> {
-        val body = response.body.string()
-        val videoObjectList = if (body.startsWith("{")) {
-            body.parseAs<VideoListDto>().videos.values.toList()
-        } else {
-            val doc = response.asJsoup(body)
-            doc.select("div.audios div[data-load-player]").mapNotNull {
-                try {
-                    val movieHosters = it.attr("data-players").parseAs<HostersDto>()
-                    val movieId = it.attr("data-load-player")
-                    val movieLang = if (it.hasClass("legendado")) "1" else "0"
-                    VideoDto(movieId, movieLang).apply { hosters = movieHosters }
-                } catch (_: Throwable) { null }
-            }
-        }
-
-        return videoObjectList.parallelCatchingFlatMapBlocking(::getVideosFromObject)
-    }
-
-    private val mixdropExtractor by lazy { MixDropExtractor(client) }
-    private val streamtapeExtractor by lazy { StreamTapeExtractor(client) }
-    private val fireplayerExtractor by lazy { FireplayerExtractor(client) }
-
-    private suspend fun getVideosFromObject(videoObj: VideoDto): List<Video> {
-        val hosters = videoObj.hosters ?: return emptyList()
-
-        val langPrefix = if (videoObj.lang == "1") "LEG" else "DUB"
-
-        return hosters.iterator().parallelCatchingFlatMap { (name, status) ->
-            // Always try the warezcdn
-            if (status != 3 && name != "warezcdn") return@parallelCatchingFlatMap emptyList()
-            val url = getPlayerUrl(videoObj.id, name)
-            if (url.isNullOrBlank()) {
-                return@parallelCatchingFlatMap emptyList()
-            }
-            when (name) {
-                "mixdrop" -> mixdropExtractor.videosFromUrl(url, langPrefix)
-                "streamtape" -> streamtapeExtractor.videosFromUrl(url, "StreamTape($langPrefix)")
-                "warezcdn" -> fireplayerExtractor.videosFromUrl(url, videoNameGen = { "WarezCDN($langPrefix) - $it" })
-                else -> emptyList()
-            }
-        }
-    }
-
-    // ============================== Settings ==============================
-    override fun setupPreferenceScreen(screen: PreferenceScreen) {
-        ListPreference(screen.context).apply {
-            key = PREF_POPULAR_PAGE_KEY
-            title = PREF_POPULAR_PAGE_TITLE
-            entries = PREF_POPULAR_PAGE_ENTRIES
-            entryValues = PREF_POPULAR_PAGE_VALUES
-            setDefaultValue(PREF_POPULAR_PAGE_DEFAULT)
-            summary = "%s"
-        }.also(screen::addPreference)
-
-        ListPreference(screen.context).apply {
-            key = PREF_PLAYER_KEY
-            title = PREF_PLAYER_TITLE
-            entries = PREF_PLAYER_ARRAY
-            entryValues = PREF_PLAYER_ARRAY
-            setDefaultValue(PREF_PLAYER_DEFAULT)
-            summary = "%s"
-        }.also(screen::addPreference)
-
-        ListPreference(screen.context).apply {
-            key = PREF_LANGUAGE_KEY
-            title = PREF_LANGUAGE_TITLE
-            entries = PREF_LANGUAGE_ENTRIES
-            entryValues = PREF_LANGUAGE_VALUES
-            setDefaultValue(PREF_LANGUAGE_DEFAULT)
-            summary = "%s"
-        }.also(screen::addPreference)
-    }
-
-    // ============================= Utilities ==============================
-    private val noRedirectClient = client.newBuilder().followRedirects(false).build()
-
-    private fun getPlayerUrl(id: String, name: String): String? {
-        return webViewResolver.getUrl("$baseUrl/embed/getEmbed.php?id=$id&sv=$name", "$baseUrl/termos")
-    }
-
-    private fun apiRequest(body: String): Request {
-        val reqBody = body.toRequestBody("application/x-www-form-urlencoded".toMediaType())
-        val newHeaders = headersBuilder().add("x-requested-with", "XMLHttpRequest").build()
-        return POST("$apiUrl/publicFunctions.php", newHeaders, body = reqBody)
-    }
-
-    override fun List<Video>.sort(): List<Video> {
-        val player = preferences.getString(PREF_PLAYER_KEY, PREF_PLAYER_DEFAULT)!!
-        val language = preferences.getString(PREF_LANGUAGE_KEY, PREF_LANGUAGE_DEFAULT)!!
-        return sortedWith(
-            compareBy(
-                { it.quality.contains(player) },
-                { it.quality.contains(language) },
-            ),
-        ).reversed()
-    }
-
-    companion object {
-        private const val PREF_POPULAR_PAGE_KEY = "pref_popular_page"
-        private const val PREF_POPULAR_PAGE_DEFAULT = "movie"
-        private const val PREF_POPULAR_PAGE_TITLE = "Página de Populares"
-        private val PREF_POPULAR_PAGE_ENTRIES = arrayOf(
-            "Animes",
-            "Filmes",
-            "Séries",
-        )
-        private val PREF_POPULAR_PAGE_VALUES = arrayOf(
-            "anime",
-            "movie",
-            "serie",
-        )
-
-        private const val PREF_PLAYER_KEY = "pref_player"
-        private const val PREF_PLAYER_DEFAULT = "MixDrop"
-        private const val PREF_PLAYER_TITLE = "Player/Server favorito"
-        private val PREF_PLAYER_ARRAY = arrayOf(
-            "MixDrop",
-            "StreamTape",
-            "WarezCDN",
-        )
-
-        private const val PREF_LANGUAGE_KEY = "pref_language"
-        private const val PREF_LANGUAGE_DEFAULT = "LEG"
-        private const val PREF_LANGUAGE_TITLE = "Língua/tipo preferido"
-        private val PREF_LANGUAGE_ENTRIES = arrayOf("Legendado", "Dublado")
-        private val PREF_LANGUAGE_VALUES = arrayOf("LEG", "DUB")
-
-        const val PREFIX_SEARCH = "path:"
-    }
-}
diff --git a/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/VizerFilters.kt b/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/VizerFilters.kt
deleted file mode 100644
index 3940da20..00000000
--- a/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/VizerFilters.kt
+++ /dev/null
@@ -1,116 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.vizer
-
-import eu.kanade.tachiyomi.animeextension.pt.vizer.VizerFilters.VizerFiltersData.CURRENT_YEAR
-import eu.kanade.tachiyomi.animesource.model.AnimeFilter
-import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
-import java.util.Calendar
-
-object VizerFilters {
-    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
-    }
-
-    private inline fun <reified R> AnimeFilterList.asQueryPart(): String {
-        return (first { it is R } as QueryPartFilter).toQueryPart()
-    }
-
-    class TypeFilter : QueryPartFilter("Tipo", VizerFiltersData.TYPES)
-    class MinYearFilter : QueryPartFilter("Ano (min)", VizerFiltersData.MIN_YEARS)
-    class MaxYearFilter : QueryPartFilter("Ano (max)", VizerFiltersData.MAX_YEARS)
-    class GenreFilter : QueryPartFilter("Categoria", VizerFiltersData.GENRES)
-
-    class SortFilter : AnimeFilter.Sort(
-        "Ordernar por",
-        VizerFiltersData.ORDERS.map { it.first }.toTypedArray(),
-        Selection(0, false),
-    )
-
-    val FILTER_LIST get() = AnimeFilterList(
-        TypeFilter(),
-        MinYearFilter(),
-        MaxYearFilter(),
-        GenreFilter(),
-        SortFilter(),
-    )
-
-    data class FilterSearchParams(
-        val type: String = "anime",
-        val minYear: String = "1890",
-        val maxYear: String = CURRENT_YEAR.toString(),
-        val genre: String = "all",
-        val orderBy: String = "rating",
-        val orderWay: String = "desc",
-    )
-
-    internal fun getSearchParameters(filters: AnimeFilterList): FilterSearchParams {
-        if (filters.isEmpty()) return FilterSearchParams()
-
-        val sortFilter = filters.firstOrNull { it is SortFilter } as? SortFilter
-        val (orderBy, ascending) = sortFilter?.state?.run {
-            val order = VizerFiltersData.ORDERS[index].second
-            val orderWay = if (ascending) "asc" else "desc"
-
-            Pair(order, orderWay)
-        } ?: Pair("rating", "desc")
-
-        return FilterSearchParams(
-            filters.asQueryPart<TypeFilter>(),
-            filters.asQueryPart<MinYearFilter>(),
-            filters.asQueryPart<MaxYearFilter>(),
-            filters.asQueryPart<GenreFilter>(),
-            orderBy,
-            ascending,
-        )
-    }
-
-    private object VizerFiltersData {
-        val TYPES = arrayOf(
-            Pair("Animes", "anime"),
-            Pair("Filmes", "Movies"),
-            Pair("Series", "Series"),
-        )
-        val CURRENT_YEAR by lazy {
-            Calendar.getInstance()[Calendar.YEAR]
-        }
-        val MAX_YEARS = (CURRENT_YEAR downTo 1890).map {
-            Pair(it.toString(), it.toString())
-        }.toTypedArray()
-
-        val MIN_YEARS = MAX_YEARS.reversed().toTypedArray()
-
-        val ORDERS = arrayOf(
-            Pair("Popularidade", "vzViews"),
-            Pair("Ano", "year"),
-            Pair("Título", "title"),
-            Pair("Rating", "rating"),
-        )
-
-        val GENRES = arrayOf(
-            Pair("Todas", "all"),
-            Pair("Animação", "animacao"),
-            Pair("Aventura", "aventura"),
-            Pair("Ação", "acao"),
-            Pair("Comédia", "comedia"),
-            Pair("Crime", "crime"),
-            Pair("Documentário", "documentario"),
-            Pair("Drama", "drama"),
-            Pair("Família", "familia"),
-            Pair("Fantasia", "fantasia"),
-            Pair("Faroeste", "faroeste"),
-            Pair("Guerra", "guerra"),
-            Pair("LGBTQ+", "lgbt"),
-            Pair("Mistério", "misterio"),
-            Pair("Músical", "musical"),
-            Pair("Romance", "romance"),
-            Pair("Suspense", "suspense"),
-            Pair("Terror", "terror"),
-        )
-    }
-}
diff --git a/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/VizerUrlActivity.kt b/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/VizerUrlActivity.kt
deleted file mode 100644
index be22e4b7..00000000
--- a/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/VizerUrlActivity.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.vizer
-
-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://vizer.tv/[anime|filme|serie]/online/<slug> intents
- * and redirects them to the main Aniyomi process.
- */
-class VizerUrlActivity : Activity() {
-
-    private val tag = "VizerUrlActivity"
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        val pathSegments = intent?.data?.pathSegments
-        if (pathSegments != null && pathSegments.size > 1) {
-            val query = "${pathSegments[0]}/${pathSegments[2]}"
-            val searchQuery = Vizer.PREFIX_SEARCH + query
-            val mainIntent = Intent().apply {
-                action = "eu.kanade.tachiyomi.ANIMESEARCH"
-                putExtra("query", 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/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/dto/VizerDto.kt b/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/dto/VizerDto.kt
deleted file mode 100644
index f8bf3c96..00000000
--- a/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/dto/VizerDto.kt
+++ /dev/null
@@ -1,92 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.vizer.dto
-
-import eu.kanade.tachiyomi.util.parseAs
-import kotlinx.serialization.EncodeDefault
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.builtins.serializer
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.JsonPrimitive
-import kotlinx.serialization.json.JsonTransformingSerializer
-import kotlinx.serialization.json.booleanOrNull
-import kotlinx.serialization.json.jsonPrimitive
-
-typealias FakeList<T> = Map<String, T>
-
-@Serializable
-class SearchResultDto(
-    val quantity: Int = 0,
-    @EncodeDefault
-    @SerialName("list")
-    val items: FakeList<SearchItemDto> = emptyMap(),
-)
-
-@Serializable
-class SearchItemDto(
-    val id: String,
-    val title: String,
-    val url: String,
-    @EncodeDefault
-    val status: String = "",
-)
-
-@Serializable
-class EpisodeListDto(
-    @SerialName("list")
-    val episodes: FakeList<EpisodeItemDto>,
-)
-
-@Serializable
-class EpisodeItemDto(
-    val id: String,
-    val name: String,
-    @Serializable(with = BooleanSerializer::class)
-    val released: Boolean,
-    val title: String,
-)
-
-@Serializable
-class VideoListDto(
-    @SerialName("list")
-    val videos: FakeList<VideoDto>,
-)
-
-@Serializable
-class VideoDto(
-    val id: String,
-    val lang: String,
-    @SerialName("players")
-    private val players: String? = null,
-) {
-    var hosters = try {
-        players?.parseAs<HostersDto>()
-    } catch (e: Throwable) {
-        null
-    }
-}
-
-@Serializable
-class HostersDto(
-    val mixdrop: Int = 0,
-    val streamtape: Int = 0,
-    val warezcdn: Int = 0,
-) {
-    operator fun iterator(): List<Pair<String, Int>> {
-        return listOf(
-            "mixdrop" to mixdrop,
-            "streamtape" to streamtape,
-            "warezcdn" to warezcdn,
-        )
-    }
-}
-
-object BooleanSerializer : JsonTransformingSerializer<Boolean>(Boolean.serializer()) {
-    override fun transformDeserialize(element: JsonElement): JsonElement {
-        require(element is JsonPrimitive)
-        return if (element.jsonPrimitive.isString && element.jsonPrimitive.content == "true") {
-            JsonPrimitive(true)
-        } else {
-            JsonPrimitive(element.jsonPrimitive.booleanOrNull ?: false)
-        }
-    }
-}
diff --git a/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/interceptor/WebViewResolver.kt b/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/interceptor/WebViewResolver.kt
deleted file mode 100644
index 177f2704..00000000
--- a/src/pt/vizer/src/eu/kanade/tachiyomi/animeextension/pt/vizer/interceptor/WebViewResolver.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-package eu.kanade.tachiyomi.animeextension.pt.vizer.interceptor
-
-import android.annotation.SuppressLint
-import android.app.Application
-import android.os.Handler
-import android.os.Looper
-import android.util.Log
-import android.webkit.WebResourceRequest
-import android.webkit.WebResourceResponse
-import android.webkit.WebView
-import android.webkit.WebViewClient
-import okhttp3.Headers
-import uy.kohesive.injekt.injectLazy
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
-
-class WebViewResolver(private val globalHeaders: Headers) {
-    private val context: Application by injectLazy()
-    private val handler by lazy { Handler(Looper.getMainLooper()) }
-    private val tag by lazy { javaClass.simpleName }
-
-    @SuppressLint("SetJavaScriptEnabled")
-    fun getUrl(origRequestUrl: String, baseUrl: String): String? {
-        val latch = CountDownLatch(1)
-        var webView: WebView? = null
-        var result: String? = null
-
-        handler.post {
-            val webview = WebView(context)
-            webView = webview
-            with(webview.settings) {
-                javaScriptEnabled = true
-                domStorageEnabled = true
-                databaseEnabled = true
-                useWideViewPort = false
-                loadWithOverviewMode = false
-                userAgentString = globalHeaders["User-Agent"]
-            }
-            webview.webViewClient = object : WebViewClient() {
-                override fun shouldInterceptRequest(
-                    view: WebView,
-                    request: WebResourceRequest,
-                ): WebResourceResponse? {
-                    val url = request.url.toString()
-                    Log.d(tag, "Checking url $url")
-                    if (VIDEO_REGEX.containsMatchIn(url)) {
-                        result = url
-                        latch.countDown()
-                    }
-                    return super.shouldInterceptRequest(view, request)
-                }
-
-                override fun onPageFinished(view: WebView?, url: String?) {
-                    Log.d(tag, "onPageFinished $url")
-                    super.onPageFinished(view, url)
-
-                    view?.evaluateJavascript("document.body.innerHTML += '<iframe src=\"" + origRequestUrl + "\" scrolling=\"no\" frameborder=\"0\" allowfullscreen=\"\" webkitallowfullscreen=\"\" mozallowfullscreen=\"\"></iframe>'") {}
-                }
-            }
-
-            webView?.loadUrl(baseUrl)
-        }
-
-        latch.await(TIMEOUT_SEC, TimeUnit.SECONDS)
-
-        handler.post {
-            webView?.stopLoading()
-            webView?.destroy()
-            webView = null
-        }
-        return result
-    }
-
-    companion object {
-        const val TIMEOUT_SEC: Long = 25
-        private val VIDEO_REGEX by lazy { Regex("//(mixdrop|streamtape|warezcdn)|/video/") }
-    }
-}
diff --git a/src/tr/turkanime/res/web_hi_res_512.png b/src/tr/turkanime/res/web_hi_res_512.png
deleted file mode 100644
index 4f080baa..00000000
Binary files a/src/tr/turkanime/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/uk/uakino/ic_launcher-playstore.png b/src/uk/uakino/ic_launcher-playstore.png
deleted file mode 100644
index 0df13731..00000000
Binary files a/src/uk/uakino/ic_launcher-playstore.png and /dev/null differ
diff --git a/src/uk/ufdub/ic_launcher-playstore.png b/src/uk/ufdub/ic_launcher-playstore.png
deleted file mode 100644
index 77a1ef3c..00000000
Binary files a/src/uk/ufdub/ic_launcher-playstore.png and /dev/null differ