diff --git a/src/en/uhdmovies/build.gradle b/src/en/uhdmovies/build.gradle index 40fd647cc..a46171a5e 100644 --- a/src/en/uhdmovies/build.gradle +++ b/src/en/uhdmovies/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'UHD Movies' pkgNameSuffix = 'en.uhdmovies' extClass = '.UHDMovies' - extVersionCode = 11 + extVersionCode = 12 libVersion = '13' } diff --git a/src/en/uhdmovies/src/eu/kanade/tachiyomi/animeextension/en/uhdmovies/UHDMovies.kt b/src/en/uhdmovies/src/eu/kanade/tachiyomi/animeextension/en/uhdmovies/UHDMovies.kt index 8bd9340a5..f9d1d5b1a 100644 --- a/src/en/uhdmovies/src/eu/kanade/tachiyomi/animeextension/en/uhdmovies/UHDMovies.kt +++ b/src/en/uhdmovies/src/eu/kanade/tachiyomi/animeextension/en/uhdmovies/UHDMovies.kt @@ -12,7 +12,6 @@ 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.util.asJsoup import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async @@ -24,11 +23,8 @@ import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -import okhttp3.FormBody -import okhttp3.Headers import okhttp3.OkHttpClient import okhttp3.Request -import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.jsoup.nodes.Element import rx.Observable @@ -55,12 +51,10 @@ class UHDMovies : ConfigurableAnimeSource, ParsedAnimeHttpSource() { Injekt.get().getSharedPreferences("source_$id", 0x0000) } - private var currentBaseUrl: String - - init { + private val currentBaseUrl by lazy { runBlocking { withContext(Dispatchers.Default) { - currentBaseUrl = client.newBuilder() + client.newBuilder() .followRedirects(false) .build() .newCall(GET("$baseUrl/")).execute().let { resp -> @@ -135,7 +129,7 @@ class UHDMovies : ConfigurableAnimeSource, ParsedAnimeHttpSource() { override fun fetchEpisodeList(anime: SAnime): Observable> { val resp = client.newCall(GET(currentBaseUrl + anime.url)).execute().asJsoup() val episodeList = mutableListOf() - val episodeElements = resp.select("p:has(a[href*=?id]):has(a[class*=maxbutton])[style*=center],p:has(a[href*=?id]):has(span.maxbutton-1-center)") + val episodeElements = resp.select("p:has(a[href*=r?key=]):has(a[class*=maxbutton])[style*=center]") val qualityRegex = "\\d{3,4}p".toRegex(RegexOption.IGNORE_CASE) val firstText = episodeElements.first()!!.text() if (firstText.contains("Episode", true) || @@ -144,17 +138,26 @@ class UHDMovies : ConfigurableAnimeSource, ParsedAnimeHttpSource() { ) { episodeElements.map { row -> val prevP = row.previousElementSibling()!! - val seasonRegex = "[ .]S(?:eason)?[ .]?(\\d{1,2})[ .]".toRegex(RegexOption.IGNORE_CASE) + val seasonRegex = "[ .]?S(?:eason)?[ .]?(\\d{1,2})[ .]?".toRegex(RegexOption.IGNORE_CASE) + val partRegex = "Part ?(\\d{1,2})".toRegex(RegexOption.IGNORE_CASE) val result = seasonRegex.find(prevP.text()) - + var part = "" val season = ( - result?.groups?.get(1)?.value ?: let { + result?.groups?.get(1)?.value?.also { + part = partRegex.find(prevP.text())?.groups?.get(1)?.value ?: "" + } ?: let { val prevPre = row.previousElementSiblings().prev("pre,div.mks_separator") val preResult = seasonRegex.find(prevPre.first()!!.text()) - preResult?.groups?.get(1)?.value ?: let { + preResult?.groups?.get(1)?.value?.also { + part = partRegex.find(prevPre.first()!!.text())?.groups?.get(1)?.value ?: "" + } ?: let { val title = resp.select("h1.entry-title") - val titleResult = "[ .\\[(]S(?:eason)?[ .]?(\\d{1,2})[ .\\])]".toRegex(RegexOption.IGNORE_CASE).find(title.text()) - titleResult?.groups?.get(1)?.value ?: "-1" + val titleResult = "[ .\\[(]?S(?:eason)?[ .]?(\\d{1,2})[ .\\])]?" + .toRegex(RegexOption.IGNORE_CASE) + .find(title.text()) + titleResult?.groups?.get(1)?.value?.also { + part = partRegex.find(title.text())?.groups?.get(1)?.value ?: "" + } ?: "-1" } } ).replaceFirst("^0+(?!$)".toRegex(), "") @@ -174,13 +177,14 @@ class UHDMovies : ConfigurableAnimeSource, ParsedAnimeHttpSource() { ?.replace("Episode", "", true) ?.trim()?.toIntOrNull() ?: (index + 1) Triple( - season + "_$episode", + season + "_$episode" + "_$part", linkElement.attr("href") ?: return@mapIndexed null, quality, ) }.filterNotNull() }.flatten().groupBy { it.first }.map { group -> - val (season, episode) = group.key.split("_") + val (season, episode, part) = group.key.split("_") + val partText = if (part.isBlank()) "" else " Pt $part" episodeList.add( SEpisode.create().apply { url = EpLinks( @@ -188,7 +192,7 @@ class UHDMovies : ConfigurableAnimeSource, ParsedAnimeHttpSource() { EpUrl(url = it.second, quality = it.third) }, ).toJson() - name = "Season $season Ep $episode" + name = "Season $season$partText Ep $episode" episode_number = episode.toFloat() }, ) @@ -284,31 +288,7 @@ class UHDMovies : ConfigurableAnimeSource, ParsedAnimeHttpSource() { // ============================= Utilities ============================== private fun extractVideo(epUrl: EpUrl): Pair, String> { - val postLink = epUrl.url.substringBefore("?id=").substringAfter("/?") - val formData = FormBody.Builder().add("_wp_http_c", epUrl.url.substringAfter("?id=")).build() - val response = client.newCall(POST(postLink, body = formData)).execute().body.string() - val (longC, catC, _) = getCookiesDetail(response) - val cookieHeader = Headers.headersOf("Cookie", "$longC; $catC") - val parsedSoup = Jsoup.parse(response) - val link = parsedSoup.selectFirst("center > a")!!.attr("href") - - val response2 = client.newCall(GET(link, cookieHeader)).execute().body.string() - val (longC2, _, postC) = getCookiesDetail(response2) - val cookieHeader2 = Headers.headersOf("Cookie", "$catC; $longC2; $postC") - val parsedSoup2 = Jsoup.parse(response2) - val link2 = parsedSoup2.selectFirst("center > a")!!.attr("href") - - val tokenResp = client.newCall(GET(link2, cookieHeader2)).execute().body.string() - val goToken = tokenResp.substringAfter("?go=").substringBefore("\"") - val tokenUrl = "$postLink?go=$goToken" - val newLongC = "$goToken=" + longC2.substringAfter("=") - val tokenCookie = Headers.headersOf("Cookie", "$catC; rdst_post=; $newLongC") - - val noRedirectClient = client.newBuilder().followRedirects(false).build() - val tokenResponse = noRedirectClient.newCall(GET(tokenUrl, tokenCookie)).execute().asJsoup() - val redirectUrl = tokenResponse.select("meta[http-equiv=refresh]").attr("content") - .substringAfter("url=").substringBefore("\"") - val mediaResponse = noRedirectClient.newCall(GET(redirectUrl)).execute() + val mediaResponse = client.newCall(GET(epUrl.url)).execute() val path = mediaResponse.body.string().substringAfter("replace(\"").substringBefore("\"") if (path == "/404") return Pair(emptyList(), "") val mediaUrl = "https://" + mediaResponse.request.url.host + path @@ -322,30 +302,6 @@ class UHDMovies : ConfigurableAnimeSource, ParsedAnimeHttpSource() { return Pair(videoList, mediaUrl) } - private fun getCookiesDetail(page: String): Triple { - val cat = "rdst_cat" - val post = "rdst_post" - val longC = page.substringAfter(".setTime") - .substringAfter("document.cookie = \"") - .substringBefore("\"") - .substringBefore(";") - val catC = if (page.contains("$cat=")) { - page.substringAfterLast("$cat=") - .substringBefore(";").let { - "$cat=$it" - } - } else { "" } - - val postC = if (page.contains("$post=")) { - page.substringAfterLast("$post=") - .substringBefore(";").let { - "$post=$it" - } - } else { "" } - - return Triple(longC, catC, postC) - } - private val sizeRegex = "\\[((?:.(?!\\[))+)] *\$".toRegex(RegexOption.IGNORE_CASE) private fun extractWorkerLinks(mediaUrl: String, quality: String, type: Int): List