diff --git a/src/pt/anitube/build.gradle b/src/pt/anitube/build.gradle
index a70e1061..a468f926 100644
--- a/src/pt/anitube/build.gradle
+++ b/src/pt/anitube/build.gradle
@@ -1,7 +1,7 @@
 ext {
     extName = 'Anitube'
     extClass = '.Anitube'
-    extVersionCode = 18
+    extVersionCode = 19
 }
 
 apply from: "$rootDir/common.gradle"
diff --git a/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt
index 953b5f7e..9d5e4d02 100644
--- a/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt
+++ b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt
@@ -4,6 +4,7 @@ import android.app.Application
 import androidx.preference.EditTextPreference
 import androidx.preference.ListPreference
 import androidx.preference.PreferenceScreen
+import eu.kanade.tachiyomi.animeextension.pt.anitube.extractors.AnitubeDownloadExtractor
 import eu.kanade.tachiyomi.animeextension.pt.anitube.extractors.AnitubeExtractor
 import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
 import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@@ -15,6 +16,7 @@ import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
 import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.awaitSuccess
 import eu.kanade.tachiyomi.util.asJsoup
+import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
 import okhttp3.Request
 import okhttp3.Response
 import org.jsoup.nodes.Document
@@ -189,9 +191,29 @@ class Anitube : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
     }
 
     // ============================ Video Links =============================
-    private val extractor by lazy { AnitubeExtractor(headers, client, preferences) }
+    private val anitubeExtractor by lazy { AnitubeExtractor(headers, client, preferences) }
+    private val downloadExtractor by lazy { AnitubeDownloadExtractor(headers, client) }
+
+    override fun videoListParse(response: Response): List<Video> {
+        val document = response.asJsoup()
+
+        val links = mutableListOf(document.location())
+
+        document.selectFirst("div.abaItemDown > a")?.attr("href")?.let {
+            links.add(it)
+        }
+
+        val epName = document.selectFirst("meta[itemprop=name]")!!.attr("content")
+
+        return links.parallelCatchingFlatMapBlocking {
+            when {
+                it.contains("/download/") -> downloadExtractor.videosFromUrl(it, epName)
+                it.contains("file4go.net") -> downloadExtractor.videosFromUrl(it, epName)
+                else -> anitubeExtractor.getVideoList(document)
+            }
+        }
+    }
 
-    override fun videoListParse(response: Response) = extractor.getVideoList(response)
     override fun videoListSelector() = throw UnsupportedOperationException()
     override fun videoFromElement(element: Element) = throw UnsupportedOperationException()
     override fun videoUrlParse(document: Document) = throw UnsupportedOperationException()
