From 04dd470753df0218ba878e4717f10c3d413e7bf3 Mon Sep 17 00:00:00 2001 From: CakesTwix Date: Sat, 18 Feb 2023 15:13:46 +0200 Subject: [PATCH 01/11] Anitubeinua: fork from Eneyida --- AnitubeinuaProvider/build.gradle.kts | 25 +++ .../src/main/AndroidManifest.xml | 2 + .../com/lagradost/AnitubeinuaProvider.kt | 187 ++++++++++++++++++ .../lagradost/AnitubeinuaProviderPlugin.kt | 13 ++ .../kotlin/com/lagradost/models/PlayerJson.kt | 22 +++ 5 files changed, 249 insertions(+) create mode 100644 AnitubeinuaProvider/build.gradle.kts create mode 100644 AnitubeinuaProvider/src/main/AndroidManifest.xml create mode 100644 AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt create mode 100644 AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProviderPlugin.kt create mode 100644 AnitubeinuaProvider/src/main/kotlin/com/lagradost/models/PlayerJson.kt diff --git a/AnitubeinuaProvider/build.gradle.kts b/AnitubeinuaProvider/build.gradle.kts new file mode 100644 index 0000000..c4228cc --- /dev/null +++ b/AnitubeinuaProvider/build.gradle.kts @@ -0,0 +1,25 @@ +// use an integer for version numbers +version = 1 + + +cloudstream { + language = "uk" + // All of these properties are optional, you can safely remove them + + description = "На нашому сайті ви можете подивитися аніме онлайн українською безкоштовно. Великий список аніме онлайн тільки у нас." + authors = listOf("CakesTwix") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 3 // will be 3 if unspecified + tvTypes = listOf( + "Anime", + ) + + iconUrl = "https://www.google.com/s2/favicons?domain=anitube.in.ua&sz=%size%" +} \ No newline at end of file diff --git a/AnitubeinuaProvider/src/main/AndroidManifest.xml b/AnitubeinuaProvider/src/main/AndroidManifest.xml new file mode 100644 index 0000000..29aec9d --- /dev/null +++ b/AnitubeinuaProvider/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt new file mode 100644 index 0000000..22f64ef --- /dev/null +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt @@ -0,0 +1,187 @@ +package com.lagradost + +import com.lagradost.models.PlayerJson +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addActors +import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.M3u8Helper +import org.jsoup.nodes.Element + +class AnitubeinuaProvider : MainAPI() { + + // Basic Info + override var mainUrl = "https://eneyida.tv" + override var name = "Anitubeinua" + override val hasMainPage = true + override var lang = "uk" + override val hasDownloadSupport = true + override val supportedTypes = setOf( + TvType.Movie, + TvType.TvSeries, + TvType.Anime, + ) + + // Sections + override val mainPage = mainPageOf( + "$mainUrl/films/page/" to "Фільми", + "$mainUrl/series/page/" to "Серіали", + "$mainUrl/anime/page/" to "Аніме", + "$mainUrl/cartoon/page/" to "Мультфільми", + "$mainUrl/cartoon-series/page/" to "Мультсеріали", + ) + + override suspend fun getMainPage( + page: Int, + request: MainPageRequest + ): HomePageResponse { + var document = app.get(request.data + page).document + + val home = document.select("article.short").map { + it.toSearchResponse() + } + return newHomePageResponse(request.name, home) + } + + private fun Element.toSearchResponse(): SearchResponse { + val title = this.selectFirst("a.short_title")?.text()?.trim().toString() + val href = this.selectFirst("a.short_title")?.attr("href").toString() + val posterUrl = mainUrl + this.selectFirst("a.short_img img")?.attr("data-src") + + return newMovieSearchResponse(title, href, TvType.Movie) { + this.posterUrl = posterUrl + } + + } + + override suspend fun search(query: String): List { + val document = app.post( + url = "$mainUrl", + data = mapOf( + "do" to "search", + "subaction" to "search", + "story" to query.replace(" ", "+") + ) + ).document + + return document.select("article.short").map { + it.toSearchResponse() + } + } + + // Detailed information + override suspend fun load(url: String): LoadResponse { + val document = app.get(url).document + // Parse info + val full_info = document.select(".full_info li") + val title = document.selectFirst("div.full_header-title h1")?.text()?.trim().toString() + val poster = mainUrl + document.selectFirst(".full_content-poster img")?.attr("src") + val tags = full_info[1].select("a").map { it.text() } + val year = full_info[0].select("a").text().toIntOrNull() + val playerUrl = document.select(".tabs_b.visible iframe").attr("src") + + val tvType = if (tags.contains("фільм") or playerUrl.contains("/vod/")) TvType.Movie else TvType.TvSeries + val description = document.selectFirst(".full_content-desc p")?.text()?.trim() + val trailer = document.selectFirst("div#trailer_place iframe")?.attr("src").toString() + val rating = document.selectFirst(".r_kp span, .r_imdb span")?.text().toRatingInt() + val actors = full_info[4].select("a").map { it.text() } + + val recommendations = document.select(".short.related_item").map { + it.toSearchResponse() + } + + // Return to app + // Parse Episodes as Series + return if (tvType == TvType.TvSeries) { + var episodes: List = emptyList() + val playerRawJson = app.get(playerUrl).document.select("script").html() + .substringAfterLast("file:\'") + .substringBefore("\',") + + tryParseJson>(playerRawJson)?.map { dubs -> // Dubs + for(season in dubs.folder){ // Seasons + for(episode in season.folder){ // Episodes + episodes = episodes.plus( + Episode( + "${season.title}, ${episode.title}, $playerUrl", + episode.title, + season.title.replace(" Сезон ","").toIntOrNull(), + episode.title.replace("Серія ","").toIntOrNull(), + episode.poster + ) + ) + } + } + } + newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { + this.posterUrl = poster + this.year = year + this.plot = description + this.tags = tags + this.rating = rating + addActors(actors) + this.recommendations = recommendations + addTrailer(trailer) + } + } else { // Parse as Movie. + newMovieLoadResponse(title, url, TvType.Movie, "$title, $playerUrl") { + this.posterUrl = poster + this.year = year + this.plot = description + this.tags = tags + this.rating = rating + addActors(actors) + this.recommendations = recommendations + addTrailer(trailer) + } + } + } + + // It works when I click to view the series + override suspend fun loadLinks( + data: String, // (Serisl) [Season, Episode, Player Url] | (Film) [Title, Player Url] + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + val dataList = data.split(", ") + + // Its film, parse one m3u8 + if(dataList.size == 2){ + val m3u8Url = app.get(dataList[1]).document.select("script").html() + .substringAfterLast("file:\"") + .substringBefore("\",") + M3u8Helper.generateM3u8( + source = dataList[0], + streamUrl = m3u8Url, + referer = "https://tortuga.wtf/" + ).forEach(callback) + + return true + } + + val playerRawJson = app.get(dataList[2]).document.select("script").html() + .substringAfterLast("file:\'") + .substringBefore("\',") + + tryParseJson>(playerRawJson)?.map { dubs -> // Dubs + for(season in dubs.folder){ // Seasons + if(season.title == dataList[0]){ + for(episode in season.folder){ // Episodes + if(episode.title == dataList[1]){ + // Add as source + M3u8Helper.generateM3u8( + source = dubs.title, + streamUrl = episode.file, + referer = "https://tortuga.wtf/" + ).forEach(callback) + } + } + } + } + } + return true + } + +} \ No newline at end of file diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProviderPlugin.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProviderPlugin.kt new file mode 100644 index 0000000..e67f482 --- /dev/null +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProviderPlugin.kt @@ -0,0 +1,13 @@ +package com.lagradost + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class AnitubeinuaProviderPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(AnitubeinuaProvider()) + } +} \ No newline at end of file diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/models/PlayerJson.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/models/PlayerJson.kt new file mode 100644 index 0000000..163dd77 --- /dev/null +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/models/PlayerJson.kt @@ -0,0 +1,22 @@ +package com.lagradost.models + +data class PlayerJson ( + + val title : String, + val folder : List +) + +data class Season ( + + val title : String, + val folder : List +) + +data class Episode ( + + val title : String, + val file : String, + val id : String, + val poster : String, + val subtitle : String, +) From 80800dc8ba2b0be7f247db51687093a7a16e261e Mon Sep 17 00:00:00 2001 From: CakesTwix Date: Sun, 19 Feb 2023 10:26:26 +0200 Subject: [PATCH 02/11] Anitubeinua: Parse main and impl. load --- .../com/lagradost/AnitubeinuaProvider.kt | 105 +++++++----------- 1 file changed, 39 insertions(+), 66 deletions(-) diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt index 22f64ef..33b0057 100644 --- a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt @@ -1,9 +1,11 @@ package com.lagradost +import android.util.Log import com.lagradost.models.PlayerJson import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addActors import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer +import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.M3u8Helper @@ -12,24 +14,20 @@ import org.jsoup.nodes.Element class AnitubeinuaProvider : MainAPI() { // Basic Info - override var mainUrl = "https://eneyida.tv" + override var mainUrl = "https://anitube.in.ua" override var name = "Anitubeinua" override val hasMainPage = true override var lang = "uk" override val hasDownloadSupport = true override val supportedTypes = setOf( - TvType.Movie, - TvType.TvSeries, + TvType.AnimeMovie, TvType.Anime, ) // Sections override val mainPage = mainPageOf( - "$mainUrl/films/page/" to "Фільми", - "$mainUrl/series/page/" to "Серіали", - "$mainUrl/anime/page/" to "Аніме", - "$mainUrl/cartoon/page/" to "Мультфільми", - "$mainUrl/cartoon-series/page/" to "Мультсеріали", + "$mainUrl/anime/page/" to "Нові", + "$mainUrl/f/sort=rating/order=desc/page/" to "Популярне", ) override suspend fun getMainPage( @@ -38,16 +36,16 @@ class AnitubeinuaProvider : MainAPI() { ): HomePageResponse { var document = app.get(request.data + page).document - val home = document.select("article.short").map { + val home = document.select(".story").map { it.toSearchResponse() } return newHomePageResponse(request.name, home) } private fun Element.toSearchResponse(): SearchResponse { - val title = this.selectFirst("a.short_title")?.text()?.trim().toString() - val href = this.selectFirst("a.short_title")?.attr("href").toString() - val posterUrl = mainUrl + this.selectFirst("a.short_img img")?.attr("data-src") + val title = this.selectFirst(".story_c h2 a")?.text()?.trim().toString() + val href = this.selectFirst(".story_c h2 a")?.attr("href").toString() + val posterUrl = mainUrl + this.selectFirst(".story_c_l span.story_post img")?.attr("src") return newMovieSearchResponse(title, href, TvType.Movie) { this.posterUrl = posterUrl @@ -73,71 +71,46 @@ class AnitubeinuaProvider : MainAPI() { // Detailed information override suspend fun load(url: String): LoadResponse { val document = app.get(url).document + + var someInfo = document.select("div.story_c_r")[1] + // Parse info - val full_info = document.select(".full_info li") - val title = document.selectFirst("div.full_header-title h1")?.text()?.trim().toString() - val poster = mainUrl + document.selectFirst(".full_content-poster img")?.attr("src") - val tags = full_info[1].select("a").map { it.text() } - val year = full_info[0].select("a").text().toIntOrNull() - val playerUrl = document.select(".tabs_b.visible iframe").attr("src") + val title = document.selectFirst(".story_c h2")?.text()?.trim().toString() + val poster = mainUrl + document.selectFirst(".story_c_left span.story_post img")?.attr("src") + val tags = someInfo.select("noindex a").html().split("\n").map { it } + val year = someInfo.select("strong:contains(Рік випуску аніме:)").next().html().toIntOrNull() - val tvType = if (tags.contains("фільм") or playerUrl.contains("/vod/")) TvType.Movie else TvType.TvSeries - val description = document.selectFirst(".full_content-desc p")?.text()?.trim() - val trailer = document.selectFirst("div#trailer_place iframe")?.attr("src").toString() - val rating = document.selectFirst(".r_kp span, .r_imdb span")?.text().toRatingInt() - val actors = full_info[4].select("a").map { it.text() } + val tvType = TvType.Anime + val description = document.selectFirst("div.my-text")?.text()?.trim() + // val author = someInfo.select("strong:contains(Студія:)").next().html() + val rating = document.selectFirst(".lexington-box > div:last-child span")?.text().toRatingInt() - val recommendations = document.select(".short.related_item").map { + val recommendations = document.select(".horizontal ul").map { it.toSearchResponse() } // Return to app - // Parse Episodes as Series - return if (tvType == TvType.TvSeries) { - var episodes: List = emptyList() - val playerRawJson = app.get(playerUrl).document.select("script").html() - .substringAfterLast("file:\'") - .substringBefore("\',") + // 12 - json with episodes + // Players, Episodes, Number of episodes + // TODO: Parse Episodes + val playerScriptJson = document.select("script")[12].html().substringAfterLast(".init(").substringBefore(");") + val playerNames = playerScriptJson.substringAfterLast("],") + val numberOfEpisodes = playerScriptJson.substringAfterLast(",") + Log.d("load-debug", playerScriptJson.substringAfterLast(",")) - tryParseJson>(playerRawJson)?.map { dubs -> // Dubs - for(season in dubs.folder){ // Seasons - for(episode in season.folder){ // Episodes - episodes = episodes.plus( - Episode( - "${season.title}, ${episode.title}, $playerUrl", - episode.title, - season.title.replace(" Сезон ","").toIntOrNull(), - episode.title.replace("Серія ","").toIntOrNull(), - episode.poster - ) - ) - } - } - } - newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { - this.posterUrl = poster - this.year = year - this.plot = description - this.tags = tags - this.rating = rating - addActors(actors) - this.recommendations = recommendations - addTrailer(trailer) - } - } else { // Parse as Movie. - newMovieLoadResponse(title, url, TvType.Movie, "$title, $playerUrl") { - this.posterUrl = poster - this.year = year - this.plot = description - this.tags = tags - this.rating = rating - addActors(actors) - this.recommendations = recommendations - addTrailer(trailer) - } + var episodes: List = emptyList() + + return newTvSeriesLoadResponse(title, url, tvType, episodes) { + this.posterUrl = poster + this.year = year + this.plot = description + this.tags = tags + this.rating = rating + this.recommendations = recommendations } } + // It works when I click to view the series override suspend fun loadLinks( data: String, // (Serisl) [Season, Episode, Player Url] | (Film) [Title, Player Url] From 2dca366c12031c80bc87912e16475a805de34357 Mon Sep 17 00:00:00 2001 From: CakesTwix Date: Sun, 19 Feb 2023 15:48:44 +0200 Subject: [PATCH 03/11] Anitubeinua: Parse from script JSON --- .../com/lagradost/AnitubeinuaProvider.kt | 51 ++++++++++--------- .../kotlin/com/lagradost/models/PlayerJson.kt | 21 ++------ 2 files changed, 32 insertions(+), 40 deletions(-) diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt index 33b0057..8fe8c43 100644 --- a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt @@ -3,13 +3,14 @@ package com.lagradost import android.util.Log import com.lagradost.models.PlayerJson import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.LoadResponse.Companion.addActors -import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer -import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.M3u8Helper +import okio.ByteString.Companion.decodeBase64 +import okio.ByteString.Companion.decodeHex +import okio.ByteString.Companion.encodeUtf8 import org.jsoup.nodes.Element +import java.nio.charset.Charset class AnitubeinuaProvider : MainAPI() { @@ -93,10 +94,28 @@ class AnitubeinuaProvider : MainAPI() { // 12 - json with episodes // Players, Episodes, Number of episodes // TODO: Parse Episodes - val playerScriptJson = document.select("script")[12].html().substringAfterLast(".init(").substringBefore(");") - val playerNames = playerScriptJson.substringAfterLast("],") - val numberOfEpisodes = playerScriptJson.substringAfterLast(",") - Log.d("load-debug", playerScriptJson.substringAfterLast(",")) + document.select("script").map{ script -> + if (script.data().contains("RalodePlayer.init(")) { + val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") + val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",") + val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).split(",") + val numberOfEpisodesInt = playerScriptRawJson.substringAfterLast(",").toIntOrNull() + Log.d("load-debug", playerNamesArray[0].dropLast(1).drop(1)) + + // TODO: Decode string + Log.d("load-debug", decode(playerNamesArray[0])) + val playerJson = tryParseJson>>(playerEpisodesRawJson)!! + for(item in playerJson) { + for (item2 in item) { + //Log.d("load-debug", item2.name) + } + } + } + + } //.substringAfterLast(".init(").substringBefore(");") + + + var episodes: List = emptyList() @@ -138,23 +157,9 @@ class AnitubeinuaProvider : MainAPI() { .substringAfterLast("file:\'") .substringBefore("\',") - tryParseJson>(playerRawJson)?.map { dubs -> // Dubs - for(season in dubs.folder){ // Seasons - if(season.title == dataList[0]){ - for(episode in season.folder){ // Episodes - if(episode.title == dataList[1]){ - // Add as source - M3u8Helper.generateM3u8( - source = dubs.title, - streamUrl = episode.file, - referer = "https://tortuga.wtf/" - ).forEach(callback) - } - } - } - } - } + return true } + fun decode(input: String): String = java.net.URLDecoder.decode(input, "utf-16") } \ No newline at end of file diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/models/PlayerJson.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/models/PlayerJson.kt index 163dd77..c6cdcbc 100644 --- a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/models/PlayerJson.kt +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/models/PlayerJson.kt @@ -2,21 +2,8 @@ package com.lagradost.models data class PlayerJson ( - val title : String, - val folder : List -) - -data class Season ( - - val title : String, - val folder : List -) - -data class Episode ( - - val title : String, - val file : String, - val id : String, - val poster : String, - val subtitle : String, + val name : String, // Серія 0 + val code : String, // iframe block + val zid : Int, + val sid : Int ) From 73b0059e6854123ec177340cc4b00a4c3926fd5f Mon Sep 17 00:00:00 2001 From: CakesTwix Date: Sun, 19 Feb 2023 18:51:47 +0200 Subject: [PATCH 04/11] Anitubeinua: Initial series parsing Only Ashdi players Fuck the website developers --- .../com/lagradost/AnitubeinuaProvider.kt | 83 +++++++++++-------- .../lagradost/extractors/AshdiExtractor.kt | 12 +++ 2 files changed, 61 insertions(+), 34 deletions(-) create mode 100644 AnitubeinuaProvider/src/main/kotlin/com/lagradost/extractors/AshdiExtractor.kt diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt index 8fe8c43..c33cb1a 100644 --- a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt @@ -2,15 +2,13 @@ package com.lagradost import android.util.Log import com.lagradost.models.PlayerJson +import com.lagradost.extractors.AshdiExtractor import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.M3u8Helper -import okio.ByteString.Companion.decodeBase64 -import okio.ByteString.Companion.decodeHex -import okio.ByteString.Companion.encodeUtf8 +import org.jsoup.Jsoup import org.jsoup.nodes.Element -import java.nio.charset.Charset class AnitubeinuaProvider : MainAPI() { @@ -73,7 +71,7 @@ class AnitubeinuaProvider : MainAPI() { override suspend fun load(url: String): LoadResponse { val document = app.get(url).document - var someInfo = document.select("div.story_c_r")[1] + val someInfo = document.select("div.story_c_r")[1] // Parse info val title = document.selectFirst(".story_c h2")?.text()?.trim().toString() @@ -94,30 +92,40 @@ class AnitubeinuaProvider : MainAPI() { // 12 - json with episodes // Players, Episodes, Number of episodes // TODO: Parse Episodes + var episodes: List = emptyList() + document.select("script").map{ script -> if (script.data().contains("RalodePlayer.init(")) { val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",") val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).split(",") val numberOfEpisodesInt = playerScriptRawJson.substringAfterLast(",").toIntOrNull() - Log.d("load-debug", playerNamesArray[0].dropLast(1).drop(1)) - // TODO: Decode string - Log.d("load-debug", decode(playerNamesArray[0])) + // Decoded string, thanks to Secozzi + // val hexRegex = Regex("\\\\u([0-9a-fA-F]{4})") + // val decodedString = hexRegex.replace(playerNamesArray[0]) { matchResult -> + // Integer.parseInt(matchResult.groupValues[1], 16).toChar().toString() + // } + // Log.d("load-debug", decodedString) + val playerJson = tryParseJson>>(playerEpisodesRawJson)!! for(item in playerJson) { for (item2 in item) { - //Log.d("load-debug", item2.name) + if(!item2.name.contains("ПЛЕЙЛИСТ")) // UFDub player + { + episodes = episodes.plus( + Episode( + "${item2.name}, $url", + item2.name, + episode = item2.name.replace("Серія ","").toIntOrNull(), + ) + ) + } } } } - } //.substringAfterLast(".init(").substringBefore(");") - - - - - var episodes: List = emptyList() + } return newTvSeriesLoadResponse(title, url, tvType, episodes) { this.posterUrl = poster @@ -132,34 +140,41 @@ class AnitubeinuaProvider : MainAPI() { // It works when I click to view the series override suspend fun loadLinks( - data: String, // (Serisl) [Season, Episode, Player Url] | (Film) [Title, Player Url] + data: String, // Серія, url title isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { val dataList = data.split(", ") + val document = app.get(dataList[1]).document + Log.d("load-debug", dataList.toString()) - // Its film, parse one m3u8 - if(dataList.size == 2){ - val m3u8Url = app.get(dataList[1]).document.select("script").html() - .substringAfterLast("file:\"") - .substringBefore("\",") - M3u8Helper.generateM3u8( - source = dataList[0], - streamUrl = m3u8Url, - referer = "https://tortuga.wtf/" - ).forEach(callback) + document.select("script").map { script -> + Log.d("load-debug", script.data()) + if (script.data().contains("RalodePlayer.init(")) { + val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") + val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",") + Log.d("load-debug", playerScriptRawJson) - return true + val playerJson = tryParseJson>>(playerEpisodesRawJson)!! + for(item in playerJson) { + for (item2 in item) { + if(item2.name == dataList[0]){ + if(item2.code.contains("https://ashdi.vip")){ + M3u8Helper.generateM3u8( + source = dataList[0], + streamUrl = AshdiExtractor().ParseM3U8(Jsoup.parse(item2.code).select("iframe").attr("src")), + referer = "https://qeruya.cyou" + ).forEach(callback) + } + } + } + } + return true + } } - - val playerRawJson = app.get(dataList[2]).document.select("script").html() - .substringAfterLast("file:\'") - .substringBefore("\',") - - return true } - fun decode(input: String): String = java.net.URLDecoder.decode(input, "utf-16") + fun decode(input: String): String = java.net.URLDecoder.decode(input, "ISO-8859-1") } \ No newline at end of file diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/extractors/AshdiExtractor.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/extractors/AshdiExtractor.kt new file mode 100644 index 0000000..eb765fc --- /dev/null +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/extractors/AshdiExtractor.kt @@ -0,0 +1,12 @@ +package com.lagradost.extractors; + +import com.lagradost.cloudstream3.app + +class AshdiExtractor() { + suspend fun ParseM3U8(url: String): String{ + return app.get(url).document.select("script").html() + .substringAfterLast("file:\"") + .substringBefore("\",") + + } +} From 2cff8c0d1fa25ef1ba6cf319012ecd2b7a43ea95 Mon Sep 17 00:00:00 2001 From: CakesTwix Date: Sun, 19 Feb 2023 20:37:04 +0200 Subject: [PATCH 05/11] Anitubeinua: Add player name to source --- .../com/lagradost/AnitubeinuaProvider.kt | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt index c33cb1a..3b6dc32 100644 --- a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt @@ -101,13 +101,6 @@ class AnitubeinuaProvider : MainAPI() { val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).split(",") val numberOfEpisodesInt = playerScriptRawJson.substringAfterLast(",").toIntOrNull() - // Decoded string, thanks to Secozzi - // val hexRegex = Regex("\\\\u([0-9a-fA-F]{4})") - // val decodedString = hexRegex.replace(playerNamesArray[0]) { matchResult -> - // Integer.parseInt(matchResult.groupValues[1], 16).toChar().toString() - // } - // Log.d("load-debug", decodedString) - val playerJson = tryParseJson>>(playerEpisodesRawJson)!! for(item in playerJson) { for (item2 in item) { @@ -150,19 +143,19 @@ class AnitubeinuaProvider : MainAPI() { Log.d("load-debug", dataList.toString()) document.select("script").map { script -> - Log.d("load-debug", script.data()) if (script.data().contains("RalodePlayer.init(")) { val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",") - Log.d("load-debug", playerScriptRawJson) + val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).split(",") val playerJson = tryParseJson>>(playerEpisodesRawJson)!! - for(item in playerJson) { - for (item2 in item) { + playerJson.forEachIndexed { index, dub -> + Log.d("load-debug", dub.toString()) + for (item2 in dub) { if(item2.name == dataList[0]){ if(item2.code.contains("https://ashdi.vip")){ M3u8Helper.generateM3u8( - source = dataList[0], + source = decode(playerNamesArray[index]), streamUrl = AshdiExtractor().ParseM3U8(Jsoup.parse(item2.code).select("iframe").attr("src")), referer = "https://qeruya.cyou" ).forEach(callback) @@ -176,5 +169,11 @@ class AnitubeinuaProvider : MainAPI() { return true } - fun decode(input: String): String = java.net.URLDecoder.decode(input, "ISO-8859-1") + fun decode(input: String): String{ + // Decoded string, thanks to Secozzi + val hexRegex = Regex("\\\\u([0-9a-fA-F]{4})") + return hexRegex.replace(input) { matchResult -> + Integer.parseInt(matchResult.groupValues[1], 16).toChar().toString() + } + } } \ No newline at end of file From 398b7395fa9c89380ec35d63628d2f356b4fa754 Mon Sep 17 00:00:00 2001 From: CakesTwix Date: Mon, 20 Feb 2023 09:31:21 +0200 Subject: [PATCH 06/11] Anitubeinua: Fix parse player name and parse episode by index --- .../com/lagradost/AnitubeinuaProvider.kt | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt index 3b6dc32..42267e4 100644 --- a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt @@ -98,17 +98,17 @@ class AnitubeinuaProvider : MainAPI() { if (script.data().contains("RalodePlayer.init(")) { val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",") - val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).split(",") + val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).replace("\",\"", ",,,").split(",,,") val numberOfEpisodesInt = playerScriptRawJson.substringAfterLast(",").toIntOrNull() val playerJson = tryParseJson>>(playerEpisodesRawJson)!! for(item in playerJson) { - for (item2 in item) { + item.forEachIndexed { index, item2 -> if(!item2.name.contains("ПЛЕЙЛИСТ")) // UFDub player { episodes = episodes.plus( Episode( - "${item2.name}, $url", + "$index, $url", item2.name, episode = item2.name.replace("Серія ","").toIntOrNull(), ) @@ -133,7 +133,7 @@ class AnitubeinuaProvider : MainAPI() { // It works when I click to view the series override suspend fun loadLinks( - data: String, // Серія, url title + data: String, // index, url title isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit @@ -146,22 +146,18 @@ class AnitubeinuaProvider : MainAPI() { if (script.data().contains("RalodePlayer.init(")) { val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",") - val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).split(",") + val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).replace("\",\"", ",,,").split(",,,") val playerJson = tryParseJson>>(playerEpisodesRawJson)!! playerJson.forEachIndexed { index, dub -> - Log.d("load-debug", dub.toString()) - for (item2 in dub) { - if(item2.name == dataList[0]){ - if(item2.code.contains("https://ashdi.vip")){ - M3u8Helper.generateM3u8( - source = decode(playerNamesArray[index]), - streamUrl = AshdiExtractor().ParseM3U8(Jsoup.parse(item2.code).select("iframe").attr("src")), - referer = "https://qeruya.cyou" - ).forEach(callback) - } - } + if(dub[dataList[0].toInt()].code.contains("https://ashdi.vip")){ + M3u8Helper.generateM3u8( + source = decode(playerNamesArray[index]), + streamUrl = AshdiExtractor().ParseM3U8(Jsoup.parse(dub[dataList[0].toInt()].code).select("iframe").attr("src")), + referer = "https://qeruya.cyou" + ).forEach(callback) } + } return true } From 5d2f3f505f705aa613064845d85090134cf3bc1a Mon Sep 17 00:00:00 2001 From: CakesTwix Date: Mon, 20 Feb 2023 10:29:03 +0200 Subject: [PATCH 07/11] Anitubeinua: fix search --- .../src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt index 42267e4..502cd2c 100644 --- a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt @@ -54,7 +54,7 @@ class AnitubeinuaProvider : MainAPI() { override suspend fun search(query: String): List { val document = app.post( - url = "$mainUrl", + url = mainUrl, data = mapOf( "do" to "search", "subaction" to "search", @@ -62,7 +62,7 @@ class AnitubeinuaProvider : MainAPI() { ) ).document - return document.select("article.short").map { + return document.select("article.story").map { it.toSearchResponse() } } From fd9933a833e7787038b2039b2f4acd79b7c7aaf4 Mon Sep 17 00:00:00 2001 From: CakesTwix Date: Mon, 20 Feb 2023 12:34:09 +0200 Subject: [PATCH 08/11] Anitubeinua: add ajax links support --- .../com/lagradost/AnitubeinuaProvider.kt | 135 ++++++++++++------ 1 file changed, 95 insertions(+), 40 deletions(-) diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt index 502cd2c..fa42033 100644 --- a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt @@ -9,6 +9,7 @@ import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.M3u8Helper import org.jsoup.Jsoup import org.jsoup.nodes.Element +import java.util.* class AnitubeinuaProvider : MainAPI() { @@ -46,7 +47,7 @@ class AnitubeinuaProvider : MainAPI() { val href = this.selectFirst(".story_c h2 a")?.attr("href").toString() val posterUrl = mainUrl + this.selectFirst(".story_c_l span.story_post img")?.attr("src") - return newMovieSearchResponse(title, href, TvType.Movie) { + return newMovieSearchResponse(title, href, TvType.Anime) { this.posterUrl = posterUrl } @@ -89,38 +90,58 @@ class AnitubeinuaProvider : MainAPI() { } // Return to app - // 12 - json with episodes // Players, Episodes, Number of episodes - // TODO: Parse Episodes var episodes: List = emptyList() + val id = url.split("/").last().split("-").first() + val responseGet = app.get("$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}").parsedSafe()!! + if (responseGet?.success == true) { // First type players + episodes = + app.get("$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}") + .parsedSafe()?.response.let { + Jsoup.parse(it.toString()).select("div.playlists-videos li") + .mapNotNull { eps -> + val href = + "$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}" + val name = eps.text().trim() // Серія 1 + if (href.isNotEmpty()) { + Episode( + "$href, $name", // link, Серія 1 + name, + ) + } else { + null + } + } + } + } else { + document.select("script").map{ script -> + if (script.data().contains("RalodePlayer.init(")) { + val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") + val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",") + val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).replace("\",\"", ",,,").split(",,,") + val numberOfEpisodesInt = playerScriptRawJson.substringAfterLast(",").toIntOrNull() - document.select("script").map{ script -> - if (script.data().contains("RalodePlayer.init(")) { - val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") - val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",") - val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).replace("\",\"", ",,,").split(",,,") - val numberOfEpisodesInt = playerScriptRawJson.substringAfterLast(",").toIntOrNull() - - val playerJson = tryParseJson>>(playerEpisodesRawJson)!! - for(item in playerJson) { - item.forEachIndexed { index, item2 -> - if(!item2.name.contains("ПЛЕЙЛИСТ")) // UFDub player - { - episodes = episodes.plus( - Episode( - "$index, $url", - item2.name, - episode = item2.name.replace("Серія ","").toIntOrNull(), + val playerJson = tryParseJson>>(playerEpisodesRawJson)!! + for(item in playerJson) { + item.forEachIndexed { index, item2 -> + if(!item2.name.contains("ПЛЕЙЛИСТ")) // UFDub player + { + episodes = episodes.plus( + Episode( + "$index, $url", + item2.name, + episode = item2.name.replace("Серія ","").toIntOrNull(), + ) ) - ) + } } } } - } + } } - return newTvSeriesLoadResponse(title, url, tvType, episodes) { + return newTvSeriesLoadResponse(title, url, tvType, episodes.distinctBy{ it.name }) { this.posterUrl = poster this.year = year this.plot = description @@ -133,33 +154,61 @@ class AnitubeinuaProvider : MainAPI() { // It works when I click to view the series override suspend fun loadLinks( - data: String, // index, url title + data: String, // (First) link, episode name | (Two) index, url title isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { val dataList = data.split(", ") - val document = app.get(dataList[1]).document + Log.d("load-debug", dataList.toString()) + if(dataList[0].contains("https://")){ // Its First type player + // TODO: Rework parse. Need parse dub by data-id + Log.d("load-debug", "First Player pack") + val responseGet = app.get(dataList[0]).parsedSafe() // ajax link + responseGet?.response?.let { + val playersTab = Jsoup.parse(it).select("div.playlists-items")[1] + Jsoup.parse(it).select("div.playlists-videos li:contains(${dataList[1]})") + .mapNotNull { eps -> + var href = eps.attr("data-file") // m3u url + // Can be without https: + if (!href.contains("https://")) { + href = "https:$href" + } - document.select("script").map { script -> - if (script.data().contains("RalodePlayer.init(")) { - val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") - val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",") - val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).replace("\",\"", ",,,").split(",,,") - - val playerJson = tryParseJson>>(playerEpisodesRawJson)!! - playerJson.forEachIndexed { index, dub -> - if(dub[dataList[0].toInt()].code.contains("https://ashdi.vip")){ - M3u8Helper.generateM3u8( - source = decode(playerNamesArray[index]), - streamUrl = AshdiExtractor().ParseM3U8(Jsoup.parse(dub[dataList[0].toInt()].code).select("iframe").attr("src")), - referer = "https://qeruya.cyou" - ).forEach(callback) + val player_tab_id = eps.attr("data-id") // 0_0_0 + if (href.contains("https://ashdi.vip/vod")) { + // Add as source + M3u8Helper.generateM3u8( + source = playersTab.select("li[data-id=$player_tab_id]").text(), + streamUrl = AshdiExtractor().ParseM3U8(href), + referer = "https://qeruya.cyou" + ).forEach(callback) + } } + } + return true + } else { + val document = app.get(dataList[1]).document + document.select("script").map { script -> + if (script.data().contains("RalodePlayer.init(")) { + val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") + val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",") + val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).replace("\",\"", ",,,").split(",,,") + val playerJson = tryParseJson>>(playerEpisodesRawJson)!! + playerJson.forEachIndexed { index, dub -> + if(dub[dataList[0].toInt()].code.contains("https://ashdi.vip")){ + M3u8Helper.generateM3u8( + source = decode(playerNamesArray[index]), + streamUrl = AshdiExtractor().ParseM3U8(Jsoup.parse(dub[dataList[0].toInt()].code).select("iframe").attr("src")), + referer = "https://qeruya.cyou" + ).forEach(callback) + } + + } + return true } - return true } } return true @@ -172,4 +221,10 @@ class AnitubeinuaProvider : MainAPI() { Integer.parseInt(matchResult.groupValues[1], 16).toChar().toString() } } + + data class Responses( + val success: Boolean?, + val response: String?, + val message: String? + ) } \ No newline at end of file From 62ff3d72491e6e78ec43cf56723f5552862f9063 Mon Sep 17 00:00:00 2001 From: CakesTwix Date: Mon, 20 Feb 2023 13:37:40 +0200 Subject: [PATCH 09/11] Anitubeinua: rework parse for sources Fuck the website developers --- .../com/lagradost/AnitubeinuaProvider.kt | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt index fa42033..bfbddda 100644 --- a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt @@ -99,13 +99,13 @@ class AnitubeinuaProvider : MainAPI() { app.get("$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}") .parsedSafe()?.response.let { Jsoup.parse(it.toString()).select("div.playlists-videos li") - .mapNotNull { eps -> + .mapIndexedNotNull() { index, eps -> val href = "$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}" val name = eps.text().trim() // Серія 1 if (href.isNotEmpty()) { Episode( - "$href, $name", // link, Серія 1 + "$href, $index", // link, Серія 1 name, ) } else { @@ -154,7 +154,7 @@ class AnitubeinuaProvider : MainAPI() { // It works when I click to view the series override suspend fun loadLinks( - data: String, // (First) link, episode name | (Two) index, url title + data: String, // (First) link, index | (Two) index, url title isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit @@ -163,31 +163,51 @@ class AnitubeinuaProvider : MainAPI() { Log.d("load-debug", dataList.toString()) if(dataList[0].contains("https://")){ // Its First type player - // TODO: Rework parse. Need parse dub by data-id Log.d("load-debug", "First Player pack") + + // Get episodes list (as json) val responseGet = app.get(dataList[0]).parsedSafe() // ajax link responseGet?.response?.let { - val playersTab = Jsoup.parse(it).select("div.playlists-items")[1] - Jsoup.parse(it).select("div.playlists-videos li:contains(${dataList[1]})") + + // List Players + val playersTab = Jsoup.parse(it).select("div.playlists-items") + + // Parse all episodes by name + var index = 0 + var player_tab_id = "" + Jsoup.parse(it).select("div.playlists-videos li") .mapNotNull { eps -> - var href = eps.attr("data-file") // m3u url - // Can be without https: - if (!href.contains("https://")) { - href = "https:$href" + // 0 - idk, 1 - dub, 2 - player + // dataList[1] - index + Log.d("load-debug", index.toString()) + // 0_1_2 + if(player_tab_id != eps.attr("data-id")){ + index = -1 + player_tab_id = eps.attr("data-id") } - val player_tab_id = eps.attr("data-id") // 0_0_0 - if (href.contains("https://ashdi.vip/vod")) { - // Add as source - M3u8Helper.generateM3u8( - source = playersTab.select("li[data-id=$player_tab_id]").text(), - streamUrl = AshdiExtractor().ParseM3U8(href), - referer = "https://qeruya.cyou" - ).forEach(callback) + if(dataList[1].toInt() == index){ + var href = eps.attr("data-file") // m3u url + // Can be without https: + if (!href.contains("https://")) { + href = "https:$href" + } + + val dub_name = playersTab[0].select(" li[data-id=${ player_tab_id.dropLast(2) }]").text() // G&M + val player_name = playersTab[1].select(" li[data-id=$player_tab_id]").text() + + if (href.contains("https://ashdi.vip/vod")) { + // Add as source + M3u8Helper.generateM3u8( + source = "$player_name ($dub_name)", + streamUrl = AshdiExtractor().ParseM3U8(href), + referer = "https://qeruya.cyou" + ).forEach(callback) + } } + index += 1 } } - return true } else { val document = app.get(dataList[1]).document document.select("script").map { script -> @@ -207,7 +227,6 @@ class AnitubeinuaProvider : MainAPI() { } } - return true } } } From 209eeddcb72b6666fc845f4748a1f6a08dd961df Mon Sep 17 00:00:00 2001 From: CakesTwix Date: Mon, 20 Feb 2023 13:57:04 +0200 Subject: [PATCH 10/11] Anitubeinua: fix parsing, if data_id has subs --- .../kotlin/com/lagradost/AnitubeinuaProvider.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt index bfbddda..9d28fce 100644 --- a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt @@ -178,8 +178,9 @@ class AnitubeinuaProvider : MainAPI() { Jsoup.parse(it).select("div.playlists-videos li") .mapNotNull { eps -> // 0 - idk, 1 - dub, 2 - player + // if with sub + // 0 - idk 1 - dub 2 - sub or dub 3 - player // dataList[1] - index - Log.d("load-debug", index.toString()) // 0_1_2 if(player_tab_id != eps.attr("data-id")){ index = -1 @@ -193,8 +194,14 @@ class AnitubeinuaProvider : MainAPI() { href = "https:$href" } - val dub_name = playersTab[0].select(" li[data-id=${ player_tab_id.dropLast(2) }]").text() // G&M - val player_name = playersTab[1].select(" li[data-id=$player_tab_id]").text() + val dub_name = playersTab[0].select(" li[data-id=${ player_tab_id.take(3) }]").text() // G&M + var player_name = playersTab[1].select(" li[data-id=$player_tab_id]").text() // ПЛЕЄР ASHDI + + if(player_tab_id.count { it == '_' } == 3) { + player_name = + playersTab[2].selectFirst(" li[data-id=$player_tab_id]")!! + .text() // ПЛЕЄР ASHDI + } if (href.contains("https://ashdi.vip/vod")) { // Add as source From a1f35b204d22ae187021ba16e6eae1af28fbef6a Mon Sep 17 00:00:00 2001 From: CakesTwix Date: Mon, 20 Feb 2023 14:00:58 +0200 Subject: [PATCH 11/11] Anitubeinua: Ready for public testing --- .../com/lagradost/AnitubeinuaProvider.kt | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt index 9d28fce..1494e72 100644 --- a/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt +++ b/AnitubeinuaProvider/src/main/kotlin/com/lagradost/AnitubeinuaProvider.kt @@ -1,6 +1,5 @@ package com.lagradost -import android.util.Log import com.lagradost.models.PlayerJson import com.lagradost.extractors.AshdiExtractor import com.lagradost.cloudstream3.* @@ -15,7 +14,7 @@ class AnitubeinuaProvider : MainAPI() { // Basic Info override var mainUrl = "https://anitube.in.ua" - override var name = "Anitubeinua" + override var name = "Anitubeinua Beta" override val hasMainPage = true override var lang = "uk" override val hasDownloadSupport = true @@ -34,7 +33,7 @@ class AnitubeinuaProvider : MainAPI() { page: Int, request: MainPageRequest ): HomePageResponse { - var document = app.get(request.data + page).document + val document = app.get(request.data + page).document val home = document.select(".story").map { it.toSearchResponse() @@ -94,7 +93,7 @@ class AnitubeinuaProvider : MainAPI() { var episodes: List = emptyList() val id = url.split("/").last().split("-").first() val responseGet = app.get("$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}").parsedSafe()!! - if (responseGet?.success == true) { // First type players + if (responseGet.success == true) { // First type players episodes = app.get("$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}") .parsedSafe()?.response.let { @@ -118,8 +117,8 @@ class AnitubeinuaProvider : MainAPI() { if (script.data().contains("RalodePlayer.init(")) { val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",") - val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).replace("\",\"", ",,,").split(",,,") - val numberOfEpisodesInt = playerScriptRawJson.substringAfterLast(",").toIntOrNull() + // val playerNamesArray = (playerScriptRawJson.substringBefore("],") + "]").dropLast(1).drop(1).replace("\",\"", ",,,").split(",,,") + // val numberOfEpisodesInt = playerScriptRawJson.substringAfterLast(",").toIntOrNull() val playerJson = tryParseJson>>(playerEpisodesRawJson)!! for(item in playerJson) { @@ -161,20 +160,18 @@ class AnitubeinuaProvider : MainAPI() { ): Boolean { val dataList = data.split(", ") - Log.d("load-debug", dataList.toString()) if(dataList[0].contains("https://")){ // Its First type player - Log.d("load-debug", "First Player pack") // Get episodes list (as json) val responseGet = app.get(dataList[0]).parsedSafe() // ajax link - responseGet?.response?.let { + responseGet?.response?.let { it -> // List Players val playersTab = Jsoup.parse(it).select("div.playlists-items") // Parse all episodes by name var index = 0 - var player_tab_id = "" + var playerTabId = "" Jsoup.parse(it).select("div.playlists-videos li") .mapNotNull { eps -> // 0 - idk, 1 - dub, 2 - player @@ -182,9 +179,9 @@ class AnitubeinuaProvider : MainAPI() { // 0 - idk 1 - dub 2 - sub or dub 3 - player // dataList[1] - index // 0_1_2 - if(player_tab_id != eps.attr("data-id")){ + if(playerTabId != eps.attr("data-id")){ index = -1 - player_tab_id = eps.attr("data-id") + playerTabId = eps.attr("data-id") } if(dataList[1].toInt() == index){ @@ -194,19 +191,19 @@ class AnitubeinuaProvider : MainAPI() { href = "https:$href" } - val dub_name = playersTab[0].select(" li[data-id=${ player_tab_id.take(3) }]").text() // G&M - var player_name = playersTab[1].select(" li[data-id=$player_tab_id]").text() // ПЛЕЄР ASHDI + val dubName = playersTab[0].select(" li[data-id=${ playerTabId.take(3) }]").text() // G&M + var playerName = playersTab[1].select(" li[data-id=$playerTabId]").text() // ПЛЕЄР ASHDI - if(player_tab_id.count { it == '_' } == 3) { - player_name = - playersTab[2].selectFirst(" li[data-id=$player_tab_id]")!! + if(playerTabId.count { it == '_' } == 3) { + playerName = + playersTab[2].selectFirst(" li[data-id=$playerTabId]")!! .text() // ПЛЕЄР ASHDI } if (href.contains("https://ashdi.vip/vod")) { // Add as source M3u8Helper.generateM3u8( - source = "$player_name ($dub_name)", + source = "$playerName ($dubName)", streamUrl = AshdiExtractor().ParseM3U8(href), referer = "https://qeruya.cyou" ).forEach(callback) @@ -240,7 +237,7 @@ class AnitubeinuaProvider : MainAPI() { return true } - fun decode(input: String): String{ + private fun decode(input: String): String{ // Decoded string, thanks to Secozzi val hexRegex = Regex("\\\\u([0-9a-fA-F]{4})") return hexRegex.replace(input) { matchResult ->