anitubeinua: Fix posters for recommendations and reformat code

This commit is contained in:
CakesTwix 2024-04-09 11:54:59 +03:00
parent 0c99673a58
commit d2baf99a12
Signed by: CakesTwix
GPG key ID: 7B11051D5CE19825

View file

@ -12,7 +12,6 @@ import com.lagradost.models.Ajax
import com.lagradost.models.Link import com.lagradost.models.Link
import com.lagradost.models.PlayerJson import com.lagradost.models.PlayerJson
import com.lagradost.models.videoConstructor import com.lagradost.models.videoConstructor
import java.util.*
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
@ -25,17 +24,17 @@ class AnitubeinuaProvider : MainAPI() {
override var lang = "uk" override var lang = "uk"
override val hasDownloadSupport = true override val hasDownloadSupport = true
override val supportedTypes = override val supportedTypes =
setOf( setOf(
TvType.AnimeMovie, TvType.AnimeMovie,
TvType.Anime, TvType.Anime,
) )
// Sections // Sections
override val mainPage = override val mainPage =
mainPageOf( mainPageOf(
"$mainUrl/anime/page/" to "Нові", "$mainUrl/anime/page/" to "Нові",
"$mainUrl/f/sort=rating/order=desc/page/" to "Популярні", "$mainUrl/f/sort=rating/order=desc/page/" to "Популярні",
) )
private var dle_login_hash = "" private var dle_login_hash = ""
@ -49,8 +48,9 @@ class AnitubeinuaProvider : MainAPI() {
private fun Element.toSearchResponse(): AnimeSearchResponse { private fun Element.toSearchResponse(): AnimeSearchResponse {
val title = this.selectFirst(".story_c h2 a, div.text_content a")?.text()?.trim().toString() val title = this.selectFirst(".story_c h2 a, div.text_content a")?.text()?.trim().toString()
val href = this.selectFirst(".story_c h2 a, div.text_content a")?.attr("href").toString() val href = this.selectFirst(".story_c h2 a, div.text_content a")?.attr("href").toString()
val posterUrl = var posterUrl = this.selectFirst(".story_c_l span.story_post img")?.attr("src")
mainUrl + this.selectFirst(".story_c_l span.story_post img, a img")?.attr("src") // For recommendations
if (posterUrl.isNullOrEmpty()) posterUrl = this.selectFirst("a img")?.attr("data-src")
var isSub = this.select(".box .sub").isNotEmpty() var isSub = this.select(".box .sub").isNotEmpty()
var isDub = this.select(".box .ukr").isNotEmpty() var isDub = this.select(".box .ukr").isNotEmpty()
@ -59,23 +59,21 @@ class AnitubeinuaProvider : MainAPI() {
isDub = true isDub = true
} }
return newAnimeSearchResponse(title, href, TvType.Anime) { return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl this.posterUrl = mainUrl + posterUrl
addDubStatus(isDub, isSub) addDubStatus(isDub, isSub)
} }
} }
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val document = val document =
app.post( app.post(
url = mainUrl, url = mainUrl,
data = data =
mapOf( mapOf(
"do" to "search", "do" to "search",
"subaction" to "search", "subaction" to "search",
"story" to query.replace(" ", "+") "story" to query.replace(" ", "+")))
) .document
)
.document
return document.select("article.story").map { it.toSearchResponse() } return document.select("article.story").map { it.toSearchResponse() }
} }
@ -88,8 +86,7 @@ class AnitubeinuaProvider : MainAPI() {
// Parse info // Parse info
val title = document.selectFirst(".story_c h2")?.text()?.trim().toString() val title = document.selectFirst(".story_c h2")?.text()?.trim().toString()
val poster = val poster = mainUrl + document.selectFirst(".story_c_left span.story_post img")?.attr("src")
mainUrl + document.selectFirst(".story_c_left span.story_post img")?.attr("src")
val tags = someInfo.select("a[href*=/anime/]").map { it.text() } val tags = someInfo.select("a[href*=/anime/]").map { it.text() }
val year = someInfo.select("a[href*=/xfsearch/year/]").text().toIntOrNull() val year = someInfo.select("a[href*=/xfsearch/year/]").text().toIntOrNull()
@ -97,8 +94,7 @@ class AnitubeinuaProvider : MainAPI() {
val description = document.selectFirst("div.my-text")?.text()?.trim() val description = document.selectFirst("div.my-text")?.text()?.trim()
// val author = someInfo.select("strong:contains(Студія:)").next().html() // val author = someInfo.select("strong:contains(Студія:)").next().html()
val trailer = document.selectFirst(".rcol a.rollover")?.attr("href").toString() val trailer = document.selectFirst(".rcol a.rollover")?.attr("href").toString()
val rating = val rating = document.selectFirst(".lexington-box > div:last-child span")?.text().toRatingInt()
document.selectFirst(".lexington-box > div:last-child span")?.text().toRatingInt()
val recommendations = document.select(".horizontal ul li").map { it.toSearchResponse() } val recommendations = document.select(".horizontal ul li").map { it.toSearchResponse() }
@ -107,42 +103,37 @@ class AnitubeinuaProvider : MainAPI() {
val subEpisodes = mutableListOf<Episode>() val subEpisodes = mutableListOf<Episode>()
val dubEpisodes = mutableListOf<Episode>() val dubEpisodes = mutableListOf<Episode>()
val id = url.split("/").last().split("-").first() val id = url.split("/").last().split("-").first()
dle_login_hash = document.body().selectFirst("script")!!.html() dle_login_hash =
.substringAfterLast("dle_login_hash = '") document
.substringBefore("';") .body()
.selectFirst("script")!!
.html()
.substringAfterLast("dle_login_hash = '")
.substringBefore("';")
val ajax = val ajax =
fromPlaylistAjax( fromPlaylistAjax(
"$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&user_hash=$dle_login_hash" "$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&user_hash=$dle_login_hash")
)
if (!ajax.isNullOrEmpty()) { // Ajax list if (!ajax.isNullOrEmpty()) { // Ajax list
ajax ajax
.groupBy { it.name } .groupBy { it.name }
.forEach { episodes -> // Group by name .forEach { episodes -> // Group by name
episodes.value.forEach lit@{ episodes.value.forEach lit@{
// UFDub player, drop // UFDub player, drop
if (it.urls.url.contains("video.ufdub")) return@lit if (it.urls.url.contains("video.ufdub")) return@lit
if (it.urls.isDub) { if (it.urls.isDub) {
dubEpisodes.add( dubEpisodes.add(
Episode( Episode(
"${it.name}, $id, ${it.urls.isDub}", "${it.name}, $id, ${it.urls.isDub}", it.name, episode = it.numberEpisode))
it.name, } else {
episode = it.numberEpisode subEpisodes.add(
) Episode(
) "${it.name}, $id, ${it.urls.isDub}", it.name, episode = it.numberEpisode))
} else { }
subEpisodes.add(
Episode(
"${it.name}, $id, ${it.urls.isDub}",
it.name,
episode = it.numberEpisode
)
)
} }
} }
}
} else { } else {
document.select("script").map { script -> document.select("script").map { script ->
if (script.data().contains("RalodePlayer.init(")) { if (script.data().contains("RalodePlayer.init(")) {
@ -156,12 +147,11 @@ class AnitubeinuaProvider : MainAPI() {
varEpisodeNumber = episodesList.last().episodeNumber?.plus(1) varEpisodeNumber = episodesList.last().episodeNumber?.plus(1)
} }
dubEpisodes.add( dubEpisodes.add(
Episode( Episode(
"$varEpisodeNumber, $url", "$varEpisodeNumber, $url",
episode.episodeName, episode.episodeName,
episode = varEpisodeNumber, episode = varEpisodeNumber,
) ))
)
} }
} }
} }
@ -182,89 +172,84 @@ class AnitubeinuaProvider : MainAPI() {
// It works when I click to view the series // It works when I click to view the series
override suspend fun loadLinks( override suspend fun loadLinks(
data: String, // (Ajax) Name, id title, isDub | (Two) Episode name, url title data: String, // (Ajax) Name, id title, isDub | (Two) Episode name, url title
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val dataList = data.split(", ") val dataList = data.split(", ")
// Log.d("CakesTwix-Debug", data) // Log.d("CakesTwix-Debug", data)
if (dataList[1].toIntOrNull() != null) { // Its ajax list if (dataList[1].toIntOrNull() != null) { // Its ajax list
val ajax = val ajax =
fromPlaylistAjax( fromPlaylistAjax(
"$mainUrl/engine/ajax/playlists.php?news_id=${dataList[1]}&xfield=playlist&user_hash=$dle_login_hash" "$mainUrl/engine/ajax/playlists.php?news_id=${dataList[1]}&xfield=playlist&user_hash=$dle_login_hash")
)
// Filter by name and isDub // Filter by name and isDub
ajax ajax
?.filter { it.name == dataList[0] } ?.filter { it.name == dataList[0] }
?.filter { it.urls.isDub == dataList[2].toBoolean() } ?.filter { it.urls.isDub == dataList[2].toBoolean() }
?.forEach { ?.forEach {
// Get m3u8 url // Get m3u8 url
with(it) { with(it) {
when { when {
it.urls.url.contains("https://tortuga.wtf/vod/") -> { it.urls.url.contains("https://tortuga.wtf/vod/") -> {
M3u8Helper.generateM3u8( M3u8Helper.generateM3u8(
source = "${it.urls.playerName} (${it.urls.name})", source = "${it.urls.playerName} (${it.urls.name})",
streamUrl = AshdiExtractor().ParseM3U8(this.urls.url), streamUrl = AshdiExtractor().ParseM3U8(this.urls.url),
referer = "https://tortuga.wtf/" referer = "https://tortuga.wtf/")
) .forEach(callback)
.forEach(callback)
}
it.urls.url.contains("https://ashdi.vip/vod") -> {
M3u8Helper.generateM3u8(
source = "${it.urls.playerName} (${it.urls.name})",
streamUrl = AshdiExtractor().ParseM3U8(this.urls.url),
referer = "https://qeruya.cyou"
)
.forEach(callback)
}
it.urls.url.contains("https://www.udrop.com") -> {
callback.invoke(
ExtractorLink(
this.urls.url,
name = "${it.urls.playerName} (${it.urls.name})",
this.urls.url,
"",
0,
isM3u8 = false,
)
)
}
it.urls.url.contains("https://csst.online/embed/") || it.urls.url.contains("https://monstro.site/embed/") -> {
csstExtractor().ParseUrl(it.urls.url).split(",").forEach { csstUrl
->
callback.invoke(
ExtractorLink(
this.urls.url,
name = "${it.urls.playerName} (${it.urls.name}) ${csstUrl.substringBefore("]").drop(1)}",
csstUrl.substringAfter("]"),
"",
0,
isM3u8 = false,
)
)
} }
} it.urls.url.contains("https://ashdi.vip/vod") -> {
it.urls.url.contains("https://www.mp4upload.com/") -> { M3u8Helper.generateM3u8(
Mp4Upload().getUrl(it.urls.url)?.forEach { extlink -> source = "${it.urls.playerName} (${it.urls.name})",
callback.invoke( streamUrl = AshdiExtractor().ParseM3U8(this.urls.url),
ExtractorLink( referer = "https://qeruya.cyou")
extlink.source, .forEach(callback)
"${it.urls.playerName} (${it.urls.name})",
extlink.url,
extlink.referer,
extlink.quality,
extlink.type,
extlink.headers,
)
)
} }
it.urls.url.contains("https://www.udrop.com") -> {
callback.invoke(
ExtractorLink(
this.urls.url,
name = "${it.urls.playerName} (${it.urls.name})",
this.urls.url,
"",
0,
isM3u8 = false,
))
}
it.urls.url.contains("https://csst.online/embed/") ||
it.urls.url.contains("https://monstro.site/embed/") -> {
csstExtractor().ParseUrl(it.urls.url).split(",").forEach { csstUrl ->
callback.invoke(
ExtractorLink(
this.urls.url,
name =
"${it.urls.playerName} (${it.urls.name}) ${csstUrl.substringBefore("]").drop(1)}",
csstUrl.substringAfter("]"),
"",
0,
isM3u8 = false,
))
}
}
it.urls.url.contains("https://www.mp4upload.com/") -> {
Mp4Upload().getUrl(it.urls.url)?.forEach { extlink ->
callback.invoke(
ExtractorLink(
extlink.source,
"${it.urls.playerName} (${it.urls.name})",
extlink.url,
extlink.referer,
extlink.quality,
extlink.type,
extlink.headers,
))
}
}
else -> {}
} }
else -> {}
} }
} }
}
} else { } else {
val document = app.get(dataList[1]).document val document = app.get(dataList[1]).document
document.select("script").map { script -> document.select("script").map { script ->
@ -286,59 +271,55 @@ class AnitubeinuaProvider : MainAPI() {
when { when {
contains("https://tortuga.wtf/vod/") -> { contains("https://tortuga.wtf/vod/") -> {
M3u8Helper.generateM3u8( M3u8Helper.generateM3u8(
source = dub.playerName, source = dub.playerName,
streamUrl = AshdiExtractor().ParseM3U8(this), streamUrl = AshdiExtractor().ParseM3U8(this),
referer = "https://tortuga.wtf/" referer = "https://tortuga.wtf/")
) .forEach(callback)
.forEach(callback)
} }
contains("https://ashdi.vip/vod") -> { contains("https://ashdi.vip/vod") -> {
M3u8Helper.generateM3u8( M3u8Helper.generateM3u8(
source = dub.playerName, source = dub.playerName,
streamUrl = AshdiExtractor().ParseM3U8(this), streamUrl = AshdiExtractor().ParseM3U8(this),
referer = "https://qeruya.cyou" referer = "https://qeruya.cyou")
) .forEach(callback)
.forEach(callback)
} }
contains("https://www.udrop.com") -> { contains("https://www.udrop.com") -> {
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
dub.playerName, dub.playerName,
name = dub.playerName, name = dub.playerName,
this, this,
"", "",
0, 0,
isM3u8 = false, isM3u8 = false,
) ))
)
} }
contains("https://monstro.site/embed/") || contains("https://csst.online/embed/") -> { contains("https://monstro.site/embed/") ||
contains("https://csst.online/embed/") -> {
csstExtractor().ParseUrl(this).split(",").forEach { csstExtractor().ParseUrl(this).split(",").forEach {
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
dub.playerName, dub.playerName,
name = "${dub.playerName.replace("\"", "")} ${it.substringBefore("]").drop(1)}", name =
it.substringAfter("]"), "${dub.playerName.replace("\"", "")} ${it.substringBefore("]").drop(1)}",
"", it.substringAfter("]"),
0, "",
isM3u8 = false 0,
) isM3u8 = false))
)
} }
} }
contains("https://www.mp4upload.com/") -> { contains("https://www.mp4upload.com/") -> {
Mp4Upload().getUrl(this)?.forEach { extlink -> Mp4Upload().getUrl(this)?.forEach { extlink ->
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
extlink.source, extlink.source,
dub.playerName, dub.playerName,
extlink.url, extlink.url,
extlink.referer, extlink.referer,
extlink.quality, extlink.quality,
extlink.type, extlink.type,
extlink.headers, extlink.headers,
) ))
)
} }
} }
else -> {} else -> {}
@ -433,17 +414,15 @@ class AnitubeinuaProvider : MainAPI() {
} }
returnEpisodes.add( returnEpisodes.add(
Ajax( Ajax(
episodeId, episodeId,
element.text(), element.text(),
Link( Link(
isDub, isDub,
url, url,
audio.toString(), audio.toString(),
playerName, playerName,
) )))
)
)
} }
return returnEpisodes.toList() return returnEpisodes.toList()
@ -451,14 +430,13 @@ class AnitubeinuaProvider : MainAPI() {
private fun fromVideoContructor(script: Element): List<videoConstructor> { private fun fromVideoContructor(script: Element): List<videoConstructor> {
val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");") val playerScriptRawJson = script.data().substringAfterLast(".init(").substringBefore(");")
val playerEpisodesRawJson = val playerEpisodesRawJson = playerScriptRawJson.substringAfter("],").substringBeforeLast(",")
playerScriptRawJson.substringAfter("],").substringBeforeLast(",")
val playerNamesArray = val playerNamesArray =
(playerScriptRawJson.substringBefore("],") + "]") (playerScriptRawJson.substringBefore("],") + "]")
.dropLast(1) .dropLast(1)
.drop(1) .drop(1)
.replace("\",\"", ",,,") .replace("\",\"", ",,,")
.split(",,,") .split(",,,")
// val numberOfEpisodesInt = playerScriptRawJson.substringAfterLast(",").toIntOrNull() // val numberOfEpisodesInt = playerScriptRawJson.substringAfterLast(",").toIntOrNull()
val jsonEpisodes = tryParseJson<List<List<PlayerJson>>>(playerEpisodesRawJson)!! val jsonEpisodes = tryParseJson<List<List<PlayerJson>>>(playerEpisodesRawJson)!!
@ -468,13 +446,11 @@ class AnitubeinuaProvider : MainAPI() {
val playerName = decode(playerNamesArray[index]) val playerName = decode(playerNamesArray[index])
episode.forEach { episode.forEach {
episodes.add( episodes.add(
videoConstructor( videoConstructor(
playerName, playerName,
it.name, it.name,
extractIntFromString(it.name), extractIntFromString(it.name),
Jsoup.parse(it.code).select("iframe").attr("src") Jsoup.parse(it.code).select("iframe").attr("src")))
)
)
// Log.d("load-debug", "$playerName ${it.name}") // Log.d("load-debug", "$playerName ${it.name}")
} }
} }