@@ -264,8 +286,11 @@ class Anitube : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
     override fun List<Video>.sort(): List<Video> {
         val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!
         return sortedWith(
-            compareByDescending { it.quality.equals(quality) },
-        )
+            compareBy<Video>(
+                { it.quality.startsWith(quality) },
+                { PREF_QUALITY_ENTRIES.indexOf(it.quality.substringBefore(" ")) },
+            ).thenByDescending { it.quality },
+        ).reversed()
     }
 
     private fun String.toDate(): Long {
diff --git a/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeDownloadExtractor.kt b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeDownloadExtractor.kt
new file mode 100644
index 00000000..2d0bb1d6
--- /dev/null
+++ b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeDownloadExtractor.kt
@@ -0,0 +1,98 @@
+package eu.kanade.tachiyomi.animeextension.pt.anitube.extractors
+
+import android.util.Log
+import eu.kanade.tachiyomi.animesource.model.Video
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.network.POST
+import eu.kanade.tachiyomi.util.asJsoup
+import eu.kanade.tachiyomi.util.parallelMapNotNullBlocking
+import okhttp3.FormBody
+import okhttp3.Headers
+import okhttp3.OkHttpClient
+
+class AnitubeDownloadExtractor(
+    private val headers: Headers,
+    private val client: OkHttpClient,
+) {
+
+    private val qualities = listOf("SD", "HD", "FULLHD")
+    private val tag by lazy { javaClass.simpleName }
+
+    private fun videosFromFile4Go(url: String, quality: String): Video? {
+        Log.d(tag, "Checking download for $url")
+        val docDownload = client.newCall(GET(url)).execute().asJsoup()
+
+        val form =
+            docDownload.selectFirst("button.download")?.closest("form")
+
+        if (form == null) {
+            Log.d(tag, "Download form not found for $url")
+            return null
+        }
+
+        val body = FormBody.Builder().apply {
+            form.select("input[name]").forEach {
+                add(it.attr("name"), it.attr("value"))
+            }
+        }.build()
+
+        val postUrl = form.attr("action")
+
+        val postHeaders = headers.newBuilder()
+            .set("Referer", url)
+            .build()
+
+        val docFinal =
+            client.newCall(POST(postUrl, headers = postHeaders, body = body))
+                .execute().asJsoup()
+
+        val videoUrl = docFinal.selectFirst("a.novobotao.download")?.attr("href")
+
+        if (videoUrl == null) {
+            Log.d(tag, "Download link not found for $url")
+            return null
+        }
+
+        return Video(videoUrl, "$quality - File4Go", videoUrl)
+    }
+
+    private fun videosFromDownloadPage(url: String, epName: String): List<Video> {
+        Log.d(tag, "Extracting videos links for URL: $url")
+        val docDownload = client.newCall(GET(url)).execute().asJsoup()
+
+        val row = docDownload.select("table.downloadpag_episodios tr").firstOrNull {
+            it.text().contains(epName)
+        }
+
+        if (row == null) {
+            Log.d(tag, "Episode $epName not found in download page")
+            return emptyList()
+        }
+
+        val links = row.select("td").mapIndexedNotNull { index, el ->
+            val link = el.selectFirst("a") ?: return@mapIndexedNotNull null
+
+            object {
+                var quality = qualities.get(index - 1)
+                var url = link.attr("href")
+            }
+        }
+
+        Log.d(tag, "Found ${links.size} links for $epName")
+
+        return links.parallelMapNotNullBlocking {
+            if (!it.url.contains("file4go.net")) {
+                return@parallelMapNotNullBlocking null
+            }
+            videosFromFile4Go(it.url, it.quality)
+        }.reversed()
+    }
+
+    fun videosFromUrl(url: String, epName: String, quality: String = "Default"): List<Video> {
+        if (url.contains("file4go.net")) {
+            return listOfNotNull(videosFromFile4Go(url, quality))
+        }
+
+        return videosFromDownloadPage(url, epName)
+    }
+}
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 e6eeeeda..6c96aad9 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
@@ -6,11 +6,14 @@ import eu.kanade.tachiyomi.animesource.model.Video
 import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.POST
 import eu.kanade.tachiyomi.util.asJsoup
+import eu.kanade.tachiyomi.util.parallelMapNotNullBlocking
 import okhttp3.FormBody
 import okhttp3.Headers
+import okhttp3.HttpUrl.Companion.toHttpUrl
 import okhttp3.OkHttpClient
 import okhttp3.Request
-import okhttp3.Response
+import org.jsoup.nodes.Document
+import java.net.ProtocolException
 
 class AnitubeExtractor(
     private val headers: Headers,
@@ -20,6 +23,32 @@ class AnitubeExtractor(
 
     private val tag by lazy { javaClass.simpleName }
 
+    private data class VideoExists(
+        val exists: Boolean,
+        val code: Int,
+    )
+
+    private fun checkVideoExists(url: String): VideoExists {
+        try {
+            val request = Request.Builder()
+                .head()
+                .url(url)
+                .headers(headers)
+                .build()
+
+            val response = client.newCall(request).execute()
+
+            return VideoExists(response.isSuccessful, response.code)
+        } catch (e: ProtocolException) {
+            // There are a bug in the response that sometimes that the content is without headers
+            if (e.message?.contains("Unexpected status line") == true) {
+                return VideoExists(true, 200)
+            }
+        }
+
+        return VideoExists(false, 404)
+    }
+
     private fun getAdsUrl(
         serverUrl: String,
         thumbUrl: String,
@@ -28,15 +57,21 @@ class AnitubeExtractor(
     ): String {
         val videoName = serverUrl.split('/').last()
 
-        Log.d(tag, "Accessing the link $link")
-        val response = client.newCall(GET(link, headers = linkHeaders)).execute()
+        val finalLink =
+            if (link.startsWith("//")) {
+                "https:$link"
+            } else {
+                link
+            }
+        Log.d(tag, "Accessing the link $finalLink")
+        val response = client.newCall(GET(finalLink, headers = linkHeaders)).execute()
         val docLink = response.asJsoup()
 
         val refresh = docLink.selectFirst("meta[http-equiv=refresh]")?.attr("content")
 
         if (!refresh.isNullOrBlank()) {
             val newLink = refresh.substringAfter("=")
-            val newHeaders = linkHeaders.newBuilder().set("Referer", link).build()
+            val newHeaders = linkHeaders.newBuilder().set("Referer", finalLink).build()
             Log.d(tag, "Following link redirection to $newLink")
 
             return getAdsUrl(serverUrl, thumbUrl, newLink, newHeaders)
@@ -47,30 +82,32 @@ class AnitubeExtractor(
         Log.d(tag, "Final URL: $referer")
         Log.d(tag, "Fetching ADS URL")
 
-        val newHeaders = linkHeaders.newBuilder().set("Referer", referer).build()
+        val newHeaders =
+            linkHeaders.newBuilder().set("Referer", "https://${referer.toHttpUrl().host}/").build()
 
         try {
             val now = System.currentTimeMillis()
-            val adsUrl =
-                client.newCall(
-                    GET(
-                        "$SITE_URL/playerricas.php?name=apphd/$videoName&img=$thumbUrl&pais=pais=BR&time=$now&url=$serverUrl",
-                        headers = newHeaders,
-                    ),
-                )
-                    .execute()
-                    .body.string()
-                    .let {
-                        Regex("""ADS_URL\s*=\s*['"]([^'"]+)['"]""")
-                            .find(it)?.groups?.get(1)?.value
-                            ?: ""
-                    }
+            val body = client.newCall(
+                GET(
+                    "$SITE_URL?name=apphd/$videoName&img=$thumbUrl&pais=pais=BR&time=$now&url=$serverUrl",
+                    headers = newHeaders,
+                ),
+            )
+                .execute()
+                .body.string()
+
+            val adsUrl = body.let {
+                Regex("""ADS_URL\s*=\s*['"]([^'"]+)['"]""")
+                    .find(it)?.groups?.get(1)?.value
+                    ?: ""
+            }
 
             if (adsUrl.startsWith("http")) {
                 Log.d(tag, "ADS URL: $adsUrl")
                 return adsUrl
             }
         } catch (e: Exception) {
+            Log.e(tag, e.toString())
         }
 
         // Try default url
@@ -84,15 +121,9 @@ class AnitubeExtractor(
         if (authCode.isNotBlank()) {
             Log.d(tag, "AuthCode found in preferences")
 
-            val request = Request.Builder()
-                .head()
-                .url("${serverUrl}$authCode")
-                .headers(headers)
-                .build()
+            val response = checkVideoExists("${serverUrl}$authCode")
 
-            val response = client.newCall(request).execute()
-
-            if (response.isSuccessful || response.code == 500) {
+            if (response.exists || response.code == 500) {
                 Log.d(tag, "AuthCode is OK")
                 return authCode
             }
@@ -112,7 +143,7 @@ class AnitubeExtractor(
             .build()
 
         val newHeaders = headers.newBuilder()
-            .set("Referer", SITE_URL)
+            .set("Referer", "https://${SITE_URL.toHttpUrl().host}/")
             .add("Accept", "*/*")
             .add("Cache-Control", "no-cache")
             .add("Pragma", "no-cache")
@@ -165,8 +196,7 @@ class AnitubeExtractor(
         return authCode
     }
 
-    fun getVideoList(response: Response): List<Video> {
-        val doc = response.asJsoup()
+    fun getVideoList(doc: Document): List<Video> {
         val hasFHD = doc.selectFirst("div.abaItem:contains(FULLHD)") != null
         val serverUrl = doc.selectFirst("meta[itemprop=contentURL]")!!
             .attr("content")
@@ -188,16 +218,27 @@ class AnitubeExtractor(
 
         val authCode = getAuthCode(serverUrl, thumbUrl, firstLink)
 
-        return qualities.mapIndexed { index, quality ->
-            val path = paths[index]
-            val url = serverUrl.replace(type, path) + authCode
-            Video(url, quality, url, headers = headers)
-        }.reversed()
+        return qualities
+            .mapIndexed { index, quality ->
+                object {
+                    var path = paths[index]
+                    var url = serverUrl.replace(type, path) + authCode
+                    var quality = "$quality - Anitube"
+                }
+            }
+            .parallelMapNotNullBlocking {
+                if (!checkVideoExists(it.url).exists) {
+                    Log.d(tag, "Video not exists: ${it.url.substringBefore("?")}")
+                    return@parallelMapNotNullBlocking null
+                }
+                Video(it.url, it.quality, it.url, headers = headers)
+            }
+            .reversed()
     }
 
     companion object {
         private const val PREF_AUTHCODE_KEY = "authcode"
         private const val ADS_URL = "https://ads.anitube.vip"
-        private const val SITE_URL = "https://www.anitube.vip"
+        private const val SITE_URL = "https://www.anitube.vip/playerricas.php"
     }
 }
diff --git a/src/pt/hinatasoul/build.gradle b/src/pt/hinatasoul/build.gradle
index ff464aa0..084d175a 100644
--- a/src/pt/hinatasoul/build.gradle
+++ b/src/pt/hinatasoul/build.gradle
@@ -1,7 +1,7 @@
 ext {
     extName = 'Hinata Soul'
     extClass = '.HinataSoul'
-    extVersionCode = 8
+    extVersionCode = 9
 }
 
 apply from: "$rootDir/common.gradle"
diff --git a/src/pt/hinatasoul/src/eu/kanade/tachiyomi/animeextension/pt/hinatasoul/HinataSoul.kt b/src/pt/hinatasoul/src/eu/kanade/tachiyomi/animeextension/pt/hinatasoul/HinataSoul.kt
index 8e49face..3d636c45 100644
--- a/src/pt/hinatasoul/src/eu/kanade/tachiyomi/animeextension/pt/hinatasoul/HinataSoul.kt
+++ b/src/pt/hinatasoul/src/eu/kanade/tachiyomi/animeextension/pt/hinatasoul/HinataSoul.kt
@@ -4,6 +4,7 @@ import android.app.Application
 import androidx.preference.EditTextPreference
 import androidx.preference.ListPreference
 import androidx.preference.PreferenceScreen
+import eu.kanade.tachiyomi.animeextension.pt.hinatasoul.extractors.HinataSoulDownloadExtractor
 import eu.kanade.tachiyomi.animeextension.pt.hinatasoul.extractors.HinataSoulExtractor
 import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
 import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@@ -15,6 +16,7 @@ import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
 import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.awaitSuccess
 import eu.kanade.tachiyomi.util.asJsoup
+import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
 import okhttp3.Response
 import org.jsoup.nodes.Document
 import org.jsoup.nodes.Element
@@ -67,7 +69,11 @@ class HinataSoul : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
     override fun latestUpdatesNextPageSelector() = null
 
     // =============================== Search ===============================
-    override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage {
+    override suspend fun getSearchAnime(
+        page: Int,
+        query: String,
+        filters: AnimeFilterList,
+    ): AnimesPage {
         return if (query.startsWith(PREFIX_SEARCH)) {
             val slug = query.removePrefix(PREFIX_SEARCH)
             client.newCall(GET("$baseUrl/animes/$slug"))
@@ -156,16 +162,47 @@ class HinataSoul : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
         val title = element.attr("title")
         setUrlWithoutDomain(element.attr("href"))
         name = title
-        episode_number = title.substringBeforeLast(" - FINAL").substringAfterLast(" ").toFloatOrNull() ?: 0F
+        episode_number =
+            title.substringBeforeLast(" - FINAL").substringAfterLast(" ").toFloatOrNull() ?: 0F
         date_upload = element.selectFirst("div.lancaster_episodio_info_data")!!
             .text()
             .toDate()
     }
 
     // ============================ Video Links =============================
-    private val extractor by lazy { HinataSoulExtractor(headers, client, preferences) }
+    private val hinataExtractor by lazy { HinataSoulExtractor(headers, client, preferences) }
+    private val downloadExtractor by lazy { HinataSoulDownloadExtractor(headers, client) }
 
-    override fun videoListParse(response: Response) = extractor.getVideoList(response)
+    override fun videoListParse(response: Response): List<Video> {
+        val document = response.asJsoup()
+
+        val links = mutableListOf(document.location())
+
+        val downloadsLinks = document.select("div.reportaBox .reportContent > a")
+
+        downloadsLinks.forEach {
+            it.attr("href")?.let {
+                links.add(it)
+            }
+        }
+
+        val epName = document.selectFirst("meta[itemprop=name]")!!.attr("content")
+
+        return links.parallelCatchingFlatMapBlocking { url ->
+            when {
+                url.contains("file4go.net") -> {
+                    val quality =
+                        downloadsLinks.first { it.attr("href") == url }
+                            .textNodes().first().toString()
+                            .trim().replace(" ", "")
+
+                    downloadExtractor.videosFromUrl(url, epName, quality)
+                }
+
+                else -> hinataExtractor.getVideoList(document)
+            }
+        }
+    }
 
     override fun videoListSelector() = throw UnsupportedOperationException()
     override fun videoFromElement(element: Element) = throw UnsupportedOperationException()
@@ -246,7 +283,10 @@ class HinataSoul : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
     override fun List<Video>.sort(): List<Video> {
         val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!
         return sortedWith(
-            compareBy { it.quality.contains(quality) },
+            compareBy<Video>(
+                { it.quality.startsWith(quality) },
+                { PREF_QUALITY_VALUES.indexOf(it.quality.substringBefore(" ")) },
+            ).thenByDescending { it.quality },
         ).reversed()
     }
 
diff --git a/src/pt/hinatasoul/src/eu/kanade/tachiyomi/animeextension/pt/hinatasoul/extractors/HinataSoulDownloadExtractor.kt b/src/pt/hinatasoul/src/eu/kanade/tachiyomi/animeextension/pt/hinatasoul/extractors/HinataSoulDownloadExtractor.kt
new file mode 100644
index 00000000..71b47df9
--- /dev/null
+++ b/src/pt/hinatasoul/src/eu/kanade/tachiyomi/animeextension/pt/hinatasoul/extractors/HinataSoulDownloadExtractor.kt
@@ -0,0 +1,98 @@
+package eu.kanade.tachiyomi.animeextension.pt.hinatasoul.extractors
+
+import android.util.Log
+import eu.kanade.tachiyomi.animesource.model.Video
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.network.POST
+import eu.kanade.tachiyomi.util.asJsoup
+import eu.kanade.tachiyomi.util.parallelMapNotNullBlocking
+import okhttp3.FormBody
+import okhttp3.Headers
+import okhttp3.OkHttpClient
+
+class HinataSoulDownloadExtractor(
+    private val headers: Headers,
+    private val client: OkHttpClient,
+) {
+
+    private val qualities = listOf("SD", "HD", "FULLHD")
+    private val tag by lazy { javaClass.simpleName }
+
+    private fun videosFromFile4Go(url: String, quality: String): Video? {
+        Log.d(tag, "Checking download for $url")
+        val docDownload = client.newCall(GET(url)).execute().asJsoup()
+
+        val form =
+            docDownload.selectFirst("button.download")?.closest("form")
+
+        if (form == null) {
+            Log.d(tag, "Download form not found for $url")
+            return null
+        }
+
+        val body = FormBody.Builder().apply {
+            form.select("input[name]").forEach {
+                add(it.attr("name"), it.attr("value"))
+            }
+        }.build()
+
+        val postUrl = form.attr("action")
+
+        val postHeaders = headers.newBuilder()
+            .set("Referer", url)
+            .build()
+
+        val docFinal =
+            client.newCall(POST(postUrl, headers = postHeaders, body = body))
+                .execute().asJsoup()
+
+        val videoUrl = docFinal.selectFirst("a.novobotao.download")?.attr("href")
+
+        if (videoUrl == null) {
+            Log.d(tag, "Download link not found for $url")
+            return null
+        }
+
+        return Video(videoUrl, "$quality - File4Go", videoUrl)
+    }
+
+    private fun videosFromDownloadPage(url: String, epName: String): List<Video> {
+        Log.d(tag, "Extracting videos links for URL: $url")
+        val docDownload = client.newCall(GET(url)).execute().asJsoup()
+
+        val row = docDownload.select("table.downloadpag_episodios tr").firstOrNull {
+            it.text().contains(epName)
+        }
+
+        if (row == null) {
+            Log.d(tag, "Episode $epName not found in download page")
+            return emptyList()
+        }
+
+        val links = row.select("td").mapIndexedNotNull { index, el ->
+            val link = el.selectFirst("a") ?: return@mapIndexedNotNull null
+
+            object {
+                var quality = qualities.get(index - 1)
+                var url = link.attr("href")
+            }
+        }
+
+        Log.d(tag, "Found ${links.size} links for $epName")
+
+        return links.parallelMapNotNullBlocking {
+            if (!it.url.contains("file4go.net")) {
+                return@parallelMapNotNullBlocking null
+            }
+            videosFromFile4Go(it.url, it.quality)
+        }.reversed()
+    }
+
+    fun videosFromUrl(url: String, epName: String, quality: String = "Default"): List<Video> {
+        if (url.contains("file4go.net")) {
+            return listOfNotNull(videosFromFile4Go(url, quality))
+        }
+
+        return videosFromDownloadPage(url, epName)
+    }
+}
diff --git a/src/pt/hinatasoul/src/eu/kanade/tachiyomi/animeextension/pt/hinatasoul/extractors/HinataSoulExtractor.kt b/src/pt/hinatasoul/src/eu/kanade/tachiyomi/animeextension/pt/hinatasoul/extractors/HinataSoulExtractor.kt
index 4d4897d1..abb6bc8d 100644
--- a/src/pt/hinatasoul/src/eu/kanade/tachiyomi/animeextension/pt/hinatasoul/extractors/HinataSoulExtractor.kt
+++ b/src/pt/hinatasoul/src/eu/kanade/tachiyomi/animeextension/pt/hinatasoul/extractors/HinataSoulExtractor.kt
@@ -6,11 +6,14 @@ import eu.kanade.tachiyomi.animesource.model.Video
 import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.POST
 import eu.kanade.tachiyomi.util.asJsoup
+import eu.kanade.tachiyomi.util.parallelMapNotNullBlocking
 import okhttp3.FormBody
 import okhttp3.Headers
+import okhttp3.HttpUrl.Companion.toHttpUrl
 import okhttp3.OkHttpClient
 import okhttp3.Request
-import okhttp3.Response
+import org.jsoup.nodes.Document
+import java.net.ProtocolException
 
 class HinataSoulExtractor(
     private val headers: Headers,
@@ -20,6 +23,32 @@ class HinataSoulExtractor(
 
     private val tag by lazy { javaClass.simpleName }
 
+    private data class VideoExists(
+        val exists: Boolean,
+        val code: Int,
+    )
+
+    private fun checkVideoExists(url: String): VideoExists {
+        try {
+            val request = Request.Builder()
+                .head()
+                .url(url)
+                .headers(headers)
+                .build()
+
+            val response = client.newCall(request).execute()
+
+            return VideoExists(response.isSuccessful, response.code)
+        } catch (e: ProtocolException) {
+            // There are a bug in the response that sometimes that the content is without headers
+            if (e.message?.contains("Unexpected status line") == true) {
+                return VideoExists(true, 200)
+            }
+        }
+
+        return VideoExists(false, 404)
+    }
+
     private fun getAdsUrl(
         serverUrl: String,
         thumbUrl: String,
@@ -28,15 +57,21 @@ class HinataSoulExtractor(
     ): String {
         val videoName = serverUrl.split('/').last()
 
-        Log.d(tag, "Accessing the link $link")
-        val response = client.newCall(GET(link, headers = linkHeaders)).execute()
+        val finalLink =
+            if (link.startsWith("//")) {
+                "https:$link"
+            } else {
+                link
+            }
+        Log.d(tag, "Accessing the link $finalLink")
+        val response = client.newCall(GET(finalLink, headers = linkHeaders)).execute()
         val docLink = response.asJsoup()
 
         val refresh = docLink.selectFirst("meta[http-equiv=refresh]")?.attr("content")
 
         if (!refresh.isNullOrBlank()) {
             val newLink = refresh.substringAfter("=")
-            val newHeaders = linkHeaders.newBuilder().set("Referer", link).build()
+            val newHeaders = linkHeaders.newBuilder().set("Referer", finalLink).build()
             Log.d(tag, "Following link redirection to $newLink")
 
             return getAdsUrl(serverUrl, thumbUrl, newLink, newHeaders)
@@ -47,30 +82,31 @@ class HinataSoulExtractor(
         Log.d(tag, "Final URL: $referer")
         Log.d(tag, "Fetching ADS URL")
 
-        val newHeaders = linkHeaders.newBuilder().set("Referer", referer).build()
+        val newHeaders = linkHeaders.newBuilder().set("Referer", "https://${referer.toHttpUrl().host}/").build()
 
         try {
             val now = System.currentTimeMillis()
-            val adsUrl =
-                client.newCall(
-                    GET(
-                        "$SITE_URL/playerricas.php?name=apphd/$videoName&img=$thumbUrl&pais=pais=BR&time=$now&url=$serverUrl",
-                        headers = newHeaders,
-                    ),
-                )
-                    .execute()
-                    .body.string()
-                    .let {
-                        Regex("""ADS_URL\s*=\s*['"]([^'"]+)['"]""")
-                            .find(it)?.groups?.get(1)?.value
-                            ?: ""
-                    }
+            val body = client.newCall(
+                GET(
+                    "$SITE_URL?name=apphd/$videoName&img=$thumbUrl&pais=pais=BR&time=$now&url=$serverUrl",
+                    headers = newHeaders,
+                ),
+            )
+                .execute()
+                .body.string()
+
+            val adsUrl = body.let {
+                Regex("""ADS_URL\s*=\s*['"]([^'"]+)['"]""")
+                    .find(it)?.groups?.get(1)?.value
+                    ?: ""
+            }
 
             if (adsUrl.startsWith("http")) {
                 Log.d(tag, "ADS URL: $adsUrl")
                 return adsUrl
             }
         } catch (e: Exception) {
+            Log.e(tag, e.toString())
         }
 
         // Try default url
@@ -84,15 +120,9 @@ class HinataSoulExtractor(
         if (authCode.isNotBlank()) {
             Log.d(tag, "AuthCode found in preferences")
 
-            val request = Request.Builder()
-                .head()
-                .url("${serverUrl}$authCode")
-                .headers(headers)
-                .build()
+            val response = checkVideoExists("${serverUrl}$authCode")
 
-            val response = client.newCall(request).execute()
-
-            if (response.isSuccessful || response.code == 500) {
+            if (response.exists || response.code == 500) {
                 Log.d(tag, "AuthCode is OK")
                 return authCode
             }
@@ -112,7 +142,7 @@ class HinataSoulExtractor(
             .build()
 
         val newHeaders = headers.newBuilder()
-            .set("Referer", SITE_URL)
+            .set("Referer", "https://${SITE_URL.toHttpUrl().host}/")
             .add("Accept", "*/*")
             .add("Cache-Control", "no-cache")
             .add("Pragma", "no-cache")
@@ -165,8 +195,7 @@ class HinataSoulExtractor(
         return authCode
     }
 
-    fun getVideoList(response: Response): List<Video> {
-        val doc = response.asJsoup()
+    fun getVideoList(doc: Document): List<Video> {
         val hasFHD = doc.selectFirst("div.abaItem:contains(FULLHD)") != null
         val serverUrl = doc.selectFirst("meta[itemprop=contentURL]")!!
             .attr("content")
@@ -188,16 +217,27 @@ class HinataSoulExtractor(
 
         val authCode = getAuthCode(serverUrl, thumbUrl, firstLink)
 
-        return qualities.mapIndexed { index, quality ->
-            val path = paths[index]
-            val url = serverUrl.replace(type, path) + authCode
-            Video(url, quality, url, headers = headers)
-        }.reversed()
+        return qualities
+            .mapIndexed { index, quality ->
+                object {
+                    var path = paths[index]
+                    var url = serverUrl.replace(type, path) + authCode
+                    var quality = "$quality - Anitube"
+                }
+            }
+            .parallelMapNotNullBlocking {
+                if (!checkVideoExists(it.url).exists) {
+                    Log.d(tag, "Video not exists: ${it.url.substringBefore("?")}")
+                    return@parallelMapNotNullBlocking null
+                }
+                Video(it.url, it.quality, it.url, headers = headers)
+            }
+            .reversed()
     }
 
     companion object {
         private const val PREF_AUTHCODE_KEY = "authcode"
         private const val ADS_URL = "https://ads.anitube.vip"
-        private const val SITE_URL = "https://www.anitube.vip"
+        private const val SITE_URL = "https://www.hinatasoul.com/luffy.php"
     }
 }