added Aniworld

This commit is contained in:
hexated 2023-06-15 23:26:36 +07:00
parent 2b3fb0e8e0
commit c20e8011da
4 changed files with 230 additions and 0 deletions

27
Aniworld/build.gradle.kts Normal file
View file

@ -0,0 +1,27 @@
// use an integer for version numbers
version = 1
cloudstream {
language = "de"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"
authors = listOf("Hexated")
/**
* Status int as the following:
* 0: Down
* 1: Ok
* 2: Slow
* 3: Beta only
* */
status = 0 // will be 3 if unspecified
tvTypes = listOf(
"AnimeMovie",
"Anime",
"OVA",
)
iconUrl = "https://www.google.com/s2/favicons?domain=aniworld.to&sz=%size%"
}

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.hexated"/>

View file

@ -0,0 +1,186 @@
package com.hexated
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
import com.lagradost.cloudstream3.extractors.Voe
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.nodes.Element
class Aniworld : MainAPI() {
override var mainUrl = "https://aniworld.to"
override var name = "Aniworld"
override val hasMainPage = true
override var lang = "de"
override val hasDownloadSupport = true
override val supportedTypes = setOf(
TvType.Anime,
TvType.AnimeMovie,
TvType.OVA
)
companion object {
fun getType(t: String): TvType {
return when {
t.contains("Anime Ova") -> TvType.OVA
t.contains("Anime Movie") -> TvType.AnimeMovie
else -> TvType.Anime
}
}
fun getStatus(t: String): ShowStatus {
return when {
t.contains("/complete", true) -> ShowStatus.Completed
t.contains("/running", true) -> ShowStatus.Ongoing
else -> ShowStatus.Completed
}
}
}
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val document = app.get(mainUrl).document
val item = arrayListOf<HomePageList>()
document.select("div.carousel").map { ele ->
val header = ele.selectFirst("h2")?.text() ?: return@map
val home = ele.select("div.coverListItem").mapNotNull {
it.toSearchResult()
}
if (home.isNotEmpty()) item.add(HomePageList(header, home))
}
return HomePageResponse(item)
}
override suspend fun search(query: String): List<SearchResponse> {
val json = app.post(
"$mainUrl/ajax/search",
data = mapOf("keyword" to query),
referer = "$mainUrl/search",
headers = mapOf(
"x-requested-with" to "XMLHttpRequest"
)
)
return tryParseJson<List<AnimeSearch>>(json.text)?.filter {
!it.link.contains("episode-") && it.link.contains(
"/stream"
)
}?.map {
newAnimeSearchResponse(
it.title?.replace(Regex("</?em>"), "") ?: "",
fixUrl(it.link),
TvType.Anime
) {
}
} ?: throw ErrorLoadingException()
}
override suspend fun load(url: String): LoadResponse? {
val document = app.get(url).document
val title = document.selectFirst("div.series-title span")?.text() ?: return null
val poster = fixUrlNull(document.selectFirst("div.seriesCoverBox img")?.attr("data-src"))
val tags = document.select("div.genres li a").map { it.text() }
val year = document.selectFirst("span[itemprop=startDate] a")?.text()?.toIntOrNull()
val description = document.select("p.seri_des").text()
val actor =
document.select("li:contains(Schauspieler:) ul li a").map { it.select("span").text() }
val episodes = document.select("div#stream > ul:nth-child(4) li").mapNotNull { eps ->
Episode(
fixUrl(eps.selectFirst("a")?.attr("href") ?: return@mapNotNull null),
episode = eps.selectFirst("a")?.text()?.toIntOrNull()
)
}
return newAnimeLoadResponse(
title,
url,
TvType.Anime
) {
engName = title
posterUrl = poster
this.year = year
addEpisodes(
DubStatus.Subbed,
episodes
)
addActors(actor)
plot = description
this.tags = tags
}
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val document = app.get(data).document
document.select("div.hosterSiteVideo ul li").map {
Triple(
it.attr("data-lang-key"),
it.attr("data-link-target"),
it.select("h4").text()
)
}.filter {
it.third == "VOE"
}.apmap {
val redirectUrl = app.get(fixUrl(it.second)).url
loadExtractor(redirectUrl, data, subtitleCallback) { link ->
val name = "${link.name} [${it.first.getLanguage()}]"
callback.invoke(
ExtractorLink(
name,
name,
link.url,
link.referer,
link.quality,
link.isM3u8,
link.headers,
link.extractorData
)
)
}
}
return true
}
private fun Element.toSearchResult(): AnimeSearchResponse? {
val href = fixUrlNull(this.selectFirst("a")?.attr("href")) ?: return null
val title = this.selectFirst("h3")?.text() ?: return null
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("data-src"))
return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl
}
}
private fun String.getLanguage() : String {
return when(this) {
"1" -> "Deutsch"
"2" -> "Untertitel Deutsch"
"3" -> "Untertitel Englisch"
else -> {
""
}
}
}
private data class AnimeSearch(
@JsonProperty("link") val link: String,
@JsonProperty("title") val title: String? = null,
)
}
class Urochsunloath : Voe() {
override var mainUrl = "https://urochsunloath.com"
}

View file

@ -0,0 +1,15 @@
package com.hexated
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
import com.lagradost.cloudstream3.plugins.Plugin
import android.content.Context
@CloudstreamPlugin
class AniworldPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(Aniworld())
registerExtractorAPI(Urochsunloath())
}
}