diff --git a/Kissasian/build.gradle.kts b/Kissasian/build.gradle.kts
new file mode 100644
index 00000000..1a200aab
--- /dev/null
+++ b/Kissasian/build.gradle.kts
@@ -0,0 +1,23 @@
+// use an integer for version numbers
+version = 1
+
+
+cloudstream {
+ language = "en"
+ // 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 = 1 // will be 3 if unspecified
+ tvTypes = listOf("AsianDrama",)
+
+ iconUrl = "https://www.google.com/s2/favicons?domain=kissasian.pe&sz=%size%"
+}
\ No newline at end of file
diff --git a/Kissasian/src/main/AndroidManifest.xml b/Kissasian/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..c98063f8
--- /dev/null
+++ b/Kissasian/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Kissasian/src/main/kotlin/com/hexated/Kissasian.kt b/Kissasian/src/main/kotlin/com/hexated/Kissasian.kt
new file mode 100644
index 00000000..0a7fe320
--- /dev/null
+++ b/Kissasian/src/main/kotlin/com/hexated/Kissasian.kt
@@ -0,0 +1,138 @@
+package com.hexated
+
+import com.lagradost.cloudstream3.*
+import com.lagradost.cloudstream3.mvvm.safeApiCall
+import com.lagradost.cloudstream3.utils.ExtractorLink
+import com.lagradost.cloudstream3.utils.loadExtractor
+import org.jsoup.nodes.Element
+
+class Kissasian : MainAPI() {
+ override var mainUrl = "https://kissasian.pe"
+ override var name = "Kissasian"
+ override val hasMainPage = true
+ override val hasDownloadSupport = true
+ override val supportedTypes = setOf(TvType.AsianDrama)
+
+ companion object {
+ fun getStatus(t: String?): ShowStatus {
+ return when (t) {
+ "Completed" -> ShowStatus.Completed
+ "Ongoing" -> ShowStatus.Ongoing
+ else -> ShowStatus.Completed
+ }
+ }
+ }
+
+ override val mainPage = mainPageOf(
+ "drama-list/ongoing.html?page=" to "Drama Ongoing",
+ "drama-list/completed.html?page=" to "Drama Completed",
+ "genre/variety/?page=" to "Variety Show",
+ "genre/romance/?page=" to "Romance",
+ "genre/action/?page=" to "Action",
+ "genre/mystery/?page=" to "Mystery",
+ )
+
+ override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
+ val document = app.get("$mainUrl/${request.data}$page").document
+ val home = document.select("div.list-drama div.item").mapNotNull {
+ it.toSearchResult()
+ }
+ return newHomePageResponse(request.name, home)
+ }
+
+ private fun Element.toSearchResult(): SearchResponse? {
+ val href = fixUrl(this.selectFirst("a")?.attr("href") ?: return null)
+ val title = this.selectFirst("span.title")?.text()?.trim() ?: return null
+ val posterUrl = fixUrlNull(this.selectFirst("div.pic img")?.attr("src"))
+
+ return newTvSeriesSearchResponse(title, href, TvType.AsianDrama) {
+ this.posterUrl = posterUrl
+ }
+ }
+
+ override suspend fun search(query: String): List {
+ val document = app.get("$mainUrl/search.html?keyword=$query").document
+ return document.select("div.list-drama div.item").mapNotNull {
+ it.toSearchResult()
+ }
+ }
+
+ override suspend fun load(url: String): LoadResponse? {
+ val document = app.get(url).document
+
+ val title = document.selectFirst("div.barContentInfo a")?.text()?.trim() ?: return null
+ val poster = fixUrlNull(document.selectFirst("div.barContentInfo img")?.attr("src"))
+ val tags = document.select("div.barContentInfo p:contains(Genres:) a").map { it.text().removePrefix(",").trim() }
+
+ val year = document.selectFirst("div.barContentInfo p.type.Releasea")?.text()?.trim()?.toIntOrNull()
+ val status = getStatus(document.selectFirst("div.barContentInfo p:contains(Status:)")?.ownText()?.trim())
+ val description = document.selectFirst("div.barContentInfo p.des")?.nextElementSiblings()?.select("p")?.text()
+
+ val episodes = document.select("ul.listing li").map {
+ val name = it.selectFirst("a")?.attr("title")
+ val link = fixUrlNull(it.selectFirst("a")?.attr("href"))
+ val epNum = Regex("Episode\\s([0-9]+)").find("$name")?.groupValues?.getOrNull(1)?.toIntOrNull()
+ newEpisode(link) {
+ this.name = name
+ this.episode = epNum
+ }
+ }.reversed()
+
+ if (episodes.size == 1) {
+ return newMovieLoadResponse(title, url, TvType.Movie, episodes[0].data) {
+ posterUrl = poster
+ this.year = year
+ plot = description
+ this.tags = tags
+ }
+ } else {
+ return newTvSeriesLoadResponse(title, url, TvType.AsianDrama, episodes = episodes) {
+ posterUrl = poster
+ this.year = year
+ showStatus = status
+ plot = description
+ this.tags = tags
+ }
+ }
+ }
+
+ private suspend fun invokeDembedSource(
+ url: String,
+ subtitleCallback: (SubtitleFile) -> Unit,
+ callback: (ExtractorLink) -> Unit
+ ) {
+ val document = app.get(url).document
+ document.select("ul.list-server-items li").map {
+ val iframe = it.attr("data-video").substringBefore("=http")
+ loadExtractor(iframe, "$mainUrl/", subtitleCallback, callback)
+ }
+ }
+
+ override suspend fun loadLinks(
+ data: String,
+ isCasting: Boolean,
+ subtitleCallback: (SubtitleFile) -> Unit,
+ callback: (ExtractorLink) -> Unit
+ ): Boolean {
+
+ val document = app.get(data).document
+
+ document.select("select#selectServer option").apmap {
+ safeApiCall {
+ val iframe = fixUrl(it.attr("value"))
+
+ when {
+ iframe.startsWith("https://dembed2.com") -> invokeDembedSource(
+ iframe,
+ subtitleCallback,
+ callback
+ )
+ else -> loadExtractor(iframe, "$mainUrl/", subtitleCallback, callback)
+ }
+ }
+ }
+
+ return true
+ }
+
+}
diff --git a/Kissasian/src/main/kotlin/com/hexated/KissasianPlugin.kt b/Kissasian/src/main/kotlin/com/hexated/KissasianPlugin.kt
new file mode 100644
index 00000000..932e9fc8
--- /dev/null
+++ b/Kissasian/src/main/kotlin/com/hexated/KissasianPlugin.kt
@@ -0,0 +1,14 @@
+
+package com.hexated
+
+import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
+import com.lagradost.cloudstream3.plugins.Plugin
+import android.content.Context
+
+@CloudstreamPlugin
+class KissasianPlugin: Plugin() {
+ override fun load(context: Context) {
+ // All providers should be added in this manner. Please don't edit the providers list directly.
+ registerMainAPI(Kissasian())
+ }
+}
\ No newline at end of file
diff --git a/LayarKacaProvider/build.gradle.kts b/LayarKacaProvider/build.gradle.kts
index 27c96ea7..38955c5b 100644
--- a/LayarKacaProvider/build.gradle.kts
+++ b/LayarKacaProvider/build.gradle.kts
@@ -1,5 +1,5 @@
// use an integer for version numbers
-version = 2
+version = 3
cloudstream {
diff --git a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt
index 09b37f2c..bf8f84b8 100644
--- a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt
+++ b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt
@@ -9,7 +9,7 @@ import org.jsoup.Jsoup
import org.jsoup.nodes.Element
class LayarKacaProvider : MainAPI() {
- override var mainUrl = "https://lk21.homes"
+ override var mainUrl = "https://lk21.cloud"
override var name = "LayarKaca"
override val hasMainPage = true
override var lang = "id"
diff --git a/Movierulzhd/build.gradle.kts b/Movierulzhd/build.gradle.kts
index f5279376..b65d8692 100644
--- a/Movierulzhd/build.gradle.kts
+++ b/Movierulzhd/build.gradle.kts
@@ -1,5 +1,5 @@
// use an integer for version numbers
-version = 3
+version = 4
cloudstream {
diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt
index 526fad8b..917cfd08 100644
--- a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt
+++ b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt
@@ -175,14 +175,16 @@ class Movierulzhd : MainAPI() {
referer = url,
).text
val mapped = urltext.let { AppUtils.parseJson(it) }
- val testurl = app.get(mapped.streamData.file, headers = headers).text
- if (urltext.contains("m3u8") && testurl.contains("EXTM3U"))
- M3u8Helper.generateM3u8(
+ callback.invoke(
+ ExtractorLink(
+ name,
name,
mapped.streamData.file,
url,
+ Qualities.Unknown.value,
headers = headers
- ).forEach(callback)
+ )
+ )
}
override suspend fun loadLinks(